// 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