
// 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);
}
Kernel