hschumann2/TempleOS-Source-Code
0847
1 2U0 Exit()3{//Terminate own task.4 if (Fs==sys_focus_task && IsDbgMode) {5 LBts(&Fs->task_flags,TASKf_KILL_AFTER_DBG);6 G;7 } else {8 if (sys_staff_mode_flag)9 AdamLog("%p:%p:%p:%p:%p:%p\n",Caller(0),Caller(1),Caller(2),Caller(3),10 Caller(4),Caller(5),Caller(6),Caller(7));11 if (!Gs->num && !IsDbgMode)12 SingleUser(OFF);13 Fs->rflags=GetRFlags;14 Fs->rsp=GetRSP;15 Fs->rbp=GetRBP;16 Fs->rip=$;17 CLI18 LBts(&Fs->task_flags,TASKf_KILL_TASK);19 TaskEndNow;20 }21}22 23Bool TaskValidate(CTask *task)24{//return TRUE if task looks valid.25 if (!(0<task<=I32_MAX) || task->addr!=task ||26 task->task_signature!=TASK_SIGNATURE_VAL)27 return FALSE;28 else29 return TRUE;30}31 32I64 BirthWait(CTask **_task,I64 task_num=-1)33{//Wait for task valid and not task_num.34 while (!TaskValidate(*_task)||(*_task)->task_num==task_num)35 Yield;36 return (*_task)->task_num;37}38 39U0 DeathWait(CTask **_task,Bool send_exit=FALSE)40{//Wait for task death.41 if (send_exit && TaskValidate(*_task)) {42 TaskWait(*_task,TRUE);43 XTalk(*_task,"Exit;\n");44 }45 while (TaskValidate(*_task))46 Yield;47}48 49Bool Kill(CTask *task,Bool wait=TRUE,Bool just_break=FALSE)50{//Terminate other task.51 I64 i;52 if (TaskValidate(task)) {53 if (just_break) {54 if (task!=Fs)55 Break;56 else {//TODO wait57 sys_focus_task=task;58 LBts(sys_ctrl_alt_flags,CTRL_ALT_C);59 return TRUE;60 }61 } else {62 if (task!=sys_winmgr_task) {63 for (i=0;i<mp_cnt;i++)64 if (task==cpu_structs[i].seth_task)65 return FALSE;66 LBts(&task->task_flags,TASKf_KILL_TASK);67 if (wait) {68 do Yield;69 while (TaskValidate(task) && Bt(&task->task_flags,TASKf_KILL_TASK));70 }71 return TRUE;72 }73 }74 }75 return FALSE;76}77 78Bool Suspend(CTask *task=NULL,Bool state=TRUE)79{//Tell scheduler to skip task.80 Bool res;81 if (!task) task=Fs;82 PUSHFD83 CLI84 if (TaskValidate(task))85 res=LBEqu(&task->task_flags,TASKf_SUSPENDED,state);86 else87 res=FALSE;88 POPFD89 return res;90}91 92Bool IsSuspended(CTask *task=NULL)93{//You might use this in a DrawIt() or Animatetask().94 if (!task) task=Fs;95 if (TaskValidate(task))96 return Bt(&task->task_flags,TASKf_SUSPENDED);97 else98 return FALSE;99}100 101CTaskStk *TaskStkNew(I64 stk_size,CTask *task)102{103 CTaskStk *tmps=MAlloc(stk_size+offset(CTaskStk.stk_base),task);104 tmps->next_stk=NULL;105 tmps->stk_ptr=NULL;106 tmps->stk_size=MSize(tmps)-offset(CTaskStk.stk_base);107 return tmps;108}109 110#exe {Option(OPTf_NO_REG_VAR,ON);};111argpop I64 CallStkGrow(I64 stk_size_threshold,I64 stk_size,112 /*argpop*/I64 (*fp_addr)(...),...)113{//Grow stk in call with any fixed num of args.114//See ::/Demo/StkGrow.HC.115 CTaskStk *tmps,*tmps2,**_stk;116 I64 res,*rsp,*rsp2,*old_stk;117 118 if (UnusedStk>=stk_size_threshold) {119 120 asm {121 LEAVE122 POP RAX //return addr123 ADD RSP,16 //pop threshold,stk_size124 POP RBX // *f125 ADD RSP,8 //pop ARGC126 PUSH RAX127 JMP RBX //CALL fp_addr()128 };129 130 } else {131 132 tmps2=TaskStkNew(stk_size,Fs);133 tmps2->next_stk=tmps=Fs->stk;134 rsp2=(&tmps2->stk_base)(U8 *)+tmps2->stk_size;135 old_stk=rsp=&argv[argc];136 while (argc-->0)137 *--rsp2=*--rsp;138 _stk=&Fs->stk;139 tmps->stk_ptr=rsp=GetRSP;140 asm {141 IMPORT _FREE; //We are in a function, not at glbl scope.142//The compiler treats these in isolation.143 144 PUSHFD145 POP RDX //flags146 CLI147 MOV RBX,U64 &tmps2[RBP]148 MOV RAX,&_stk[RBP]149 MOV U64 [RAX],RBX //Fs->stk=tmps2150 MOV RSP,U64 &rsp2[RBP]151 PUSH RDX152 POPFD153 154 CALL U64 &fp_addr[RBP]155 MOV U64 &res[RBP],RAX156 157 PUSHFD158 POP RDX //flags159 CLI160 MOV RBX,U64 &tmps[RBP]161 MOV RAX,&_stk[RBP]162 MOV U64 [RAX],RBX //Fs->stk=tmps163 MOV RSP,U64 &rsp[RBP]164 PUSH RDX165 POPFD166 167 PUSH U64 &tmps2[RBP]168 CALL _FREE169 170 MOV RDX,U64 &old_stk[RBP]171 MOV RBX,U64 8[RBP]172 MOV RAX,U64 &res[RBP]173 MOV RBP,U64 [RBP]174 MOV RSP,RDX175 JMP RBX //return176 };177 }178 return 0; //dummy to get rid of warning179}180;181#exe {Option(OPTf_NO_REG_VAR,OFF);};182 183I64 TaskInit(CTask *task,I64 stk_size)184{//Returns Fs of task185 CTaskStk *tmps;186 187 QueInit(&task->code_heap->next_mem_blk);188 task->code_heap->last_mergable=NULL;189 if (task->code_heap!=task->data_heap) {190 QueInit(&task->data_heap->next_mem_blk);191 task->data_heap->last_mergable=NULL;192 }193 194 task->addr=task->next_task=task->last_task=195 task->next_input_filter_task=task->last_input_filter_task=196 task;197 198 task->task_num=sys_num_spawned_tasks++;199 200 task->rflags=RFLAGG_NORMAL;201 task->win_inhibit=WIG_TASK_DFT;202 203 task->next_child_task=task->last_child_task=204 (&task->next_child_task)(U8 *)-offset(CTask.next_sibling_task);205 206 JobCtrlInit(&task->srv_ctrl);207 QueInit(&task->next_cc);208 QueInit(&task->next_except);209 QueInit(&task->next_ctrl);210 QueInit(&task->next_ode);211 212 task->fpu_mmx=MAllocAligned(sizeof(CFPU),0x10,task);213 MemCpy(task->fpu_mmx,214 SYS_FIXED_AREA+offset(CSysFixedArea.init_fpu_mmx),sizeof(CFPU));215 216 task->hash_table=HashTableNew(TASK_HASH_TABLE_SIZE,task);217 218 if (!stk_size)219 stk_size=MEM_DFT_STK;220 task->stk=tmps=TaskStkNew(stk_size,task);221 task->rsp=(&tmps->stk_base)(U8 *)+tmps->stk_size;222 223 task->text_attr =WHITE<<4+BLUE;224 task->border_src =BDS_CONST;225 task->border_attr =DrvTextAttrGet(':');226 task->title_src =TTS_CONST;227 task->win_left =1;228 task->win_right =text.cols-2;229 task->win_top =13;230 task->win_bottom =text.rows-2;231 232 if (blkdev.home_dir) {//Beware Adam TaskInit. I guess ok until DskChg().233 task->cur_dv=blkdev.let_to_drv[*blkdev.home_dir-'A'];234 task->cur_dir=StrNew(blkdev.home_dir+2,task);235 } else236 task->cur_dir=StrNew("/Home",task);237 238 Seed(,task);239 240 return task;241}242 243CTask *Spawn(U0 (*fp_start_addr)(U8 *data),U8 *data=NULL,U8 *task_name=NULL,244 I64 target_cpu=-1, //-1 for current CPU. See multi-core.245 CTask *parent=NULL, //NULL means adam246 I64 stk_size=0, //0=default247 I64 flags=1<<JOBf_ADD_TO_QUE)248{//Create task on core running at address.249//Alloc CTask structure from code heap so addr will be short.250 //Could be alloced off of data heap.251 CTask *task;252 if (target_cpu>=0)253 return SpawnQue(fp_start_addr,data,task_name,target_cpu,254 parent,stk_size,flags);255 task=CAlloc(sizeof(CTask),adam_task->code_heap);256 task->task_signature=TASK_SIGNATURE_VAL;257 if (!task_name) task_name="Unnamed Task";258 if (!parent) parent=Gs->seth_task;259 task->parent_task=parent;260 task->gs=parent->gs;261 if (sys_code_bp)262 task->code_heap=HeapCtrlInit(,task,sys_code_bp);263 if (sys_data_bp)264 task->data_heap=HeapCtrlInit(,task,sys_data_bp);265 else266 task->data_heap=task->code_heap;267 TaskInit(task,stk_size);268 task->rip=fp_start_addr;269 task->rsp(U8 *)-=8;270 *task->rsp=data;271 task->rsp(U8 *)-=8;272 *task->rsp=&Exit;273 task->hash_table->next=parent->hash_table;274 MemCpy(task->task_name,task_name,TASK_NAME_LEN);275 StrCpy(task->task_title,task->task_name);276 task->title_src=TTS_TASK_NAME;277 PUSHFD278 CLI279 if (Bt(&flags,JOBf_ADD_TO_QUE)) {280 TaskQueInsChild(task);281 TaskQueIns(task);282 }283 POPFD284 return task;285}286 287U0 TaskDerivedValsUpdate(CTask *task=NULL,Bool update_z_buf=TRUE)288{//Those things calculated from other variables.289 if (!task) task=Fs;290 PUSHFD291 CLI292 while (LBts(&task->task_flags,TASKf_TASK_LOCK))293 PAUSE294 WinDerivedValsUpdate(task);295 if (fp_update_ctrls)296 (*fp_update_ctrls)(task);297 if (update_z_buf && Bt(&task->display_flags,DISPLAYf_SHOW))298 LBts(&sys_semas[SEMA_UPDATE_WIN_Z_BUF],0);299 LBtr(&task->task_flags,TASKf_TASK_LOCK);300 POPFD301}302 303I64 ExeCmdLine(CCmpCtrl *cc)304{//Terminal JIT-compile-and-execute loop for CCmpCtrl.305 I64 res=0,type,old_title_src=Fs->title_src;306 U8 *ptr,*ptr2,*ptr3,*machine_code,*old_task_title=StrNew(Fs->task_title);307 F64 t0;308 CDocEntry *doc_e;309 CDoc *doc;310 if (Fs->title_src!=TTS_LOCKED_CONST)311 Fs->title_src=TTS_CUR_LEX;312 while (cc->token &&313 (cc->token!='}' || !(cc->flags & CCF_EXE_BLK)) ) {314 if (Fs->title_src==TTS_CUR_LEX) {315 ptr2=&Fs->task_title;316 ptr3=ptr2+STR_LEN-1;317 if (cc->lex_include_stk->flags & LFSF_DOC) {318 doc_e=cc->lex_include_stk->cur_entry;319 doc=cc->lex_include_stk->doc;320 while (doc_e!=doc && ptr2<ptr3) {321 switch (doc_e->type_u8) {322 case DOCT_TEXT:323 ptr=doc_e->tag;324 while (*ptr && ptr2<ptr3)325 *ptr2++=*ptr++;326 break;327 case DOCT_TAB:328 case DOCT_NEW_LINE:329 *ptr2++='.';330 break;331 }332 doc_e=doc_e->next;333 }334 if (ptr2<ptr3) *ptr2=0;335 } else336 if ((ptr=cc->lex_include_stk->line_start) && *ptr)337 MemCpy(ptr2,ptr,STR_LEN-1);338 }339 cc->flags&=~CCF_HAS_MISC_DATA;340 machine_code=LexStmt2Bin(cc,&type);341 if (machine_code!=INVALID_PTR) {342 if (!(cc->flags&CCF_JUST_LOAD)) {343 t0=tS;344 res=Call(machine_code);345 Fs->answer=res;346 Fs->answer_type=type;347 Fs->answer_time=tS-t0;348 Fs->new_answer=TRUE;349 cc->pmt_line=0;350 }351 if (!(cc->flags&CCF_HAS_MISC_DATA))352 Free(machine_code);353 }354 }355 if (Fs->title_src!=TTS_LOCKED_CONST) {356 Fs->title_src=old_title_src;357 StrCpy(Fs->task_title,old_task_title);358 }359 Free(old_task_title);360 if (cc->flags&CCF_JUST_LOAD) {361 if (cc->error_cnt)362 return FALSE;363 else364 return TRUE;365 } else366 return res;367}368 369U0 SrvTaskCont()370{//Act as server task in a loop handling commands.371 I64 old_flags=GetRFlags;372 FlushMsgs;373 while (TRUE) {374 CLI375 if (JobsHndlr(old_flags) && Fs->title_src==TTS_TASK_NAME)376 MemCpy(Fs->task_title,Fs->task_name,TASK_NAME_LEN);377 FlushMsgs;378 LBts(&Fs->task_flags,TASKf_IDLE);379 LBts(&Fs->task_flags,TASKf_AWAITING_MSG);380 Yield;381 SetRFlags(old_flags);382 }383}384 385U0 UserTaskCont()386{//Terminal key-input-execute loop.387 CCmpCtrl *cc;388 CDoc *doc;389 Bool cont=TRUE;390 do {391 cc=CmpCtrlNew(,CCF_CMD_LINE|CCF_PMT|CCF_QUESTION_HELP);392 QueIns(cc,Fs->last_cc);393 try {394 Lex(cc);395 ExeCmdLine(cc);396 cont=Bt(&cc->flags,CCf_PMT);397 QueRem(cc);398 CmpCtrlDel(cc);399 } catch {400 if ((doc=Fs->put_doc) && doc->doc_signature==DOC_SIGNATURE_VAL)401 DocUnlock(doc);402 PutExcept;403 }404 } while (cont);405}406 407U0 SrvCmdLine(I64 dummy=0)408{409 no_warn dummy;410 Fs->win_inhibit=WIG_USER_TASK_DFT;411 CallExtStr("SrvStartUp");412 SrvTaskCont;413}414 415U0 UserCmdLine(I64 dummy=0)416{//A user task ends-up calling this.417 no_warn dummy;418 Fs->win_inhibit=WIG_USER_TASK_DFT;419 CallExtStr("UserStartUp");420 if (!LBts(&Fs->display_flags,DISPLAYf_SHOW))421 Dbg;422 UserTaskCont;423}424 425CTask *User(U8 *fmt=NULL,...)426{//Create user term task.427 U8 *st;428 CTask *task=Spawn(&UserCmdLine);429 TaskWait(task);430 if (fmt) {431 st=StrPrintJoin(NULL,fmt,argc,argv);432 XTalk(task,st);433 Free(st);434 }435 return task;436}437 438U0 TaskDel(CTask *task)439{//We delay freeing in case lingering ptr to reincarnated.440 HeapCtrlDel(task->code_heap);441 if (task->data_heap!=task->code_heap)442 HeapCtrlDel(task->data_heap);443 Free(task);444}445 446I64 TaskEnd()447{//Called with irq's off.448 CTask *task=Fs,*tmpt,*tmpt1;449 if (task==sys_task_being_scrn_updated) {450 LBts(&task->task_flags,TASKf_KILL_TASK);451 return task->next_task;452 }453 if (task->task_end_cb) {454 task->wake_jiffy=0;455 LBtr(&task->task_flags,TASKf_KILL_TASK);456 TaskRstAwaitingMsg(task);457 Suspend(task,FALSE);458 task->rip=task->task_end_cb;459 task->task_end_cb=NULL;460 return task;461 }462 if (task->parent_task && task->parent_task->popup_task==task) {463 task->parent_task->popup_task=NULL;464 Kill(task->parent_task,FALSE);465 return task->parent_task;466 }467 468 DrvsRelease;469 BlkDevsRelease;470 tmpt1=(&task->next_child_task)(U8 *)-offset(CTask.next_sibling_task);471 tmpt=tmpt1->next_sibling_task;472 if (tmpt!=tmpt1) {473 do {474 LBts(&tmpt->task_flags,TASKf_KILL_TASK);475 tmpt=tmpt->next_sibling_task;476 } while (tmpt!=tmpt1);477 return task->next_task;478 }479 if (LBtr(&task->display_flags,DISPLAYf_SHOW))480 LBts(&sys_semas[SEMA_UPDATE_WIN_Z_BUF],0);481 482 while (LBts(&task->task_flags,TASKf_TASK_LOCK))483 PAUSE484 while (LBts(&task->srv_ctrl.flags,JOBCf_LOCKED))485 PAUSE486 487 JobQueDel(&task->srv_ctrl.next_waiting);488 JobQueDel(&task->srv_ctrl.next_done);489 490 if (IsRaw)491 VGAFlush;492 493 if (sys_focus_task==task) {494 if (!Gs->num)495 SingleUser(OFF);496 sys_focus_task=NULL;497 if (fp_set_std_palette)498 (*fp_set_std_palette)();499 }500 501 //QueRem502 task->task_signature(I64)=0;503 504 tmpt =task->next_input_filter_task;505 tmpt1=task->last_input_filter_task;506 tmpt1->next_input_filter_task=tmpt;507 tmpt ->last_input_filter_task=tmpt1;508 509 tmpt =task->next_sibling_task;510 tmpt1=task->last_sibling_task;511 tmpt1->next_sibling_task=tmpt;512 tmpt ->last_sibling_task=tmpt1;513 514 tmpt =task->next_task; //save to return515 TaskQueRem(task);516 517 LBtr(&task->srv_ctrl.flags,JOBCf_LOCKED);518 LBtr(&task->task_flags,TASKf_TASK_LOCK);519 520 task->wake_jiffy=cnts.jiffies+DYING_JIFFIES;521 while (LBts(&Gs->cpu_flags,CPUf_DYING_TASK_QUE))522 PAUSE523 QueIns(task,Gs->last_dying);524 LBtr(&Gs->cpu_flags,CPUf_DYING_TASK_QUE);525 526 return tmpt;527}528 529U0 TaskKillDying()530{//Delay freeing to prevent asking for trouble with quick reincarnations.531//What if the user is doing this: DoTreeCheckers.532 CTaskDying *task,*task1;533 if (Gs->kill_jiffy<cnts.jiffies) {//Avoid doing as many lock operations.534 while (LBts(&Gs->cpu_flags,CPUf_DYING_TASK_QUE))535 PAUSE536 task=Gs->next_dying;537 while (task!=&Gs->next_dying && task->wake_jiffy<cnts.jiffies) {538 task1=task->next;539 QueRem(task);540 TaskDel(task);541 task=task1;542 }543 LBtr(&Gs->cpu_flags,CPUf_DYING_TASK_QUE);544 Gs->kill_jiffy=cnts.jiffies+DYING_JIFFIES;545 }546}547 