PSI sics-cvs-psi_pre-ansto
This commit is contained in:
135
doc/programmer/task.tex
Normal file
135
doc/programmer/task.tex
Normal file
@@ -0,0 +1,135 @@
|
||||
|
||||
\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}
|
||||
|
||||
Reference in New Issue
Block a user