SysHashTable *NewHashTable(U8 size,TssStruct *mem_tss=NULL) { SysHashTable *tempht; tempht=MAllocZ(offset(SysHashTable.body)+size<<3,mem_tss); tempht->mask=size-1; return tempht; } U8 AllocGdtTabEntry() { U8 old_flags=GetFlags,result; U4 *d; Cli; if (!(result=free_gdt_list)) Debugger; d=gdttab+result; free_gdt_list=*d; SetFlags(old_flags); return result; } void FreeGdtTabEntry(U8 i) { U8 old_flags=GetFlags; U4 *d=gdttab+i; Cli; *d=free_gdt_list; free_gdt_list=i; SetFlags(old_flags); } /* U8 CreateCodeSelector(U8 phy_add) { U8 result,*d,*d1,old_flags=GetFlags; Cli; result=AllocGdtTabEntry; d=gdttab+result; d1=d+4; *d =0x0000FFFF; *d1=0x00CF9A00; d=d+2; *d|=(phy_add & 0x00FFFFFF); *d1|=(phy_add & 0xFF000000); d1+=4; *d1=0; d1+=4; *d1=0; SetFlags(old_flags); return result; } */ U8 CreateTssSelector(U8 phy_add) { U8 result,old_flags=GetFlags; U4 *d,*d1; Cli; result=AllocGdtTabEntry; d=gdttab+result; d1=d+4; *d =0x0000FFFF; *d1=0x008F8900; d=d+2; *d|=(phy_add & 0x00FFFFFF); *d1|=(phy_add & 0xFF000000); d1+=4; *d1=0; d1+=4; *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+result; d1=d+4; *d =0x0000FFFF; *d1=0x00CF9200; d=d+2; *d |=(phy_add & 0x00FFFFFF); *d1|=(phy_add & 0xFF000000); d1+=4; *d1=0; d1+=4; *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=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=tss; pred->last_sibling_tss=tss; tss ->last_sibling_tss=last; tss ->next_sibling_tss=pred; SetFlags(old_flags); } asm {CP_INIT_TSS::} U8 InitTss(TssStruct *tss,U8 stk) { //Returns Fs of task void *b; tss->absolute_address=tss; tss->next_tss=tss; tss->last_tss=tss; tss->rflags=SYS_NORMAL_RFLAGS; b=&tss->next_child_tss-offset(TssStruct.next_sibling_tss); tss->next_child_tss=b; tss->last_child_tss=b; b=&tss->next_servant_cmd; tss->next_servant_cmd=b; tss->last_servant_cmd=b; b=&tss->next_master_cmd; tss->next_master_cmd=b; tss->last_master_cmd=b; tss->next_input_filter_tss=tss; tss->last_input_filter_tss=tss; b=&tss->next_mem_blk; tss->next_mem_blk=b; tss->last_mem_blk=b; b=&tss->next_lex; tss->next_lex=b; tss->last_lex=b; b=&tss->next_except; tss->next_except=b; tss->last_except=b; b=&tss->next_ode; tss->next_ode=b; tss->last_ode=b; tss->hash_table=NewHashTable(0x1000,tss); b=MAlloc(stk,tss); tss->stack_base=b; tss->stack_size=MSize(b); b+=stk; tss->rsp=b; tss->answers_displayed=1; //from 0-8 return tss; } asm {CP_INIT_CPU_STRUCT::} U8 InitCPUStruct(U8 num,CPUStruct *c) { MemSet(c,0,sizeof(CPUStruct)); c->num=num; c->absolute_address=c; c->idle_factor=0.01; if (num) { c->grbase=GrBitMapNew(BMT_COLOR4,GR_WIDTH,GR_HEIGHT); c->grbase->flags|=BMF_SCREEN_BITMAP; GrClear2(c->grbase); } return c; } U8 InitStk(U8 size) { U8 *st=MAllocZ(size); return st+size; } U2 InitTssStruct2() { TssStruct2 *tss2; tss2=MAllocZ(sizeof(TssStruct2)); tss2->io_map_offset=offset(TssStruct2.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, I1 *desc=NULL, TssStruct *parent=NULL, //NULL means adam I1 *account=NULL, U8 stk=DEFAULT_STACK, BoolU4 add_to_queue=TRUE) { U8 old_flags=GetFlags; TssStruct *tss=MAllocZ(sizeof(TssStruct),Gs->cain_tss); SysAccntStruct *tempa; if (!desc) desc="Unnamed Task"; if (!parent) parent=Gs->cain_tss; tss->parent_tss=parent; tss->gs=parent->gs; InitTss(tss,stk); tss->rip=start_add; tss->rsp-=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->account=tss->parent_tss->account; if (account) { if (tempa=CallExtStr("FindSysAccnt",account)) tss->account=tempa; } //The following is a convenient way to //initialize the FPU, but not very professional. //I'll fix it when I have time. MemCpy(&tss->fpu,&parent->fpu,108); 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)) return NULL; result=AMAlloc(sizeof(TssCmdStruct)); result->master_tss=master; result->cmd_code=TSSCT_EXECUTE_STR; result->flags=flags; result->data=ANewStr(data); Cli; servant->task_flags&=~(1<last_servant_cmd); servant->task_flags&=~(1<task_flags,TSSf_SUSPENDED); SwapInNext; } SetFlags(old_flags); return result; } TssCmdStruct *QueueTextInput(TssStruct *servant,TssStruct *master, I1 *data,U8 flags) { U8 old_flags=GetFlags; BoolU4 old_preempt=Preempt(OFF); U1 *input_filter_start_add; TssCmdStruct *result; TssStruct *tss; if (!data || !ValidateTss(servant) || master && !ValidateTss(master)) { 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=ANewStr(data); if (input_filter_start_add=ext[EXT_INPUT_FILTER_TASK]) { if (flags&1<next_input_filter_tss==servant) { tss=Spawn(input_filter_start_add, "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<last_servant_cmd); tss->task_flags&=~(1<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<last_servant_cmd); servant->task_flags&=~(1<next_master_cmd; tempc=tempc1->next; while (tempc!=tempc1) { if (!rqst || rqst==tempc) { RemQue(tempc); if (result) *result=tempc->result; AFree(tempc->data); AFree(tempc); SetFlags(old_flags); return TRUE; } tempc=tempc->next; } SetFlags(old_flags); return FALSE; } void WaitTskIdle(TssStruct *tss) { U8 old_flags=GetFlags; TssStruct *tss1; TssCmdStruct *tempc; 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; SwapInNext; } SetFlags(old_flags); } void Msg(U8 code,U8 p1,U8 p2,U8 flags=0) { if (Bt(&Fs->task_flags,TSSf_INPUT_FILTER_TASK)) { QueueMsg(Fs->last_input_filter_tss,NULL,code,p1,p2, flags| 1<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); else tempc->result=CallExtNum(EXT_EXECUTE_FILE,tempc->data); } 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 { AFree(tempc->data); AFree(tempc); Exit; } } else { if (!Bt(&tempc->flags,TSSCf_EXIT_ON_COMPLETE)) { AFree(tempc->data); AFree(tempc); goto start_over; } else { AFree(tempc->data); AFree(tempc); Exit; } } } else break; } SetFlags(old_flags); return cnt; } void ContinueServantTask() { Preempt(OFF); 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<account; StrCpy(result,"::/LT/Accts/"); if (sa) StrCat(result,sa->name); else StrCat(result,"User"); *result=PartitionToDrive(default_partition); return result; } void InitSysTask() { InitCrt; Fs->text_attribute=(WHITE<<4)+PURPLE; Fs->border_attribute=(WHITE<<4)+LTPURPLE; Fs->win_top++; } void InitLocalTask() { InitCrt; Bts(&Fs->crt_flags,CRTf_HAS_CLOSE_WIN); Fs->text_attribute=(WHITE<<4)+BLUE; Fs->border_attribute=(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"); CallExtStr("ContinueUserTask"); } void SysCmdLine() { InitSysTask; Cd("HOME"); CallExtNum(EXT_EXECUTE_FILE,"System.CPZ"); ContinueServantTask; } void ServantUserCmdLine() { InitUserTask; CallExtNum(EXT_EXECUTE_FILE,"Servant.CPZ"); ContinueServantTask; } TssStruct *SpawnUser(I1 *st=NULL) { TssStruct *tss=Spawn(&UserCmdLine); WaitTskIdle(tss); if (st) XTalk(tss,st); return tss; } void FinishOffTss(TssStruct *tss) { if (Gs->cpu_heap) { Free(tss->hash_table,Gs->cain_tss); Free(tss->stack_base,Gs->cain_tss); } FreeMemBlkList(tss); Free(tss,Gs->cain_tss); } asm {END_TASK::} U8 EndTask() { TssStruct *tempt,*tempt1; TssCmdStruct *tempc,*tempc1,*tempc2; Preempt(OFF); if (Fs->end_task_cb) { Btr(&Fs->task_flags,TSSf_KILL_TASK); 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; tempt1=&Fs->next_child_tss-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; AFree(tempc->data); AFree(tempc); tempc=tempc2; } tempc1=&Fs->next_master_cmd; tempc=tempc1->next; while (tempc!=tempc1) { tempc2=tempc->next; AFree(tempc->data); AFree(tempc); tempc=tempc2; } LBts(&sys_semas[SYS_SEMA_CLEAR_SCREEN_TEXT],0); Cli; //TDOD: might be too long if (sys_cur_focus_task==Fs) { sys_cur_focus_task=0; 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_update_screen_tss) { Fs->next_tss=Gs->dying_tss_list; Gs->dying_tss_list=Fs; } else FinishOffTss(Fs); //dangerous (stack in use) return tempt; } void FinishOffDyingTsses() { BoolU4 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); }