hschumann2/TempleOS-Source-Code
0838
1 2U0 JobDel(CJob *tmpc)3{//Free one cmd node.4 Free(tmpc->aux_str);5 Free(tmpc);6}7 8U0 JobQueDel(CJob *head)9{10 CJob *tmpc=head->next,*tmpc1;11 while (tmpc!=head) {12 tmpc1=tmpc->next;13 QueRem(tmpc);14 JobDel(tmpc);15 tmpc=tmpc1;16 }17}18 19U0 JobCtrlInit(CJobCtrl *ctrl)20{21 QueInit(&ctrl->next_waiting);22 QueInit(&ctrl->next_done);23 ctrl->flags=0;24}25 26U0 TaskRstAwaitingMsg(CTask *task=NULL)27{//Pop-ups get parent messages so wake-up our pop-ups if we got a msg.28 if (!task) task=Fs;29 PUSHFD30 CLI31 do {32 if (TaskValidate(task))33 LBtr(&task->task_flags,TASKf_AWAITING_MSG);34 else35 break;36 } while (task=task->popup_task);37 POPFD38}39 40CJob *TaskExe(CTask *srv,CTask *master,U8 *data,I64 flags)41{//Queues a request to compile and execute src code text.42 CJob *res;43 if (!data || !TaskValidate(srv) || master && !TaskValidate(master) ||44 srv->popup_task && !Bt(&srv->task_flags,TASKf_FILTER_INPUT))45 return NULL;46 res=ACAlloc(sizeof(CJob));47 res->master_task=master;48 res->job_code=JOBT_EXE_STR;49 res->flags=flags;50 res->aux_str=AStrNew(data);51 res->ctrl=&srv->srv_ctrl;52 53 PUSHFD54 CLI55 while (LBts(&srv->srv_ctrl.flags,JOBCf_LOCKED))56 PAUSE57 if (!TaskValidate(srv)) {58 LBtr(&srv->srv_ctrl.flags,JOBCf_LOCKED);59 POPFD60 JobDel(res);61 return NULL;62 } else {63 LBtr(&srv->task_flags,TASKf_IDLE);64 TaskRstAwaitingMsg(srv);65 QueIns(res,srv->srv_ctrl.last_waiting);66 LBtr(&srv->srv_ctrl.flags,JOBCf_LOCKED);67 if (Bt(&flags,JOBf_WAKE_MASTER)) {68 Suspend(master);69 Yield;70 }71 }72 POPFD73 return res;74}75 76CJob *TaskText(CTask *srv,CTask *master,U8 *data,I64 flags)77{//Post StdIn text to servant task. Tell who the master task is.78 CJob *res;79 CTask *task;80 if (!data || !TaskValidate(srv) || master && !TaskValidate(master) ||81 srv->popup_task && !Bt(&srv->task_flags,TASKf_FILTER_INPUT))82 return NULL;83 res=ACAlloc(sizeof(CJob));84 res->master_task=master; //in case somebody cares85 res->job_code=JOBT_TEXT_INPUT;86 res->flags=flags;87 res->aux_str=AStrNew(data);88 89 PUSHFD90 task=srv->last_input_filter_task;91 if (Bt(&flags,JOBf_HIGHEST_PRIORITY) || task==srv) {92 if (task!=srv)93 TaskWait(srv);94 task=Spawn(&InputFilterTask,NULL,"Input Filter",,srv);95 CLI96 task->next_input_filter_task=srv->next_input_filter_task;97 task->last_input_filter_task=srv;98 srv->next_input_filter_task=task;99 task->next_input_filter_task->last_input_filter_task=task;100 } else {101 CLI102 task=srv->next_input_filter_task;103 }104 res->ctrl=&task->srv_ctrl;105 while (LBts(&task->srv_ctrl.flags,JOBCf_LOCKED))106 PAUSE107 if (!TaskValidate(task)) {108 JobDel(res);109 res=NULL;110 } else {111 LBtr(&task->task_flags,TASKf_IDLE);112 TaskRstAwaitingMsg(task);113 QueIns(res,task->srv_ctrl.last_waiting);114 LBtr(&task->srv_ctrl.flags,JOBCf_LOCKED);115 }116 POPFD117 return res;118}119 120CJob *TaskMsg(CTask *_srv,CTask *master,121 I64 msg_code,I64 arg1,I64 arg2,I64 flags)122{//Post message to servant task. Tell who the master task is.123//See flags and msg_code.124 CJob *tmpc1,*tmpc;125 CTask *srv=_srv;126 if (!TaskValidate(srv) || master && !TaskValidate(master)||127 srv->popup_task && !Bt(&srv->task_flags,TASKf_FILTER_INPUT))128 return NULL;129 tmpc=ACAlloc(sizeof(CJob));130 tmpc->master_task=master;131 tmpc->job_code=JOBT_MSG;132 tmpc->msg_code=AbsI64(msg_code); //negative means do a down and up133 tmpc->aux1=arg1;134 tmpc->aux2=arg2;135 tmpc->flags=flags;136 PUSHFD137 if (Bt(&sys_semas[SEMA_RECORD_MACRO],0) &&138 srv!=sys_macro_task && msg_code==MSG_KEY_DOWN) {139 tmpc1=AMAllocIdent(tmpc);140 CLI141 QueIns(tmpc1,sys_macro_head.last);142 }143 CLI144 while (Bt(&srv->task_flags,TASKf_FILTER_INPUT) &&145 !Bt(&flags,JOBf_DONT_FILTER))146 srv=srv->next_input_filter_task;147 tmpc->ctrl=&srv->srv_ctrl;148 while (LBts(&srv->srv_ctrl.flags,JOBCf_LOCKED))149 PAUSE150 if (!TaskValidate(srv)) {151 JobDel(tmpc);152 tmpc=NULL;153 } else {154 LBtr(&srv->task_flags,TASKf_IDLE);155 TaskRstAwaitingMsg(srv);156 QueIns(tmpc,srv->srv_ctrl.last_waiting);157 LBtr(&srv->srv_ctrl.flags,JOBCf_LOCKED);158 }159 POPFD160 if (msg_code<0) //Down-Up161 TaskMsg(_srv,master,-msg_code+1,arg1,arg2,flags);162 return tmpc;163}164 165Bool JobResScan(CJob *rqst=NULL,I64 *_res=NULL)166{//Check rqst complete, return with or without.167 CJobCtrl *ctrl;168 CJob *tmpc,*tmpc1;169 if (!rqst || Bt(&rqst->flags,JOBf_DONE)) {170 if (!rqst || rqst->master_task)171 ctrl=&Fs->srv_ctrl;172 else173 ctrl=rqst->ctrl;174 PUSHFD175 CLI176 while (LBts(&ctrl->flags,JOBCf_LOCKED))177 PAUSE178 tmpc1=&ctrl->next_done;179 tmpc=tmpc1->next;180 while (tmpc!=tmpc1) {181 if (!rqst || rqst==tmpc) {182 QueRem(tmpc);183 LBtr(&ctrl->flags,JOBCf_LOCKED);184 POPFD185 if (_res)186 *_res=tmpc->res;187 JobDel(tmpc);188 return TRUE;189 }190 tmpc=tmpc->next;191 }192 LBtr(&ctrl->flags,JOBCf_LOCKED);193 POPFD194 }195 if (_res)196 *_res=0;197 return FALSE;198}199 200I64 JobResGet(CJob *rqst=NULL)201{//See ::/Demo/MultiCore/Lock.HC202 I64 res;203 CJob *tmpc1;204 if (!rqst) {205 tmpc1=&Fs->srv_ctrl.next_done;206 while (tmpc1==tmpc1->next) {207 LBts(&Fs->task_flags,TASKf_IDLE);208 Yield;209 }210 } else {211 while (!Bt(&rqst->flags,JOBf_DONE)) {212 LBts(&Fs->task_flags,TASKf_IDLE);213 Yield;214 }215 }216 LBtr(&Fs->task_flags,TASKf_IDLE);217//Could get taken by someone else.218 JobResScan(rqst,&res);219 return res;220}221 222U0 TaskWait(CTask *task=NULL,Bool cmd_line_pmt=FALSE)223{//Wait for idle.224 CTask *task1;225 CJob *tmpc1;226 if (!task) task=Fs;227 if (TaskValidate(task)) {228 PUSHFD229 CLI230 while (TRUE) {231 task1=task->last_input_filter_task;232 tmpc1=&task1->srv_ctrl.next_waiting;233 if (task1==Fs || !TaskValidate(task1) ||234 tmpc1==tmpc1->next && Bt(&task1->task_flags,TASKf_IDLE) &&235 (!cmd_line_pmt || Bt(&task1->task_flags,TASKf_CMD_LINE_PMT)))236 break;237 Yield;238 }239 POPFD240 }241}242 243U0 PostMsg(CTask *task,I64 msg_code,I64 arg1,I64 arg2,I64 flags=0)244{//Post message to a task and return immediately. See msg_code.245 if (TaskValidate(task)) {246 if (Bt(&task->task_flags,TASKf_INPUT_FILTER_TASK))247 TaskMsg(task->last_input_filter_task,NULL,msg_code,arg1,arg2,248 flags|1<<JOBf_DONT_FILTER);249 else250 TaskMsg(task,NULL,msg_code,arg1,arg2,flags);251 }252}253 254U0 PostMsgWait(CTask *task,I64 msg_code,I64 arg1,I64 arg2,I64 flags=0)255{//Post message to a task and wait until task is idle.See msg_code.256 PostMsg(task,msg_code,arg1,arg2,flags);257 TaskWait(task);258}259 260U0 Msg(I64 msg_code,I64 arg1,I64 arg2,I64 flags=0)261{//Post message to current task and return immediately.262//See msg_code.263 PostMsg(Fs,msg_code,arg1,arg2,flags);264}265 266#define JOB_DONE 0267#define JOB_CONT 1268#define JOB_EXIT 2269 270I64 JobRunOne(I64 run_flags,CJobCtrl *ctrl)271{//Called with ctrl->flags,JOBCf_LOCKED.272 CJob *tmpc=ctrl->next_waiting;273 CTask *master;274 I64 res,flags=tmpc->flags,old_flags=GetRFlags;275 if (Bt(&flags,JOBf_EXIT_ON_COMPLETE))276 res=JOB_EXIT;277 else278 res=JOB_CONT;279 switch (tmpc->job_code) {280 case JOBT_SPAWN_TASK:281 QueRem(tmpc);282 LBts(&tmpc->flags,JOBf_DISPATCHED);283 LBtr(&ctrl->flags,JOBCf_LOCKED);284 if (tmpc->aux_str)285 tmpc->spawned_task=Spawn(tmpc->addr,tmpc->fun_arg,286 tmpc->aux_str,,tmpc->aux1,tmpc->aux2,tmpc->flags);287 else288 tmpc->spawned_task=Spawn(tmpc->addr,tmpc->fun_arg,289 "Unnamed",,tmpc->aux1,tmpc->aux2,tmpc->flags);290 break;291 case JOBT_CALL:292 QueRem(tmpc);293 LBts(&tmpc->flags,JOBf_DISPATCHED);294 LBtr(&ctrl->flags,JOBCf_LOCKED);295 SetRFlags(run_flags);296 LBtr(&Fs->task_flags,TASKf_IDLE);297 try298 tmpc->res=(*tmpc->addr)(tmpc->fun_arg);299 catch300 Fs->catch_except=TRUE;301 SetRFlags(old_flags);302 break;303 case JOBT_EXE_STR:304 QueRem(tmpc);305 LBts(&tmpc->flags,JOBf_DISPATCHED);306 LBtr(&ctrl->flags,JOBCf_LOCKED);307 SetRFlags(run_flags);308 LBtr(&Fs->task_flags,TASKf_IDLE);309 try310 tmpc->res=ExePrint("%s",tmpc->aux_str);311 catch312 Fs->catch_except=TRUE;313 SetRFlags(old_flags);314 break;315 default:316 res=JOB_DONE;317 }318 if (res) {319 if (master=tmpc->master_task) {320 if (!Bt(&flags,JOBf_FREE_ON_COMPLETE)) {321 CLI322 while (LBts(&master->srv_ctrl.flags,JOBCf_LOCKED))323 PAUSE324 QueIns(tmpc,master->srv_ctrl.last_done);325 LBts(&tmpc->flags,JOBf_DONE);326 LBtr(&master->srv_ctrl.flags,JOBCf_LOCKED);327 SetRFlags(old_flags);328 }329 if (Bt(&flags,JOBf_FOCUS_MASTER) &&330 !Bt(&master->win_inhibit,WIf_SELF_FOCUS))331 sys_focus_task=master;332 if (Bt(&flags,JOBf_WAKE_MASTER))333 Suspend(master,FALSE);334 }335 if (Bt(&flags,JOBf_FREE_ON_COMPLETE))336 JobDel(tmpc);337 else if (!master) {338 CLI339 while (LBts(&ctrl->flags,JOBCf_LOCKED))340 Yield;341 QueIns(tmpc,ctrl->last_done);342 LBts(&tmpc->flags,JOBf_DONE);343 LBtr(&ctrl->flags,JOBCf_LOCKED);344 SetRFlags(old_flags);345 }346 }347 return res;348}349 350I64 JobsHndlr(I64 run_flags,CTask *task=NULL)351{//Handle all waiting cmds and return.352 I64 cnt=0,old_flags=GetRFlags;353 if (!task) task=Fs;354 while (TRUE) {355 CLI356 while (LBts(&task->srv_ctrl.flags,JOBCf_LOCKED))357 PAUSE358 if (task->srv_ctrl.next_waiting!=&task->srv_ctrl)359 switch (JobRunOne(run_flags,&task->srv_ctrl)) {360 case JOB_CONT:361 cnt++;362 break;363 case JOB_EXIT:364 Exit;365 case JOB_DONE:366 goto jh_done;367 }368 else369 goto jh_done;370 }371jh_done:372 LBtr(&task->srv_ctrl.flags,JOBCf_LOCKED);373 SetRFlags(old_flags);374 return cnt;375}376 377I64 PopUp(U8 *buf,CTask *parent=NULL,CTask **_pu_task=NULL)378{//Execute code in PopUp task.379 I64 res;380 CJob *tmpc;381 CTask *task=Spawn(&SrvCmdLine,NULL,"Servant",,parent);382 if (!parent) {383 TaskExe(task,parent,buf,1<<JOBf_EXIT_ON_COMPLETE|1<<JOBf_FREE_ON_COMPLETE);384 if (_pu_task) *_pu_task=task;385 return 0;386 } else {387 Fs->popup_task=task;388 tmpc=TaskExe(task,parent,buf,1<<JOBf_WAKE_MASTER|1<<JOBf_FOCUS_MASTER);389 if (_pu_task) *_pu_task=task;390 JobResScan(tmpc,&res);391 Fs->popup_task=NULL;392 Kill(task);393 if (_pu_task) *_pu_task=NULL;394 return res;395 }396}397 398I64 PopUpPrint(U8 *fmt,...)399{//Execute code in PopUp task.400 U8 *buf=StrPrintJoin(NULL,fmt,argc,argv);401 I64 res;402 res=PopUp(buf,Fs);403 Free(buf);404 return res;405}406 407I64 Adam(U8 *fmt,...)408{//Make adam_task execute code.409 I64 res;410 U8 *buf=StrPrintJoin(NULL,fmt,argc,argv);411 CJob *tmpc;412 if (Fs==adam_task) {413 tmpc=TaskExe(adam_task,Fs,buf,0);414 JobsHndlr(GetRFlags);415 } else {416 TaskWait(adam_task);417 tmpc=TaskExe(adam_task,Fs,buf,1<<JOBf_WAKE_MASTER);418 }419 JobResScan(tmpc,&res);420 Free(buf);421 return res;422}423 424U0 AdamLog(U8 *fmt,...)425{//Display text in adam_task.426 U8 *buf=StrPrintJoin(NULL,fmt,argc,argv);427 if (Fs==adam_task)428 "%s",buf;429 else if (!IsSingleUser)430 Adam("\"%%s\",%d;",buf);431 Free(buf);432}433 434U0 AdamErr(U8 *fmt,...)435{//Display red blinking Err text in adam_task.436 U8 *buf=StrPrintJoin(NULL,fmt,argc,argv),437 *st=MStrPrint(ST_ERR_ST "%s",buf);438 if (Fs==adam_task)439 "%s",st;440 else if (!IsSingleUser)441 Adam("\"%%s\",%d;",st);442 Free(st);443 Free(buf);444}445 446U0 XTalk(CTask *task,U8 *fmt,...)447{//Sends text to other task. See ::/Misc/OSTestSuite.HC.448 U8 *buf=StrPrintJoin(NULL,fmt,argc,argv),*st=AStrNew(buf),449 *st2=MStrPrint("\"%%s\",%d;Free(%d);",st,st);450 TaskText(task,NULL,st2,0);451 Free(st2);452 Free(buf);453}454 455U0 XTalkWait(CTask *task,U8 *fmt,...)456{//Send text to other task and wait for it to idle.457 U8 *buf=StrPrintJoin(NULL,fmt,argc,argv),*st=AStrNew(buf),458 *st2=MStrPrint("\"%%s\",%d;Free(%d);",st,st);459 TaskText(task,NULL,st2,0);460 Free(st2);461 Free(buf);462 TaskWait(task);463}464 465U0 InStr(U8 *fmt,...)466{//Send InFile code to self.467 U8 *buf=StrPrintJoin(NULL,fmt,argc,argv);468 if (Bt(&Fs->task_flags,TASKf_INPUT_FILTER_TASK))469 ExePrint("%s",buf);470 else471 TaskText(Fs,NULL,buf,1<<JOBf_HIGHEST_PRIORITY);472 Free(buf);473}474 475U0 InFile(U8 *filename)476{//Send InFile code file to self.477 U8 *name=ExtDft(filename,"IN.Z");478 InStr("Cd(\"%C:%s\");;#include \"%s\"",479 Drv2Let(Fs->cur_dv),Fs->cur_dir,name);480 Free(name);481}482 483U0 In(U8 *fmt,...)484{//Send text to own input buffer. See ::/Demo/AcctExample/TOS/TOSDistro.HC.485 U8 *buf=StrPrintJoin(NULL,fmt,argc,argv),*st=AStrNew(buf);486 InStr("\"%%s\",%d;Free(%d);",st,st);487 Free(buf);488}489 490U0 XTalkStr(CTask *task,U8 *fmt,...)491{//Send InFile code to other task.492 U8 *buf=StrPrintJoin(NULL,fmt,argc,argv);493 TaskText(task,NULL,buf,0);494 Free(buf);495}496 497U0 XTalkStrWait(CTask *task,U8 *fmt,...)498{//Send InFile code to other task and wait for it to idle.499 U8 *buf=StrPrintJoin(NULL,fmt,argc,argv);500 TaskText(task,NULL,buf,0);501 Free(buf);502 TaskWait(task);503}504 