// TSS task flags
#define TSSf_KILL_TASK                0
#define TSSf_SUSPENDED                1
#define TSSf_LOCAL_USER                2
#define TSSf_PREEMPT                 3
#define TSSf_IDLE                 4
#define TSSf_INPUT_FILTER_TASK        5
#define TSSf_FILTER_INPUT        6
#define TSSf_HAS_SONG                7
#define TSSf_NOT_RAW                8
#define TSSf_DONT_CHANGE_DESC        9
#define TSSf_DISABLE_BPTS        10
#define TSSf_AWAITING_MSG        11
#define TSSf_CURRENTLY_RUNNING        12
#define TSSf_HAS_BEEN_SWAPPED        13
#define TSSf_BREAK_LOCKED        14
#define TSSf_PENDING_BREAK        15
#define TSSf_PAUSED                16
#define TSSf_SERVANT_USER        17
#define TSSf_BREAK_TO_CTRLQ        18
#define TSSf_CONFIG_RECORD_DONE        19

#define DISPLAYf_CURSOR_ON                0
#define DISPLAYf_SHOW                1
#define DISPLAYf_HAS_MENU                2
#define DISPLAYf_HAS_CLOSE_WIN        3
#define DISPLAYf_HAS_BEEN_RESIZED        4
#define DISPLAYf_SILENT                5
#define DISPLAYf_NO_DOUBLE_CLICK        6
#define DISPLAYf_HAS_BEEN_RESIZED2        7
#define DISPLAYf_NO_BORDER                8
#define DISPLAYf_CHILDREN_NOT_ON_TOP 9
#define DISPLAYf_WIN_ON_TOP                10

#define TSSS_IN_QUEUE_SIGNATURE        0x23476542

#define TSS_DESC_LENGTH                        127
#define TSS_WALLPAPER_DATA_SIZE                128

public class TssStruct $LK+BK,"Redundant Asm Struct","FF:/LT/OSMain/OSDefs.ASZ,TSS_RIP"$
{
  TssStruct *address;
  U8 task_flags;
  U8 display_flags;
  U8 wake_time;

  HeapCtrl *code_heap,*data_heap;

  Ltf        *cur_ltf,*aux_ltf;
  I8        win_left;
  I8        win_right;
  I8        win_top;
  I8        win_bottom;

  LTPartition *cur_partition;
  I1        *cur_dir;

  TssStruct *parent_tss;
  TssStruct *next_tss,*last_tss;
  TssStruct *next_input_filter_tss,*last_input_filter_tss;
  TssStruct *next_sibling_tss,*last_sibling_tss;
  TssStruct *next_child_tss,*last_child_tss;

  //These are derived from left,top,right,bottom
  I8        win_width;
  I8        win_height;
  I8        win_pixel_left; //These are in pixels, not characters
  I8        win_pixel_right;
  I8        win_pixel_width;
  I8        win_pixel_top;
  I8        win_pixel_bottom;
  I8        win_pixel_height;
  I8        win_border_pixel_left;
  I8        win_border_pixel_right;
  I8        win_border_pixel_top;
  I8        win_border_pixel_bottom;

  U8 rip;
  U8 rflags;
  U8 rax;
  U8 rcx;
  U8 rdx;
  U8 rbx;
  U8 rsp;
  U8 rbp;
  U8 rsi;
  U8 rdi;
  U8 r8;
  U8 r9;
  U8 r10;
  U8 r11;
  U8 r12;
  U8 r13;
  U8 r14;
  U8 r15;
  CPUCachedStruct *gs;

  FPUState fpu;
  U8        time_slice_start;
  U8        total_time;
  U8        swap_cnter;

  void        update_win(TssStruct *tss);
  void        draw_it(TssStruct *tss,GrBitMap *base);

  I1        task_descriptor[TSS_DESC_LENGTH+1];
  I1        task_descriptor2[TSS_DESC_LENGTH+1];
  I1        wallpaper_data[TSS_WALLPAPER_DATA_SIZE];

  Ltf        *double_buf_cur_ltf,*double_buf_aux_ltf;

  I4        scroll_speed; //For scrolling Sign like text
  U1        text_attr;
  U1        border_attr;
  U2        pad;

  U1   *stack_base;
  U8        stack_size;
  ExceptStruct *next_except,*last_except;
  U8        except_rbp;        //Stores throw routine's RBP
  U8        except_argc;
  I8        *except_argv;
  BoolI1 catch_except,ignore_except,pad[6];
  SysBpt *bpt_list;
  Ctrl        *next_ctrl,*last_ctrl;
  Ode        *next_ode,*last_ode;
  U8        last_ode_time;
  SysHashTable *hash_table;
  SysAcctStruct *acct;

#define MSG_NULL                0
#define MSG_CMD                        1
#define MSG_KEY_DOWN                2
#define MSG_KEY_UP                3
#define MSG_IP_MOVE                4
#define MSG_IP_L_DOWN                5
#define MSG_IP_L_UP                6
#define MSG_IP_L_D_DOWN         7
#define MSG_IP_L_D_UP                8
#define MSG_IP_R_DOWN                9
#define MSG_IP_R_UP                10
#define MSG_IP_R_D_DOWN         11
#define MSG_IP_R_D_UP                12
#define MSG_FOCUS                13
#define MSG_RESIZE                14
#define MSG_MOVE                15

#define MSGF_ALLOW_KEY_DESC        63

  TssCmdStruct *next_servant_cmd,*last_servant_cmd;
  TssCmdStruct *next_master_cmd,*last_master_cmd;
  LexStruct *next_lex,*last_lex;

  I8        win_old_left;
  I8        win_old_right;
  I8        win_old_top;
  I8        win_old_bottom;

  U1   *end_task_cb;
  U4        user_num;
  U4        fault_num;
  U8         answers[8];
  double double_answers[8];
  U4        answers_types[8];
  U4        answers_displayed;
  U4        in_queue_signature;
  TssStruct *dbg_tss;
  TssStruct *popup_tss;
  LTChnl    *local_chnl;
  LTChnl    *rmt_chnl;
  WinScrollState horz_scroll,vert_scroll;

  I8        mp;  //Free to use for multicore control

  I8        slave_task_data0,slave_task_data1,
              slave_task_data2,slave_task_data3;

  I8        user_data0,user_data1,
              user_data2,user_data3;
};

$PJ,"Project: OSMain","/LT/OSMain/OS.SPZ"$
SysHashTable *HashTableNew(U8 size,TssStruct *mem_tss=NULL)
{
  SysHashTable *tempht;
  tempht=MAllocZ(sizeof(SysHashTable),mem_tss);
  tempht->body=MAllocZ(size<<3,mem_tss);
  tempht->mask=size-1;
  return tempht;
}

U8 AllocGdtTabEntry()
{ //Global descriptor table
  U8 old_flags=GetFlags,result;
  U4 *d;
  Cli;
  if (!(result=free_gdt_list))
      Debugger;
  d=gdttab><(U1 *)+result;
  free_gdt_list=*d;
  SetFlags(old_flags);
  return result;
}

void FreeGdtTabEntry(U8 i)
{
  U8 old_flags=GetFlags;
  U4 *d=gdttab><(U1 *)+i;
  Cli;
  *d=free_gdt_list;
  free_gdt_list=i;
  SetFlags(old_flags);
}

U8 CreateTssSelector(U8 phy_add)
{
  U8 result,old_flags=GetFlags;
  U4 *d,*d1;
  Cli;
  result=AllocGdtTabEntry;
  d=gdttab><(U1 *)+result;
  d1=d><(U1 *)+4;
  *d =0x0000FFFF;
  *d1=0x008F8900;
  d><(U1 *)+=2;
  *d|=phy_add & 0x00FFFFFF;
  *d1++|=phy_add & 0xFF000000;
  *d1++=0;
  *d1=0;
  SetFlags(old_flags);
  return result;
}

U8 CreateMemSelector(U8 phy_add)
{
  U8 result,old_flags=GetFlags;
  U4 *d,*d1;
  Cli;
  result=AllocGdtTabEntry;
  d=gdttab><(U1 *)+result;
  d1=d><(U1 *)+4;
  *d =0x0000FFFF;
  *d1=0x00CF9200;
  d><(U1 *)+=2;
  *d |=phy_add & 0x00FFFFFF;
  *d1++|=phy_add & 0xFF000000;
  *d1++=0;
  *d1=0;
  SetFlags(old_flags);
  return result;
}

void AddTaskToQueue(TssStruct *tss,TssStruct *pred=NULL)
{
  TssStruct *last;
  U8 old_flags=GetFlags;
  Cli;
  if (!pred) pred=Fs;
  last=pred->last_tss;
  last->next_tss=pred->last_tss=tss;
  tss ->last_tss=last;
  tss ->next_tss=pred;
  tss->in_queue_signature=TSSS_IN_QUEUE_SIGNATURE;
  SetFlags(old_flags);
}

void AddTaskToChildQueue(TssStruct *tss)
{
  TssStruct *last,*pred;
  U8 old_flags=GetFlags;
  Cli;
  pred=tss->parent_tss->last_child_tss;
  last=pred->last_sibling_tss;
  last->next_sibling_tss=pred->last_sibling_tss=tss;
  tss ->last_sibling_tss=last;
  tss ->next_sibling_tss=pred;
  SetFlags(old_flags);
}

void UpdateDerivedTssValues(TssStruct *tss=NULL)
{
  U8 old_flags=GetFlags;
  if (!tss) tss=Fs;

  Cli; //TODO Multiprocessor safe
  UpdateDerivedWinValues(tss);
  CallExtNum(EXT_UPDATE_CTRLS,tss);
  SetFlags(old_flags);
}

asm {CP_INIT_TSS::};
U8 InitTss(TssStruct *tss,U8 stk)
{ //Returns Fs of task
  U1 *b;

  tss->code_heap->next_mem_blk=
      tss->code_heap->last_mem_blk=
      &tss->code_heap->next_mem_blk;
  if (tss->code_heap!=tss->data_heap)
      tss->data_heap->next_mem_blk=
          tss->data_heap->last_mem_blk=
          &tss->data_heap->next_mem_blk;

  tss->address=
      tss->next_tss=
      tss->last_tss=
      tss->next_input_filter_tss=
      tss->last_input_filter_tss=
      tss;

  tss->rflags=SYS_NORMAL_RFLAGS;

  tss->next_child_tss=
      tss->last_child_tss=
      (&tss->next_child_tss)><(U1 *)-offset(TssStruct.next_sibling_tss);

  tss->next_servant_cmd=
      tss->last_servant_cmd=
      &tss->next_servant_cmd;

  tss->next_master_cmd=
      tss->last_master_cmd=
      &tss->next_master_cmd;


  tss->next_lex=
      tss->last_lex=
      &tss->next_lex;

  tss->next_except=
      tss->last_except=
      &tss->next_except;

  tss->next_ctrl=
      tss->last_ctrl=
      &tss->next_ctrl;

  tss->next_ode=
      tss->last_ode=
      &tss->next_ode;

  MemCpy(&tss->fpu,&sys_initial_fpu,108);

  tss->hash_table=HashTableNew(0x1000,tss);
  b=MAlloc(stk,tss);
  tss->stack_base=b;
  tss->stack_size=MSize(b);
  b><(U1 *)+=stk;
  tss->rsp=b;
  tss->answers_displayed=1;  //from 0-8
  return tss;
}

asm {CP_INIT_IDT::};
void InitIDT(U8 *idt,U8 size)
{ //interrupt descriptor table
  U8 i,temp_ptr[2];
  U4 *src=IRQ_VECTORS,*dst=idt;
  for (i=0;i<MAX_INITIAL_IDT;i++) {
      *dst><(U2 *)++=*src><(U2 *)++;
      *dst><(U2 *)++=SYS_CS64_SEL;
      *dst><(U2 *)++=0x8E00; //E=32-bit irq gate
      *dst><(U2 *)++=*src><(U2 *)++;
      *dst><(U8 *)++=0;
  }
  dst=temp_ptr;
  *dst><(U2 *)++=size*16-1;
  *dst><(U4 *)++=idt;
  *dst><(U2 *)++=0;
  *dst><(U4 *)++=0;
  SetIDT(temp_ptr);
  WbInvd;
}

U8 GetIDTEntry(U8 irq,U8 core_num)
{
  U8 result,*src=cpu_cached[core_num].idt><(U1 *)+irq*16;
  result.u2[0]=*src><(U2 *);
  src><(U1 *)+=6;
  result.u2[1]=*src><(U2 *)++;
  result.u4[1]=*src><(U4 *);
  return result;
}

U8 SetIDTEntry(U8 irq,U8 new_handler,U8 core_num)
{
  U8 result=GetIDTEntry(irq,core_num);
  U1 *dst=cpu_cached[core_num].idt><(U1 *)+irq*16;
  *dst><(U2 *)++=new_handler.u2[0];
  *dst><(U2 *)++=SYS_CS64_SEL;
  *dst><(U2 *)++=0x8E00; //E=32-bit irq gate
  *dst><(U2 *)++=new_handler.u2[1];
  *dst><(U4 *)++=new_handler.u4[1];
  *dst><(U4 *)++=0;
  MPWbInvdAll;
  return result;
}

CPUUncachedStruct *InitCPUUncachedStruct(CPUUncachedStruct *uc)
{
  uc->idle_factor=0.01;
  uc->no_preempt_factor=0.01;
  return uc;
}

asm {CP_INIT_CPU_CACHED_STRUCT::};
CPUCachedStruct *InitCPUCachedStruct(U8 num,CPUCachedStruct *c)
{
  MemSet(c,0,sizeof(CPUCachedStruct));
  c->cached_address=c;
  c->num=num;
  if (num) {
      c->idle_tss=Spawn(0,NULL,"Idle",Fs,NULL,DEFAULT_STACK,FALSE);
      CallExtStr("GrInitCPU",c);
  }
  return c;
}

U8 InitStk(U8 size)
{
  U1 *st=MAllocZ(size);
  return st+size;
}

U2 InitRealTssStruct()
{
  RealTssStruct *tss2;
  tss2=MAllocZ(sizeof(RealTssStruct));
  tss2->io_map_offset=offset(RealTssStruct.io_map);
  MemSet(tss2->io_map,0xFF,MAXIO/8);
  tss2->rsp0=InitStk(4096);
  tss2->rsp1=InitStk(4096);
  tss2->rsp2=InitStk(4096);
  tss2->ist1=InitStk(4096);
  tss2->ist2=InitStk(4096);
  tss2->ist3=InitStk(4096);
  tss2->ist4=InitStk(4096);
  tss2->ist5=InitStk(4096);
  tss2->ist6=InitStk(4096);
  tss2->ist7=InitStk(4096);
  return CreateTssSelector(tss2);
}

asm {CP_SPAWN_TASK::};
TssStruct *Spawn(void *start_add,void *data=NULL,
                      I1 *desc=NULL,
                      TssStruct *parent=NULL, //NULL means adam
                      I1 *acct=NULL,
                      U8 stk=DEFAULT_STACK,
                      BoolI1 add_to_queue=TRUE)
{
  U8 old_flags=GetFlags;
  TssStruct *tss=MAllocZ(sizeof(TssStruct),Gs->seth_tss);
  SysAcctStruct *tempa;
  if (!desc) desc="Unnamed Task";
  if (!parent) parent=Gs->seth_tss;
  tss->parent_tss=parent;
  tss->gs=parent->gs;
  if (Gs->code_bp)
      
tss->data_heap=tss->code_heap=InitTssHeapCtrl(tss,Gs->code_bp,Gs->seth_tss->data_heap);
  if (Gs->data_bp)
      tss->data_heap=InitTssHeapCtrl(tss,Gs->data_bp,Gs->seth_tss->data_heap);
  InitTss(tss,stk);
  tss->rip=start_add;
  tss->rsp><(U1 *)-=8;
  *tss->rsp=data;
  tss->rsp><(U1 *)-=8;
  *tss->rsp=&Exit;
  tss->hash_table->next=parent->hash_table;
  MemCpy(tss->task_descriptor,desc,TSS_DESC_LENGTH);
  MemCpy(tss->task_descriptor2,desc,TSS_DESC_LENGTH);
  tss->acct=tss->parent_tss->acct;
  if (acct) {
      if (tempa=CallExtStr("FindSysAcct",acct))
          tss->acct=tempa;
  }

  Cli;
  if (add_to_queue) {
      AddTaskToQueue(tss);
      AddTaskToChildQueue(tss);
  }
  SetFlags(old_flags);
  return tss;
}


TssCmdStruct *QueueTaskRequest(TssStruct *servant,TssStruct *master,
                                        I1 *data,U8 flags)
{
  U8 old_flags=GetFlags;
  TssCmdStruct *result;
  if (!data || !ValidateTss(servant) ||
          master && !ValidateTss(master) ||
          servant->popup_tss && !Bt(&servant->task_flags,TSSf_FILTER_INPUT))
      return NULL;
  result=AMAlloc(sizeof(TssCmdStruct));
  result->master_tss=master;
  result->cmd_code=TSSCT_EXECUTE_STR;
  result->flags=flags;
  result->data=AStrNew(data);
  Cli;
  servant->task_flags&=~(1<<TSSf_IDLE|1<<TSSf_AWAITING_MSG);
  InsQue(result,servant->last_servant_cmd);
  if (Bt(&flags,TSSCf_WAKE_MASTER) &&
          ValidateTss(master)) {
      Bts(&master->task_flags,TSSf_SUSPENDED);
      SwapInNextTask;
  }
  SetFlags(old_flags);
  return result;
}

TssCmdStruct *QueueTextInput(TssStruct *servant,TssStruct *master,
                                        I1 *data,U8 flags)
{
  U8 old_flags=GetFlags;
  BoolI1 old_preempt=Preempt(OFF);
  U1 *input_filter_start_add;
  TssCmdStruct *result;
  TssStruct *tss;
  if (!data || !ValidateTss(servant) ||
          master && !ValidateTss(master) ||
          servant->popup_tss && !Bt(&servant->task_flags,TSSf_FILTER_INPUT)) {
      Preempt(old_preempt);
      return NULL;
  }
  result=AMAlloc(sizeof(TssCmdStruct));
  result->master_tss=master; //in case somebody cares
  result->cmd_code=TSSCT_TEXT_INPUT;
  result->flags=flags;
  result->data=AStrNew(data);

  if (input_filter_start_add=ext[EXT_INPUT_FILTER_TASK]) {
      if (flags&1<<TSSCf_HIGHEST_PRIORITY ||
              servant->next_input_filter_tss==servant) {
          tss=Spawn(input_filter_start_add,0,
              "Input Filter",servant);
          Cli;
          tss->next_input_filter_tss=servant->next_input_filter_tss;
          tss->last_input_filter_tss=servant;
          servant->next_input_filter_tss=tss;
          tss->next_input_filter_tss->last_input_filter_tss=tss;
      } else
          tss=servant->next_input_filter_tss;
      Cli;
      tss->task_flags&=~(1<<TSSf_IDLE|1<<TSSf_AWAITING_MSG);
      InsQue(result,tss->last_servant_cmd);
      SetFlags(old_flags);
  } else {
      Free(result);
      result=NULL;
  }
  Preempt(old_preempt);
  return result;
}

TssCmdStruct *QueueMsg(TssStruct *servant,TssStruct *master,
                                        U8 code,U8 p1,U8 p2,U8 flags)
{
  TssCmdStruct *tempc1,*tempc;
  U8 old_flags=GetFlags;
  if (!ValidateTss(servant) ||
          master && !ValidateTss(master)||
          servant->popup_tss && !Bt(&servant->task_flags,TSSf_FILTER_INPUT))
      return NULL;
  tempc=AMAlloc(sizeof(TssCmdStruct));
  tempc->master_tss=master;
  tempc->cmd_code=TSSCT_MSG;
  tempc->msg_code=code;
  tempc->p1=p1;
  tempc->p2=p2;
  tempc->flags=flags;
  tempc->data=NULL;
  if (Bt(&sys_semas[SYS_SEMA_RECORD_MACRO],0) &&
          servant!=macro_util_tss &&
          code==MSG_KEY_DOWN) {
      tempc1=AMAllocIdentical(tempc);
      InsQue(tempc1,sys_macro_queue.last);
  }
  Cli;
  while (Bt(&servant->task_flags,TSSf_FILTER_INPUT) &&
          !Bt(&flags,TSSCf_DONT_FILTER))
      servant=servant->next_input_filter_tss;
  servant->task_flags&=~(1<<TSSf_IDLE|1<<TSSf_AWAITING_MSG);
  InsQue(tempc,servant->last_servant_cmd);
  SetFlags(old_flags);
  return tempc;
}

BoolI8 GetRequestResult(TssCmdStruct *rqst=NULL,U8 *result=NULL)
{
  U8 old_flags=GetFlags;
  TssCmdStruct *tempc,*tempc1;
  Cli;
  tempc1=&Fs->next_master_cmd;
  tempc=tempc1->next;
  while (tempc!=tempc1) {
      if (!rqst || rqst==tempc) {
          RemQue(tempc);
          if (result)
              *result=tempc->result;
          Free(tempc->data);
          Free(tempc);
          SetFlags(old_flags);
          return TRUE;
      }
      tempc=tempc->next;
  }
  SetFlags(old_flags);
  return FALSE;
}

void WaitTaskIdle(TssStruct *tss)
{
  U8 old_flags=GetFlags;
  TssStruct *tss1;
  TssCmdStruct *tempc;
  if (ValidateTss(tss)) {
      Cli;
      while (TRUE) {
          tss1=tss->last_input_filter_tss;
          tempc=&tss1->next_servant_cmd;
          if (ValidateTss(tss1) && tempc==*tempc &&
                  Bt(&tss1->task_flags,TSSf_IDLE))
              break;
          SwapInNextTask;
      }
      SetFlags(old_flags);
  }
}

void PostMsg(TssStruct *tss,U8 code,U8 p1,U8 p2,U8 flags=0)
{
  if (Bt(&tss->task_flags,TSSf_INPUT_FILTER_TASK))
      QueueMsg(tss->last_input_filter_tss,NULL,code,p1,p2,
              flags| 1<<TSSCf_DONT_FILTER);
  else
      QueueMsg(tss,NULL,code,p1,p2,flags);
}

void SendMsg(TssStruct *tss,U8 code,U8 p1,U8 p2,U8 flags=0)
{
  PostMsg(tss,code,p1,p2,flags);
  WaitTaskIdle(tss);
}

void Msg(U8 code,U8 p1,U8 p2,U8 flags=0)
{
  PostMsg(Fs,code,p1,p2,flags);
}


U8 HandleServantCmds(TssStruct *tss=NULL)
{
  U8 cnt=0,old_flags=GetFlags;
  TssCmdStruct *tempc,*tempc1;
  TssStruct *master;
  if (!tss) tss=Fs;
start_over:
  Cli;
  tempc1=&tss->next_servant_cmd;
  while (tempc!=tempc1) {
      tempc=tempc1->next;
      if (tempc->cmd_code==TSSCT_EXECUTE_STR ||
      tempc->cmd_code==TSSCT_EXECUTE_FILE) {
          cnt++;
          RemQue(tempc);
          SetFlags(old_flags);
          try {
              if (tempc->cmd_code==TSSCT_EXECUTE_STR)
                  
tempc->result=CallExtNum(EXT_EXECUTE_STR,tempc->data,sys_temp_filename,FALSE);
              else
                  tempc->result=CallExtNum(EXT_EXECUTE_FILE,tempc->data,FALSE);
          } catch
              Fs->catch_except=TRUE;
          if (master=tempc->master_tss) {
              if (!Bt(&tempc->flags,TSSCf_EXIT_ON_COMPLETE)) {
                  Cli;
                  InsQue(tempc,master->last_master_cmd);
                  SetFlags(old_flags);
              }
              if (Bt(&tempc->flags,TSSCf_FOCUS_MASTER) &&
              Bt(&master->task_flags,TSSf_LOCAL_USER))
                  sys_cur_focus_task=master;
              if (Bt(&tempc->flags,TSSCf_WAKE_MASTER))
                  Btr(&master->task_flags,TSSf_SUSPENDED);
              if (!Bt(&tempc->flags,TSSCf_EXIT_ON_COMPLETE))
                  goto start_over;
              else {
                  Free(tempc->data);
                  Free(tempc);
                  Exit;
              }
          } else {
              if (!Bt(&tempc->flags,TSSCf_EXIT_ON_COMPLETE)) {
                  Free(tempc->data);
                  Free(tempc);
                  goto start_over;
              } else {
                  Free(tempc->data);
                  Free(tempc);
                  Exit;
              }
          }
      } else
          break;
  }
  SetFlags(old_flags);
  return cnt;
}

void ContServantTask()
{
  CallExtNum(EXT_FLUSH_MSGS,NULL);
  while (TRUE) {
      if (HandleServantCmds)
          if (!Bt(&Fs->task_flags,TSSf_DONT_CHANGE_DESC))
              MemCpy(Fs->task_descriptor,Fs->task_descriptor2,TSS_DESC_LENGTH);
      CallExtNum(EXT_FLUSH_MSGS,NULL);
      Fs->task_flags|= 1<<TSSf_IDLE|1<<TSSf_AWAITING_MSG;
      SwapInNextTask;
  }
}

void InitLocalTask()
{
  InitDisplay;
  Bts(&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);
}

void InitUserTask()
{
  Bts(&Fs->task_flags,TSSf_LOCAL_USER);
  InitLocalTask;
}


asm {CP_USER_CMD_LINE::};
void UserCmdLine()
{
  InitUserTask;
  Fs->user_num=++num_spawned_users;
  CallExtNum(EXT_EXECUTE_FILE,"User.CPZ",FALSE);
  if (!Bts(&Fs->display_flags,DISPLAYf_SHOW))
      Debugger;
  CallExtStr("ContUserTask");
}

void ServantUserCmdLine()
{
  Bts(&Fs->task_flags,TSSf_SERVANT_USER);
  InitUserTask;
  CallExtNum(EXT_EXECUTE_FILE,"Servant.CPZ",FALSE);
  ContServantTask;
}

TssStruct *SpawnUser(I1 *st=NULL)
{
  TssStruct *tss=Spawn(&UserCmdLine);
  WaitTaskIdle(tss);
  if (st)
      XTalk(tss,st);
  return tss;
}

void FinishOffTss(TssStruct *tss)
{ //$FG,2$We delay freeing in case lingering$FG$
  //$FG,2$references are made to tss's.$FG$
  FreeMemBlkList(tss->code_heap);
  Free(tss->code_heap);
  if (tss->data_heap!=tss->code_heap) {
      FreeMemBlkList(tss->data_heap);
      Free(tss->data_heap);
  }
  Free(tss);
}

asm {END_TASK::};
U8 EndTask()
{
  TssStruct *tempt,*tempt1;
  TssCmdStruct *tempc,*tempc1,*tempc2;
  if (Fs==sys_task_being_screen_updated) {
      Fs->task_flags|=1<<TSSf_SUSPENDED|1<<TSSf_KILL_TASK;
      return Fs->next_tss;
  }
  if (Fs->end_task_cb) {
      Fs->wake_time=0;
      Fs->task_flags&=~(1<<TSSf_KILL_TASK+1<<TSSf_AWAITING_MSG|1<<TSSf_SUSPENDED);
      Fs->rip=Fs->end_task_cb;
      Fs->end_task_cb=NULL;
      return Fs;
  }
  if (Fs->parent_tss) {
      if (Fs->parent_tss->popup_tss==Fs) {
          Fs->parent_tss->popup_tss=NULL;
          Kill(Fs->parent_tss,FALSE);
          return Fs->parent_tss;
      }
      if (Fs->parent_tss->dbg_tss==Fs)
          Fs->parent_tss->dbg_tss=NULL;
  }

  ReleaseTaskPartitions;
  ReleaseTaskBlkDevs;
  tempt1=(&Fs->next_child_tss)><(U1 *)-offset(TssStruct.next_sibling_tss);
  tempt=tempt1->next_sibling_tss;
  if (tempt!=tempt1) {
      do {
          Bts(&tempt->task_flags,TSSf_KILL_TASK);
          tempt=tempt->next_sibling_tss;
      } while (tempt!=tempt1);
      return Fs->next_tss;
  }
  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 (IsInDebugger)
          CallExtNum(EXT_EXIT_DEBUGGER);
      if (!Gs->num)
          SingleUser(OFF);
      sys_cur_focus_task=NULL;
      ip_inhibit_win_operations=FALSE;
  }


//Remque
  Fs->in_queue_signature=0;

  tempt =Fs->next_input_filter_tss;
  tempt1=Fs->last_input_filter_tss;
  tempt1->next_input_filter_tss=tempt;
  tempt ->last_input_filter_tss=tempt1;

  tempt =Fs->next_sibling_tss;
  tempt1=Fs->last_sibling_tss;
  tempt1->next_sibling_tss=tempt;
  tempt ->last_sibling_tss=tempt1;

  tempt =Fs->next_tss;
  tempt1=Fs->last_tss;
  tempt1->next_tss=tempt;
  tempt ->last_tss=tempt1;

  if (sys_winmgr_tss) {
      Fs->next_tss=Gs->dying_tss_list;
      Gs->dying_tss_list=Fs;
  } else
      FinishOffTss(Fs); //dangerous (stack in use)
  return tempt;
}

void FinishOffDyingTsses()
{ //$FG,2$We delay freeing in case lingering$FG$
  //$FG,2$references are made to tss's.$FG$
  BoolI1 old_preempt=Preempt(OFF);
  TssStruct *tss1,*tss2;
  if (tss1=Gs->dying_tss_list) {
      do {
          tss2=tss1->next_tss;
          FinishOffTss(tss1);
          tss1=tss2;
      } while (tss1);
      Gs->dying_tss_list=NULL;
  }
  Preempt(old_preempt);
}
Home

Kernel
StartUp
Scheduler
Memory
MultiCore
Interrupts
BitMaps
Screen
Plot
Compiler Frontend
Compiler Mid
Compiler Backend
Kernel
Historical capture: 2008-08-02. Home | Power on LoseThos | Sources and changes