Files
sics/doc/programmer/task.tex

136 lines
6.0 KiB
TeX

\subsection{The Task Switcher}
This is a portable task switching module. It effectively implments a form of
cooperative multitasking. A task in this context is a function of type
TaskFunc which defines the task. The task function looks like this: \\
\centerline{int (*TaskFunc)(void *pData)}\\
pData is a pointer to a user defined data structure which should contain the
data the task is going to need in order to do its job. This function returns
1 if it shall continue, or 0 if it is finally ended and should be deleted from
the list of tasks. Please note, that the whole task switcher is blocked when
a task executes a very lengthy operation. In such cases a task function
should call either TaksWait or TaskYield at apropriate
places in the code in order to give other tasks a chance to execute.
This module now keeps a list of such tasks and calls the task functions one
after another. Actually, the tasks are kept in a special data structure in a
doubly linked list. When the end of this list has been reached, the code
jumps to the list head automatically. The data structure for each task looks
like this:
\begin{verbatim}
typedef struct __TaskHead {
long lID;
int iStatus;
long lWait;
TaskFunc pRun;
SignalFunc pSignal;
void *pData;
TaskKillFunc pKill;
pTaskHead pNext;
pTaskHead pPrevious;
} TaskHead;
\end{verbatim}
The fields have the following meanings: \begin{description}
\item[lID] A unique task ID.
\item[iStatus] is a status flag. A task can be READY or WAITING for another task
to finish.
\item[lWait] If the task is in wait state, lWait denotes the task ID to wait
for.
\item[pRun] is the tasks task function.
\item[pSignal] is the tasks signal function. This implements some form of
inter task communication. A signal function looks like this:\\
\centerline{typedef void (*SignalFunc)(void *pUser,int iSignal, void
*pSigData);}\\
pUser is a pointer to the task data structure, iSignal is the ID of a signal
sent. It is the applications job to define these signal codes. pSigData is a
pointer to a signal data structure. Again it is the applications job to
define this data structure for each signal.
\item[pData] is the tasks data structure. It will be passed into each call
to the task and signal function.
\item[pKill] is a pointer to a function capable of deleting the task data
structure. This function will be automatically called when the task ends.
\item[pNext, pPrevious] are pointers which maintain the doubly linked list
of tasks.
\end{description}
The other data structure used in the task switching module is the task
managers data structure. It looks like this:
\begin{verbatim}
typedef struct __TaskMan {
int iID;
int iStop;
pTaskHead pCurrent;
pTaskHead pHead;
} TaskMan;
\end{verbatim}
The fields:
\begin{description}
\item[iID] a ID to characterize the task manager data structure. Will be
used to test if this structure has been corrupted or the user passed in
some shit.
\item[iStop] is used for stopping the task switcher.
\item[pCurrent] denotes the current task executing.
\item[pHead] define the head of the task list.
\end{description}
In order to use this module it is needed to provide these items for each
task:\begin{itemize}
\item A task data structure.
\item A data structure removal function if applicable.
\item A task function.
\item A signal function, if the task is going to react on signals.
\end{itemize}
Interaction with the task switching module happens through the functions
defined below. All functions return 0 on failure and 1 on success if not
sated otherwise. For encapsulation, the following pointers are defined:
\begin{verbatim}
typedef struct __TaskHead *pTaskHead;
typedef struct __TaskMan *pTaskMan;
\end{verbatim}
\begin{description}
\item[int TaskerInit(pTaskMan *self)]
Initalises a Task Manager.
\item[int TaskerDelete(pTaskMan *self)]
Stops all running tasks and clears all data structures associated with
tasks and the TaskManager.
\item[long TaskRegister(pTaskMan self, TaskFunc pTaskRun,
SignalFunc pSignalFunc, \\
TaskKillFunc pKillFunc,
void *pData,
int iPriority)]
This call enter a new task into the system. The caller has to
specify:
\begin{itemize}
\item a TaskFunction [Required]
\item a SignalFunction [Optional, can be NULL]
\item a KillFunction for task private data.
[Optional, can be NULL]
\item a pointer to task private data
[Optional, can be NULL]
\item a priority for this task. This is currently unused.
\end{itemize}
On Success a positive value denoting the ID of the task is returned.
On error a negative value is returned.
\item[int TaskSchedule(pTaskMan self)]
Starts task switching.
\item[int TaskStop(pTaskMan self)]
Interrupts task switching all together
\item[int TaskContinue(pTaskMan self)]
Continues an task switching session interrupted by TaskStop. After this
the apopriate TaskYield, TaskSchedule or whatever has to be called.
\item[int TaskWait(pTaskMan self, long lID)]
Waits until the task specified by lID has finished. lID is obtained from
a call to TaskRegister.
\item[int TaskYield(pTaskman self)] does one cycle through the main loop.
Should be called by tasks performing lengthy operations now and then in
order to allow other tasks to execute. This is not yet implemented.
\item[int TaskSignal(pTaskMan self, int iSignal, void *pSigData)]
Invokes each Task's signal function with parameters iSignal and
pSigData.
\end{description}