Project: OSMain
U0 Exit()
{
if (Fs==sys_cur_focus_task && IsInDbg) {
LBts(&Fs->task_flags,TASKf_KILL_AFTER_DBG);
DbgExit;
} else {
if (!Gs->num && !IsInDbg)
SingleUser(OFF);
Fs->rflags=GetFlags;
Fs->rsp=GetStkPtr;
Fs->rbp=GetBasePtr;
Fs->rip=$;
Cli;
LBts(&Fs->task_flags,TASKf_KILL_TASK);
TaskEndNow;
}
}
BoolI8 TaskValidate(TaskStruct *task)
{
if (!(0<task<=MAX_I4) || task->address!=task ||
task->task_signature><(U8)!=TASK_COMBINED_SIGNATURE_VAL)
return FALSE;
else
return TRUE;
}
U0 Kill(TaskStruct *task,BoolI1 wait=TRUE)
{
U8 i;
CPUStruct *c;
BoolI1 found,old_preempt=Preempt(OFF);
if (TaskValidate(task)) {
if (task==sys_winmgr_task)
found=TRUE;
else
found=FALSE;
for (i=0;i<mp_cnt;i++) {
c=&cpu_structs[i];
if (task==c->seth_task)
found=TRUE;
}
if (!found) {
LBts(&task->task_flags,TASKf_KILL_TASK);
if (wait) {
do {
TaskNext;
if (!Bt(&task->task_flags,TASKf_KILL_TASK))
break;
} while (TaskValidate(task));
}
}
}
Preempt(old_preempt);
}
asm {_INIT_TASK:}
U8 TaskInit(TaskStruct *task,U8 stk)
{ //Returns Fs of task
U1 *b;
task->code_heap->next_mem_blk=
task->code_heap->last_mem_blk=
&task->code_heap->next_mem_blk;
if (task->code_heap!=task->data_heap)
task->data_heap->next_mem_blk=
task->data_heap->last_mem_blk=
&task->data_heap->next_mem_blk;
task->address=
task->next_task=
task->last_task=
task->next_input_filter_task=
task->last_input_filter_task=
task;
task->next_key_dev=
task->last_key_dev=
&task->next_key_dev;
task->rflags=SYS_NORMAL_RFLAGS;
task->next_child_task=
task->last_child_task=
(&task->next_child_task)><(U1 *)-offset(TaskStruct.next_sibling_task);
task->next_servant_cmd=
task->last_servant_cmd=
&task->next_servant_cmd;
task->next_master_cmd=
task->last_master_cmd=
&task->next_master_cmd;
task->next_lex=
task->last_lex=
&task->next_lex;
task->next_ltf=
task->last_ltf=
(&task->next_ltf)><(U1 *)-offset(Ltf.next_ltf);
task->next_except=
task->last_except=
&task->next_except;
task->next_ctrl=
task->last_ctrl=
&task->next_ctrl;
task->next_ode=
task->last_ode=
&task->next_ode;
task->fpu_mmx=MAllocAligned(sizeof(FPUState),0x10,task);
MemCpy(task->fpu_mmx,&sys_init_fpu_mmx,sizeof(FPUState));
if (task==SYS_ADAM_TASK) {
// Delayed until heap expanded.See Expand Heap
// task->hash_table=HashTableNew(ADAM_HASH_SIZE,task);
} else {
if (!Gs->num)
task->hash_table=HashTableNew(STD_HASH_SIZE,task);
else
task->hash_table=HashTableNew(MP_STD_HASH_SIZE,task);
}
if (!stk) {
if (!Gs->num)
stk=DEFAULT_STACK;
else
stk=MP_DEFAULT_STACK;
}
b=task->stack_base=MAlloc(stk,task);
task->stack_size=MSize(b);
task->rsp=b+task->stack_size;
task->answers_displayed=1; //from 0-8
task->text_attr=0xF1;
task->border_attr=WHITE<<4+LTBLUE;
task->win_right=text_cols-2;
task->win_left=1;
task->win_top=1;
task->win_bottom=text_rows-2;
return task;
}
TaskStruct *Spawn(U0 (*fp_start_add)(U0 *data),U0 *data=NULL,
U1 *task_name=NULL,
TaskStruct *parent=NULL, //NULL means adam
U1 *acct=NULL,
U8 stk=0, //0=default
U8 flags=SPAWNF_ADD_TO_QUEUE)
{
//We alloc from code heap so address will be short
//Could be allocated off of data heap
TaskStruct *task=CAlloc(sizeof(TaskStruct),Gs->seth_task->code_heap);
task->task_signature=TASK_SIGNATURE_VAL;
if (!task_name) task_name="Unnamed Task";
if (!parent) parent=Gs->seth_task;
task->parent_task=parent;
task->gs=parent->gs;
if (Gs->code_bp)
task->data_heap=task->code_heap=TaskHeapCtrlInit(task,Gs->code_bp,Gs->seth_task->data_heap);
if (Gs->data_bp)
task->data_heap=TaskHeapCtrlInit(task,Gs->data_bp,Gs->seth_task->data_heap);
TaskInit(task,stk);
task->rip=fp_start_add;
task->rsp><(U1 *)-=8;
*task->rsp=data;
task->rsp><(U1 *)-=8;
*task->rsp=&Exit;
task->hash_table->next=parent->hash_table;
MemCpy(task->task_title,task_name,TASK_TITLE_LEN+1);
MemCpy(task->task_name,task_name,TASK_NAME_LEN+1);
if (acct)
task->acct=AcctFind(acct);
else
task->acct=task->parent_task->acct;
PushFD;
Cli;
if (flags&SPAWNF_ADD_TO_QUEUE) {
TaskChildAdd(task);
TaskQueueAdd(task);
}
PopFD;
return task;
}
U0 ServantTaskCont()
{
FlushMsgs;
while (TRUE) {
if (ServantCmdsHandler)
if (!Bt(&Fs->task_flags,TASKf_LOCK_TITLE))
MemCpy(Fs->task_title,Fs->task_name,TASK_NAME_LEN+1);
FlushMsgs;
LBts(&Fs->task_flags,TASKf_IDLE);
LBts(&Fs->task_flags,TASKf_AWAITING_MSG);
TaskNext;
}
}
U0 TaskDerivedValuesUpdate(TaskStruct *task=NULL)
{
if (!task) task=Fs;
PushFD;
Cli; //TODO Multiprocessor safe
WinDerivedValuesUpdate(task);
if (fp_update_ctrls)
fp_update_ctrls(task);
PopFD;
}
U0 TaskLocalInit()
{
if (LBts(&Fs->task_flags,TASKf_LOCAL_INITIALIZED))
return;
TaskDerivedValuesUpdate;
LBts(&Fs->display_flags,DISPLAYf_HAS_CLOSE_WIN);
Fs->text_attr=WHITE<<4+BLUE;
Fs->border_attr=WHITE<<4+LTBLUE;
Fs->win_top=13;
Cd("HOME");
CallExtNum(EXT_WIN_TO_TOP,Fs);
}
U0 UserTaskInit()
{
LBts(&Fs->task_flags,TASKf_LOCAL_USER);
TaskLocalInit;
}
U0 UserCmdLine()
{
UserTaskInit;
Fs->user_num=++num_spawned_users;
ExeFile("UserStartUp.CPZ");
if (!LBts(&Fs->display_flags,DISPLAYf_SHOW))
Dbg;
UserTaskCont;
}
U0 ServantUserCmdLine()
{
LBts(&Fs->task_flags,TASKf_SERVANT_USER);
UserTaskInit;
ExeFile("ServantStartUp.CPZ");
ServantTaskCont;
}
TaskStruct *SpawnUser(U1 *st=NULL)
{
TaskStruct *task=Spawn(&UserCmdLine);
TaskWaitIdle(task);
if (st)
XTalk(task,st);
return task;
}
U0 TaskPause(TaskStruct *task,BoolI1 state)
{
TaskStruct *task1;
BoolI1 old_preempt=Preempt(OFF);
if (TaskValidate(task)) {
if (LBEqu(&task->task_flags,TASKf_PAUSED,state)) {
if (!state)
task->pause_total+=t-task->pause_start;
} else {
if (state)
task->pause_start=t;
}
task1=task->next_child_task;
while (task1!=&task->next_child_task) {
if (!TaskValidate(task1))
break;
TaskPause(task1,state);
task1=task1->next_sibling_task;
}
}
Preempt(old_preempt);
}
U0 TaskFinishOff(TaskStruct *task)
{ //We delay freeing in case lingering
//references are made to task's.
FreeMemBlkList(task->code_heap);
Free(task->code_heap);
if (task->data_heap!=task->code_heap) {
FreeMemBlkList(task->data_heap);
Free(task->data_heap);
}
Free(task);
}
asm {_TASK_END:}
U8 TaskEnd()
{ //called with irq's off
TaskStruct *tempt,*tempt1;
TaskCmdStruct *tempc,*tempc1,*tempc2;
if (Fs==sys_task_being_screen_updated) {
LBts(&Fs->task_flags,TASKf_KILL_TASK);
return Fs->next_task;
}
if (Fs->task_end_cb) {
Fs->wake_time=0;
LBtr(&Fs->task_flags,TASKf_KILL_TASK);
LBtr(&Fs->task_flags,TASKf_AWAITING_MSG);
LBtr(&Fs->task_flags,TASKf_SUSPENDED);
Fs->rip=Fs->task_end_cb;
Fs->task_end_cb=NULL;
return Fs;
}
if (Fs->parent_task) {
if (Fs->parent_task->popup_task==Fs) {
Fs->parent_task->popup_task=NULL;
Kill(Fs->parent_task,FALSE);
return Fs->parent_task;
}
if (Fs->parent_task->dbg_task==Fs)
Fs->parent_task->dbg_task=NULL;
}
PartitionsRelease;
BlkDevsRelease;
tempt1=(&Fs->next_child_task)><(U1 *)-offset(TaskStruct.next_sibling_task);
tempt=tempt1->next_sibling_task;
if (tempt!=tempt1) {
do {
LBts(&tempt->task_flags,TASKf_KILL_TASK);
tempt=tempt->next_sibling_task;
} while (tempt!=tempt1);
return Fs->next_task;
}
while (LBts(&Fs->locked_flags,TASKLf_TASK_LOCK))
Pause;
tempc1=&Fs->next_servant_cmd;
tempc=tempc1->next;
while (tempc!=tempc1) {
tempc2=tempc->next;
Free(tempc->data);
Free(tempc);
tempc=tempc2;
}
tempc1=&Fs->next_master_cmd;
tempc=tempc1->next;
while (tempc!=tempc1) {
tempc2=tempc->next;
Free(tempc->data);
Free(tempc);
tempc=tempc2;
}
if (IsRaw)
LBts(&sys_semas[SYS_SEMA_FLUSH_VGA_IMAGE],0);
if (sys_cur_focus_task==Fs) {
if (!Gs->num)
SingleUser(OFF);
sys_cur_focus_task=NULL;
win_inhibit=0;
}
//Remque
Fs->task_signature><(U8)=0;
tempt =Fs->next_input_filter_task;
tempt1=Fs->last_input_filter_task;
tempt1->next_input_filter_task=tempt;
tempt ->last_input_filter_task=tempt1;
tempt =Fs->next_sibling_task;
tempt1=Fs->last_sibling_task;
tempt1->next_sibling_task=tempt;
tempt ->last_sibling_task=tempt1;
tempt =Fs->next_task;
tempt1=Fs->last_task;
tempt1->next_task=tempt;
tempt ->last_task=tempt1;
LBtr(&Fs->locked_flags,TASKLf_TASK_LOCK);
if (sys_winmgr_task) {
Fs->next_task=Gs->dying_task_list;
Gs->dying_task_list=Fs;
} else
TaskFinishOff(Fs); //dangerous (stack in use)
return tempt;
}
U0 TaskFinishOffDying()
{ //We delay freeing in case lingering
//references are made to task's.
BoolI1 old_preempt=Preempt(OFF);
TaskStruct *task1,*task2;
if (task1=Gs->dying_task_list) {
do {
task2=task1->next_task;
TaskFinishOff(task1);
task1=task2;
} while (task1);
Gs->dying_task_list=NULL;
}
Preempt(old_preempt);
}