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);
}
Historical capture: 2010-01-29. Home | Power on LoseThos | Sources and changes