This commit is contained in:
parent
8788076d39
commit
1c5c1b4011
59 changed files with 24871 additions and 56 deletions
860
Utils/Libs/GLib/tasker.c
Normal file
860
Utils/Libs/GLib/tasker.c
Normal file
|
@ -0,0 +1,860 @@
|
|||
/* ===========================================================================
|
||||
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 */
|
Loading…
Add table
Add a link
Reference in a new issue