136 lines
6.0 KiB
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}
|
|
|