861 lines
21 KiB
C
861 lines
21 KiB
C
/* ===========================================================================
|
|
File: TASKER.C
|
|
|
|
Notes: Cooperative multitasking
|
|
|
|
Author: G Robert Liddon @ 73b
|
|
|
|
Created: Wednesday 27th March 1996
|
|
|
|
Copyright (C) 1996 DCI Ltd All rights reserved.
|
|
============================================================================ */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Standard Lib Includes
|
|
--------------------- */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Glib Includes
|
|
------------- */
|
|
#include "tasker.h"
|
|
#include "gsys.h"
|
|
#include "gdebug.h"
|
|
|
|
#include "gtimsys.h"
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
My Includes
|
|
----------- */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Defines
|
|
------- */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function Prototypes
|
|
------------------- */
|
|
static void ReturnToSchedulerIfCurrentTask(TASK *T);
|
|
static void ExecuteTask(TASK *T);
|
|
static void AddToList(TASK **Head,TASK *ThisObj);
|
|
static void DetachFromList(TASK **Head,TASK *ThisObj);
|
|
static void LoTskKill(TASK *T);
|
|
static void DoEpi(TASK * T);
|
|
static void DoPro(TASK * T);
|
|
static void ExtraMarkStack(u32 * Stack,int SizeLongs);
|
|
static int CheckExtraStack(u32 * Stack,int LongsToCheck);
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Defines
|
|
------- */
|
|
#define NUM_OF_TASKS 100
|
|
#define DEFAULT_XTRA_PRO_STACK_LONGS 1024
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Variables
|
|
--------- */
|
|
static TASK * ActiveTasks;
|
|
static TASK * CurrentTask;
|
|
static TASK * T;
|
|
|
|
static U32 MemTypeForTasker;
|
|
static jmp_buf SchEnv; /* The Scheduler's enviroment */
|
|
static U32 ExecId;
|
|
static U32 ExecMask;
|
|
static int TasksActive;
|
|
|
|
|
|
/* Vars for epi pro stuff
|
|
---------------------- */
|
|
static TSK_CBACK EpiFunc; /* Func to call before execing task of correct class */
|
|
static TSK_CBACK ProFunc; /* Func to call after execing task of correct class */
|
|
static U32 EpiProId;
|
|
static U32 EpiProMask;
|
|
|
|
static DOTSK_CBACK DoTasksPrologue;
|
|
static DOTSK_CBACK DoTasksEpilogue;
|
|
|
|
/* Vars for Xtra Stack Protection
|
|
------------------------------ */
|
|
static TSK_CBACK StackFloodCallback;
|
|
static BOOL ExtraStackProtection;
|
|
static int ExtraStackSizeLongs;
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: static void DoEpi(TASK * T)
|
|
Purpose: Do epilogue route if appropriate
|
|
--------------------------------------------------------------------------- */
|
|
static void DoEpi(TASK * T)
|
|
{
|
|
if (EpiFunc)
|
|
if ((T->Id&EpiProMask)==EpiProId)
|
|
EpiFunc(T);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: static void DoPro(TASK * T)
|
|
Purpose: Do prologue route if appropriate
|
|
--------------------------------------------------------------------------- */
|
|
static void DoPro(TASK * T)
|
|
{
|
|
if (ProFunc)
|
|
if ((T->Id&EpiProMask)==EpiProId)
|
|
ProFunc(T);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: BOOL TSK_OpenModule(U32 MemType)
|
|
|
|
Purpose: Init the tasker module
|
|
|
|
Params: MemType = Mem tasker uses for workspace
|
|
|
|
Returns: FALSE if an error
|
|
--------------------------------------------------------------------------- */
|
|
BOOL TSK_OpenModule(U32 MemType)
|
|
{
|
|
|
|
TasksActive=0;
|
|
ActiveTasks=NULL;
|
|
MemTypeForTasker=MemType;
|
|
CurrentTask=NULL;
|
|
TSK_ClearExecFilter();
|
|
TSK_ClearEpiProFilter();
|
|
TSK_SetDoTasksEpilogue(NULL);
|
|
TSK_SetDoTasksPrologue(NULL);
|
|
TSK_SetExtraStackProtection(FALSE);
|
|
TSK_SetStackFloodCallback(NULL);
|
|
TSK_SetExtraStackSize(DEFAULT_XTRA_PRO_STACK_LONGS*sizeof(u32));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: TASK * TSK_AddTask(U32 Id,void (*Main)(TASK *T))
|
|
|
|
Purpose: Add a task to the list of those to do
|
|
|
|
Returns: -> to task to run
|
|
NULL if no tasks available
|
|
--------------------------------------------------------------------------- */
|
|
TASK * TSK_AddTask(U32 Id,void (*Main)(TASK *T),int StackSize,int DataSize)
|
|
{
|
|
TASK * RetTask;
|
|
MHANDLE hndTask;
|
|
|
|
GAL_STRUCT G[4];
|
|
|
|
G[0].OriginalSize=sizeof(TASK);
|
|
G[1].OriginalSize=DataSize;
|
|
|
|
if (ExtraStackProtection)
|
|
G[2].OriginalSize=StackSize+ExtraStackSizeLongs*sizeof(u32);
|
|
else
|
|
G[2].OriginalSize=StackSize;
|
|
|
|
|
|
G[3].OriginalSize=-1;
|
|
|
|
hndTask=GAL_AllocMultiStruct(G,MemTypeForTasker,"TASK");
|
|
|
|
if (hndTask==NULL_HANDLE)
|
|
return(NULL);
|
|
|
|
RetTask=GAL_Lock(hndTask);
|
|
|
|
if (RetTask)
|
|
{
|
|
RetTask->Id = Id;
|
|
|
|
RetTask->fToInit=1;
|
|
RetTask->fToDie=0;
|
|
RetTask->fKillable=1;
|
|
RetTask->fActive=1;
|
|
|
|
RetTask->Main=Main;
|
|
|
|
RetTask->hndTask=hndTask;
|
|
|
|
RetTask->Stack=(void *)(((U32) RetTask)+G[2].Offset);
|
|
RetTask->StackSize=G[3].Offset-G[2].Offset;
|
|
|
|
if (DataSize)
|
|
RetTask->Data=(void *)(((U32) RetTask)+G[1].Offset);
|
|
else
|
|
RetTask->Data=NULL;
|
|
|
|
RetTask->SleepTime=1;
|
|
RetTask->fXtraStack=ExtraStackProtection;
|
|
RetTask->XtraLongs=ExtraStackSizeLongs;
|
|
|
|
if (RetTask->fXtraStack)
|
|
ExtraMarkStack(RetTask->Stack,RetTask->StackSize/sizeof(u32));
|
|
else
|
|
GSYS_MarkStack(RetTask->Stack,RetTask->StackSize);
|
|
|
|
/* if a task running then add as next in list or at beggining */
|
|
|
|
if (CurrentTask)
|
|
{
|
|
AddToList(&CurrentTask->Next,RetTask);
|
|
RetTask->Prev=CurrentTask;
|
|
}
|
|
else
|
|
AddToList(&ActiveTasks,RetTask);
|
|
|
|
TasksActive++;
|
|
|
|
}
|
|
|
|
return RetTask;
|
|
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void TSK_DoTasks(void)
|
|
Purpose: Run All the tasks
|
|
--------------------------------------------------------------------------- */
|
|
void TSK_DoTasks(void)
|
|
{
|
|
T=ActiveTasks;
|
|
|
|
if (DoTasksPrologue)
|
|
DoTasksPrologue();
|
|
|
|
while (T)
|
|
{
|
|
if (T->fActive && (T->Id&ExecMask)==ExecId)
|
|
{
|
|
T->SleepTime--;
|
|
|
|
if (!T->SleepTime)
|
|
{
|
|
|
|
if (!setjmp(SchEnv))
|
|
{
|
|
|
|
/* See if this task needs initing or not */
|
|
CurrentTask=T;
|
|
|
|
DoPro(T);
|
|
|
|
if (T->fToInit)
|
|
{
|
|
T->fToInit=0;
|
|
GSYS_SetStackAndJump((void *)((U32)T->Stack+T->StackSize-sizeof(void *)*4),(void *)ExecuteTask,T);
|
|
}
|
|
else
|
|
longjmp(T->TskEnv,1);
|
|
}
|
|
else
|
|
{
|
|
|
|
/* Back from the previous task */
|
|
TASK * NextT;
|
|
|
|
|
|
NextT=T->Next;
|
|
|
|
/* Top this task if it was intended to die */
|
|
|
|
if (T->fToDie)
|
|
LoTskKill(T);
|
|
|
|
T=NextT;
|
|
}
|
|
}
|
|
else
|
|
T=T->Next;
|
|
}
|
|
else
|
|
T=T->Next;
|
|
}
|
|
|
|
if (DoTasksEpilogue)
|
|
DoTasksEpilogue();
|
|
|
|
CurrentTask=NULL;
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void TSK_Sleep(int Frames)
|
|
Purpose: This Task to sleep for an amount of frames
|
|
Params: T -> Task
|
|
Frames = num of frames to sleep
|
|
--------------------------------------------------------------------------- */
|
|
void TSK_Sleep(int Frames)
|
|
{
|
|
TASK * T;
|
|
|
|
T=CurrentTask;
|
|
|
|
|
|
ASSERT(T);
|
|
|
|
if (TSK_IsStackCorrupted(T))
|
|
{
|
|
if (StackFloodCallback)
|
|
StackFloodCallback(T);
|
|
else
|
|
ASSERT(!"TSK STACK CORRUPTION");
|
|
}
|
|
|
|
// ASSERT(!GSYS_IsStackOutOfBounds(T->Stack,T->StackSize));
|
|
|
|
DoEpi(T);
|
|
|
|
if (!setjmp(T->TskEnv))
|
|
{
|
|
/* Saving enviro so go back to scheduler */
|
|
T->SleepTime=Frames;
|
|
ReturnToSchedulerIfCurrentTask(CurrentTask);
|
|
}
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: static void ReturnToScheduler(TASK *T)
|
|
Purpose: Return to scheduler
|
|
Params: T -> Current Task
|
|
--------------------------------------------------------------------------- */
|
|
static void ReturnToSchedulerIfCurrentTask(TASK *T)
|
|
{
|
|
if (TSK_IsStackCorrupted(T))
|
|
{
|
|
if (StackFloodCallback)
|
|
StackFloodCallback(T);
|
|
else
|
|
ASSERT(!"TSK STACK CORRUPTION");
|
|
}
|
|
|
|
longjmp(SchEnv,1);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void TSK_Die(void)
|
|
Purpose: Kill off current task
|
|
--------------------------------------------------------------------------- */
|
|
void TSK_Die(void)
|
|
{
|
|
if (CurrentTask)
|
|
TSK_Kill(CurrentTask);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void TSK_Kill(TASK *T)
|
|
Purpose: Kill off a task
|
|
If this is the current task then return to scheduler
|
|
Params: T -> Task to kill
|
|
--------------------------------------------------------------------------- */
|
|
void TSK_Kill(TASK *T)
|
|
{
|
|
if (T==CurrentTask && CurrentTask)
|
|
{
|
|
T->fToDie=TRUE;
|
|
ReturnToSchedulerIfCurrentTask(T);
|
|
}
|
|
else
|
|
LoTskKill(T);
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: TASK * TSK_GetFirstActive(void);
|
|
|
|
Purpose: Get the first in the chain of active tasks
|
|
|
|
Params: T -> Task block to check
|
|
|
|
Returns: True if it is
|
|
--------------------------------------------------------------------------- */
|
|
TASK * TSK_GetFirstActive(void)
|
|
{
|
|
return(ActiveTasks);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: BOOL TSK_IsStackCorrupted(TASK *T)
|
|
|
|
Purpose: Check to see if this task's stack has flooded
|
|
|
|
Params: T -> Task block to check
|
|
|
|
Returns: True if it is
|
|
--------------------------------------------------------------------------- */
|
|
BOOL TSK_IsStackCorrupted(TASK *T)
|
|
{
|
|
if (T->fXtraStack)
|
|
{
|
|
int LongsOk;
|
|
LongsOk=CheckExtraStack(T->Stack,T->StackSize/4);
|
|
T->MaxStackSizeBytes=(u16)T->StackSize-(LongsOk*sizeof(u32));
|
|
return (LongsOk < T->XtraLongs);
|
|
}
|
|
else
|
|
return(GSYS_IsStackCorrupted(T->Stack,T->StackSize));
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void TSK_JumpAndResetStack(void (*RunFunc)(TASK *))
|
|
|
|
Purpose: Current running task stack is reset and jumped off to
|
|
another routine
|
|
|
|
Params: T -> Task block to check
|
|
|
|
Returns: True if it is
|
|
--------------------------------------------------------------------------- */
|
|
void TSK_JumpAndResetStack(void (*RunFunc)(TASK *))
|
|
{
|
|
TASK * T;
|
|
|
|
T=CurrentTask;
|
|
|
|
if (T)
|
|
{
|
|
T->Main=RunFunc;
|
|
GSYS_SetStackAndJump((void *)((U32)T->Stack+T->StackSize-sizeof(void *)*4),(void *)ExecuteTask,T);
|
|
}
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void TSK_SetStackAndJump(void (*RunFunc)(TASK *))
|
|
|
|
Purpose: Current running task
|
|
|
|
Params: T -> Task block to repoint
|
|
|
|
Returns: True if it is
|
|
--------------------------------------------------------------------------- */
|
|
void TSK_RepointProc(TASK *T,void (*Func)(TASK *T))
|
|
{
|
|
/* If the current task is this task then just jump there else mark as
|
|
needing initing and -> start to new func */
|
|
|
|
if (T==CurrentTask)
|
|
TSK_JumpAndResetStack(Func);
|
|
else
|
|
{
|
|
T->fToInit=1;
|
|
T->Main=Func;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: TASK * TSK_GetCurrentTask(void);
|
|
|
|
Purpose: Get the current executing task
|
|
|
|
Returns: -> Current execiting task block
|
|
|
|
--------------------------------------------------------------------------- */
|
|
TASK * TSK_GetCurrentTask(void)
|
|
{
|
|
return(CurrentTask);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: BOOL TSK_IsCurrentTask(TASK *T)
|
|
|
|
Purpose: Is this task the currently executing one?
|
|
|
|
Returns: TRUE or FALSE
|
|
|
|
--------------------------------------------------------------------------- */
|
|
BOOL TSK_IsCurrentTask(TASK *T)
|
|
{
|
|
return(T==CurrentTask);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: TASK *TSK_Exist(TASK *T,U32 Id,U32 Mask)
|
|
|
|
Purpose: Is this task the currently executing one?
|
|
|
|
Params: T -> Calling task
|
|
|
|
Returns: -> first task found
|
|
|
|
--------------------------------------------------------------------------- */
|
|
TASK *TSK_Exist(TASK *T,U32 Id,U32 Mask)
|
|
{
|
|
TASK * ptrTask;
|
|
TASK * RetTask;
|
|
|
|
ptrTask=ActiveTasks;
|
|
RetTask=NULL;
|
|
|
|
while (ptrTask && !RetTask)
|
|
{
|
|
if ((ptrTask != T) && (ptrTask->Id&Mask)==Id)
|
|
RetTask=ptrTask;
|
|
else
|
|
ptrTask=ptrTask->Next;
|
|
}
|
|
|
|
return(RetTask);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void TSK_SetExecFilter(U32 Id,U32 Mask)
|
|
|
|
Purpose: Set a filter for tasks that are executed
|
|
If ((Task.Id&Mask) == Id) then task is run
|
|
|
|
Params:
|
|
U32 = Id;
|
|
Mask = Task class mask
|
|
|
|
--------------------------------------------------------------------------- */
|
|
void TSK_SetExecFilter(U32 Id,U32 Mask)
|
|
{
|
|
ExecId=Id;
|
|
ExecMask=Mask;
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void TSK_ClearExecFilter(void)
|
|
|
|
Purpose: Clears the exec filter, everything is run
|
|
|
|
--------------------------------------------------------------------------- */
|
|
void TSK_ClearExecFilter(void)
|
|
{
|
|
TSK_SetExecFilter(0,0);
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: int TSK_KillTasks(TASK * CallingT,U32 Id,U32 Mask)
|
|
|
|
Purpose: Mass task killer. Whacks through task list looking for victims.
|
|
If (T->fKillable && (Task.Id&Mask) == Id) then kill it.
|
|
|
|
Params: CallingT -> Calling task
|
|
U32 = Id;
|
|
Mask = Task class mask
|
|
|
|
Returns: # of Tasks Killed
|
|
--------------------------------------------------------------------------- */
|
|
int TSK_KillTasks(TASK * CallingT,U32 Id,U32 Mask)
|
|
{
|
|
int TasksKilled;
|
|
TASK * T;
|
|
BOOL WasCurrentTaskKilled;
|
|
|
|
TasksKilled=0;
|
|
WasCurrentTaskKilled=FALSE;
|
|
T=ActiveTasks;
|
|
|
|
while (T)
|
|
{
|
|
TASK * NextT;
|
|
|
|
NextT=T->Next;
|
|
|
|
if (T != CallingT)
|
|
{
|
|
if (T->fKillable && (T->Id&Mask)==Id)
|
|
{
|
|
if (T==CurrentTask)
|
|
WasCurrentTaskKilled=TRUE;
|
|
else
|
|
LoTskKill(T);
|
|
|
|
TasksKilled++;
|
|
}
|
|
}
|
|
|
|
T=NextT;
|
|
}
|
|
|
|
/* If Current task was killed then we go on to next task */
|
|
|
|
if (WasCurrentTaskKilled)
|
|
{
|
|
CurrentTask->fToDie=TRUE;
|
|
ReturnToSchedulerIfCurrentTask(CurrentTask);
|
|
}
|
|
|
|
return(TasksKilled);
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void TSK_IterateTasks(U32 Id,U32 Mask,void (*CallBack)(TASK *T))
|
|
Purpose: Go through task list and do a callback for all tasks which match.
|
|
If (Task->Id&Mask)==Id then callback function is invoked.
|
|
Params: Id = Task Id to match
|
|
Mask = Task class mask
|
|
--------------------------------------------------------------------------- */
|
|
void TSK_IterateTasks(U32 Id,U32 Mask,void (*CallBack)(TASK *T))
|
|
{
|
|
TASK * T;
|
|
|
|
T=ActiveTasks;
|
|
|
|
while (T)
|
|
{
|
|
TASK * NextT;
|
|
|
|
NextT=T->Next;
|
|
|
|
if ((T->Id&Mask)==Id)
|
|
CallBack(T);
|
|
|
|
T=NextT;
|
|
}
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void TSK_MakeTaskInactive(TASK *T)
|
|
Purpose: Make a task temporarily inactive.
|
|
Params: T -> Task to knock out
|
|
--------------------------------------------------------------------------- */
|
|
void TSK_MakeTaskInactive(TASK *T)
|
|
{
|
|
T->fActive=0;
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void TSK_MakeTaskActive(TASK *T)
|
|
Purpose: Make a task active again.
|
|
Params: T -> Task to reactivate
|
|
--------------------------------------------------------------------------- */
|
|
void TSK_MakeTaskActive(TASK *T)
|
|
{
|
|
T->fActive=1;
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void TSK_MakeTaskImmortal(TASK *T)
|
|
Purpose: Make a task impervious to mass killings.
|
|
Note that task can still be killed explicitly with TSK_Kill.
|
|
Params: T -> Task to protect
|
|
--------------------------------------------------------------------------- */
|
|
void TSK_MakeTaskImmortal(TASK *T)
|
|
{
|
|
T->fKillable=0;
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void TSK_MakeTaskMortal(TASK *T)
|
|
Purpose: Make a task vulnerable to mass killings.
|
|
Params: T -> Task to expose
|
|
--------------------------------------------------------------------------- */
|
|
void TSK_MakeTaskMortal(TASK *T)
|
|
{
|
|
T->fKillable=1;
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: BOOL TSK_IsTaskActive(TASK *T)
|
|
Purpose: Check if a task is active
|
|
Params: T -> Task to eheck
|
|
Returns: 0=Inactive, 1=Active
|
|
--------------------------------------------------------------------------- */
|
|
BOOL TSK_IsTaskActive(TASK *T)
|
|
{
|
|
return (T->fActive);
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: BOOL TSK_IsTaskMortal(TASK *T)
|
|
Purpose: Check if a task is easy to kill.
|
|
Params: T -> Task to check
|
|
Returns: 0=Immortal, 1=Mortal
|
|
--------------------------------------------------------------------------- */
|
|
BOOL TSK_IsTaskMortal(TASK *T)
|
|
{
|
|
return (T->fKillable);
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void DetachFromList(TASK **Head,TASK *ThisObj)
|
|
Purpose: Take an object from an obj list
|
|
Params: Head -> Head ptr of list
|
|
ThisObj -> Obj to add
|
|
--------------------------------------------------------------------------- */
|
|
static void DetachFromList(TASK **Head,TASK *ThisObj)
|
|
{
|
|
if (ThisObj->Prev)
|
|
ThisObj->Prev->Next=ThisObj->Next;
|
|
else
|
|
*Head=ThisObj->Next;
|
|
|
|
if (ThisObj->Next)
|
|
ThisObj->Next->Prev=ThisObj->Prev;
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void AddToList(TASK **Head,TASK *ThisObj)
|
|
Purpose: Add an object to a obj list
|
|
Params: Head -> Head ptr of list
|
|
ThisObj -> Obj to add
|
|
--------------------------------------------------------------------------- */
|
|
static void AddToList(TASK **Head,TASK *ThisObj)
|
|
{
|
|
ThisObj->Prev=NULL;
|
|
|
|
if ((ThisObj->Next=*Head))
|
|
ThisObj->Next->Prev=ThisObj;
|
|
|
|
*Head=ThisObj;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: static void LoTskKill(TASK *T)
|
|
Purpose: Low level killing of task helper routine
|
|
Params: T -> Task to kill
|
|
--------------------------------------------------------------------------- */
|
|
static void LoTskKill(TASK *T)
|
|
{
|
|
BOOL GalRet;
|
|
|
|
/* Take out of list of active tasks */
|
|
|
|
DetachFromList(&ActiveTasks,T);
|
|
|
|
/* Dealloc the task block */
|
|
GalRet=GAL_Free(T->hndTask);
|
|
TasksActive--;
|
|
|
|
ASSERT(GalRet);
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: static void ExecuteTask(TASK *T)
|
|
Purpose: Low level task executor, protects from tasks that return
|
|
without a TSK_Kill
|
|
Params: T -> Task to execute
|
|
--------------------------------------------------------------------------- */
|
|
static void ExecuteTask(TASK *T)
|
|
{
|
|
T->Main(T);
|
|
DoEpi(T);
|
|
T->fToDie=TRUE;
|
|
ReturnToSchedulerIfCurrentTask(T);
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Epilogue / Prologue Function stuff
|
|
--------------------------------------------------------------------------- */
|
|
DOTSK_CBACK TSK_SetDoTasksPrologue(DOTSK_CBACK Func)
|
|
{
|
|
DOTSK_CBACK Old;
|
|
|
|
Old=DoTasksPrologue;
|
|
DoTasksPrologue=Func;
|
|
return(Old);
|
|
}
|
|
|
|
DOTSK_CBACK TSK_SetDoTasksEpilogue(DOTSK_CBACK Func)
|
|
{
|
|
DOTSK_CBACK Old;
|
|
|
|
Old=DoTasksEpilogue;
|
|
DoTasksEpilogue=Func;
|
|
return(Old);
|
|
}
|
|
|
|
|
|
TSK_CBACK TSK_SetTaskPrologue(TSK_CBACK Pro)
|
|
{
|
|
TSK_CBACK Old;
|
|
|
|
Old=ProFunc;
|
|
ProFunc=Pro;
|
|
return(Old);
|
|
}
|
|
|
|
TSK_CBACK TSK_SetTaskEpilogue(TSK_CBACK Epi)
|
|
{
|
|
TSK_CBACK Old;
|
|
|
|
Old=EpiFunc;
|
|
EpiFunc=Epi;
|
|
return(Old);
|
|
}
|
|
|
|
void TSK_SetEpiProFilter(U32 Id,U32 Mask)
|
|
{
|
|
EpiProId=Id;
|
|
EpiProMask=Id;
|
|
}
|
|
|
|
void TSK_ClearEpiProFilter(void)
|
|
{
|
|
TSK_SetEpiProFilter(1,0);
|
|
TSK_SetTaskEpilogue(NULL);
|
|
TSK_SetTaskPrologue(NULL);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: void TSK_SetExtraStackProtection(BOOL OnOff)
|
|
Purpose: Say if we want the slow, memory heavy xtra stack protection
|
|
--------------------------------------------------------------------------- */
|
|
void TSK_SetExtraStackProtection(BOOL OnOff)
|
|
{
|
|
ExtraStackProtection=OnOff;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: TSK_CBACK TSK_SetStackFloodCallback(TSK_CBACK Func);
|
|
Purpose: This gets called if stack is detected as broken
|
|
--------------------------------------------------------------------------- */
|
|
TSK_CBACK TSK_SetStackFloodCallback(TSK_CBACK Func)
|
|
{
|
|
TSK_CBACK OldFunc;
|
|
|
|
OldFunc=StackFloodCallback;
|
|
|
|
StackFloodCallback=Func;
|
|
return(OldFunc);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function: int TSK_SetExtraStackSize(int Size)
|
|
Purpose: Set the xtra stack size for safety
|
|
--------------------------------------------------------------------------- */
|
|
int TSK_SetExtraStackSize(int Size)
|
|
{
|
|
int OldSize=ExtraStackSizeLongs*sizeof(u32);
|
|
ExtraStackSizeLongs=Size/4;
|
|
return(OldSize);
|
|
|
|
}
|
|
|
|
void ExtraMarkStack(u32 * Stack,int SizeLongs)
|
|
{
|
|
int f;
|
|
for (f=0;f<SizeLongs;f++)
|
|
Stack[f]=f;
|
|
}
|
|
|
|
int CheckExtraStack(u32 * Stack,int LongsToCheck)
|
|
{
|
|
u32 f;
|
|
|
|
for (f=0;f<(u32) LongsToCheck;f++)
|
|
{
|
|
if (Stack[f] != f)
|
|
return(f);
|
|
}
|
|
return(f);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
ends */
|