Seth -> Daemon

This commit is contained in:
xmm15 2020-02-16 14:28:10 -06:00
parent 8d04100a73
commit 19ffe0a9a2
20 changed files with 1986 additions and 1982 deletions

Binary file not shown.

View file

@ -330,7 +330,7 @@ U0 MPMenDraw(CDC *dc2)
dc->depth_buf=NULL;
DCDel(dc);
LBtr(&mp_not_done_flags,Gs->num);
Seed; //Return Seth task to timer-based.
Seed; //Return Daemon task to timer-based.
}
U0 MissilePos(I64 m,F64 é,I64 *_x,I64 *_y)

Binary file not shown.

View file

@ -1,4 +1,4 @@
$WW,1$$FG,5$$TX+CX,"Glossary"$$FG$
$WW,1$$FG,5$$TX+CX,"Glossary"$$FG$
$TR,"Abbreviations"$
$ID,2$$FG,2$Abs$FG$ Absolute
@ -148,8 +148,8 @@ $ID,2$There is no distinction between $FG,2$task$FG$, $FG,2$process$FG$ or $FG,2
Since there is not friendly disk sharing and all tasks have the same address map, it might be accurate to call ZenithOS, "multi-thread/single-process". You run a single application process on $FG,2$Core0$FG$ and it can create threads on the same core or others. If you run multiple processes, it should be safe, but one process will wait until another completely finishes a long disk access.
$ID,-2$$TR,"Zenith Task"$
$ID,2$This is Zenith, as in Zenith and Eve, the parent of all tasks. Zenith is immortal. The zenith task is created at start-up and appears in the small window at the top beneath the user terminal windows. Since the Zenith task is immortal, on Zenith's heap go all memory objects which you don't want destroyed by any single task's death. When created, Zenith runs the file $LK,"::/StartOS.CC"$. When start-up is finished, the zenith task enters a server mode where it accepts requests from other tasks. The $LK,"Zenith",A="MN:Zenith"$("") routine will make Zenith compile and run text src code. $FG,2$#include$FG$ statements can be sent to $LK,"Zenith",A="MN:Zenith"$(""), creating system-wide code and data which are immortal.
$ID,-2$$TR,"Seth Tasks"$
$ID,2$In the Bible, $LK,"Seth",A="BF:Genesis,4:25"$$FG$ is Zenith and Eve's child. Each CPU core has an executive task called $FG,2$Seth$FG$ that is immortal. The Zenith task on $FG,2$Core0$FG$ is also its $FG,2$Seth$FG$ task.
$ID,-2$$TR-C,"Daemon Tasks"$
$ID,2$Each CPU core has an executive task called $FG,2$Daemon$FG$ that is immortal. The Zenith task on $FG,2$Core0$FG$ is also its $FG,2$Daemon$FG$ task.
$ID,-2$$TR,"Code and Data Heaps"$
$ID,2$ZenithOS uses the asm $FG,2$CALL$FG$ inst, exclusively, and that inst is limited to calling routines $FG,2$+/-2Gig$FG$ from the current code location. To prevent out-of-range issues, I decided to separate code and data, placing all code within the lowest $FG,2$2Gig$FG$ of memory, addresses $FG,2$00000000$FG$-$FG,2$7FFFFFFF$FG$. The compiler and $LK,"Load",A="MN:Load"$()er alloc memory from the code heap to store code and glbl vars, unless the compiler option $LK,"OPTf_GLBLS_ON_DATA_HEAP",A="MN:OPTf_GLBLS_ON_DATA_HEAP"$ is used. When programs call $LK,"MAlloc",A="MN:MAlloc"$() is from the data heap, which in not limited in size, except by physical RAM memory. You can alloc from any heap in any task at any time on any core, even making $LK,"independent",A="MN:MemPagAlloc"$ heaps.
$ID,-2$$TR,"Parent, Child and PopUp Tasks"$
@ -269,5 +269,5 @@ $ID,2$When two parts of a program have a common low-level routine, that routine
$ID,-2$$TR,"user_data"$
$ID,2$Many operating system structures have space set aside for you to store values. You are on your own managing these with multiple applications and libraries.
$ID,-2$$TR,"Multicore Core0/CoreAP"$
$ID,2$Core0, has the $LK,"Zenith Task",A="FF:::/Doc/Glossary.DD,Zenith Task"$$FG$, and it is the master. The $FG,2$application processors$FG$ have an executive $LK,"Seth Tasks",A="FF:::/Doc/Glossary.DD,Seth Tasks"$ and are the slave processors. Only $FG,2$Core0$FG$ tasks can have windows and can launch applications. Slave cores are used if the application explicitly $LK,"Spawn",A="MN:Spawn"$s() a task or $LK,"JobQueue",A="MN:JobQueue"$() a job on them.
$ID,2$Core0, has the $LK,"Zenith Task",A="FF:::/Doc/Glossary.DD,Zenith Task"$$FG$, and it is the master. The $FG,2$application processors$FG$ have an executive $LK,"Daemon Tasks",A="FF:::/Doc/Glossary.DD,Daemon Tasks"$ and are the slave processors. Only $FG,2$Core0$FG$ tasks can have windows and can launch applications. Slave cores are used if the application explicitly $LK,"Spawn",A="MN:Spawn"$s() a task or $LK,"JobQueue",A="MN:JobQueue"$() a job on them.
$ID,-2$

Binary file not shown.

View file

@ -4,9 +4,9 @@ There are multicore safe locks for file access and heap allocations, however, so
Only tasks on $FG,2$Core0$FG$ can have windows, but other cores can help render them.
Each core has an executive $LK,"Seth Task",A="FF:::/Doc/Glossary.DD,Seth Tasks"$ which is the father of all tasks on that core. $LK,"Zenith",A="FF:::/Doc/Glossary.DD,Zenith Task"$ is the $LK,"Seth Task",A="FF:::/Doc/Glossary.DD,Seth Tasks"$ on $FG,2$Core0$FG$.
Each core has an executive $LK,"Daemon Task",A="FF:::/Doc/Glossary.DD,Daemon Tasks"$ which is the father of all tasks on that core. $LK,"Zenith",A="FF:::/Doc/Glossary.DD,Zenith Task"$ is the $LK,"Daemon Task",A="FF:::/Doc/Glossary.DD,Daemon Tasks"$ on $FG,2$Core0$FG$.
You give a job to a $LK,"Seth Task",A="FF:::/Doc/Glossary.DD,Seth Tasks"$ with $LK,"JobQueue",A="MN:JobQueue"$() and get the result with $LK,"JobResGet",A="MN:JobResGet"$(). You spawn a task on any core with $LK,"Spawn",A="MN:Spawn"$().
You give a job to a $LK,"Daemon Task",A="FF:::/Doc/Glossary.DD,Daemon Tasks"$ with $LK,"JobQueue",A="MN:JobQueue"$() and get the result with $LK,"JobResGet",A="MN:JobResGet"$(). You spawn a task on any core with $LK,"Spawn",A="MN:Spawn"$().
Note: You must use the $FG,2$LOCK$FG$ asm prefix when changing shared structures in a multicore environment. The $LK,"LBts",A="MN:LBts"$(), $LK,"LBtr",A="MN:LBtr"$() and $LK,"LBtc",A="MN:LBtc"$() insts have $FG,2$LOCK$FG$ prefixes. The compiler has a $FG,2$lock{}$FG$ feature but it doesn't work well. See $LK,"::/Demo/MultiCore/Lock.CC"$.

Binary file not shown.

View file

@ -66,7 +66,7 @@ CHash *FunSegFind(U8 *addr,I64 *_offset)
if (IsDebugMode)
for (i=0;i<mp_count;i++) {
c=&cpu_structs[i];
task=c->seth_task;
task=c->daemon_task;
do {
if (!TaskValidate(task)) goto fs_abort_task;
h=task->hash_table;
@ -75,7 +75,7 @@ CHash *FunSegFind(U8 *addr,I64 *_offset)
h=h->next;
}
task=task->next_task;
} while (task!=c->seth_task);
} while (task!=c->daemon_task);
fs_abort_task:
}
else {

View file

@ -55,7 +55,7 @@ IRQ_TIMER:: //I_TIMER
@@20: CALL &IntCore0TimerHandler //Only Core 0 calls this.
@@25: XOR RAX,RAX
CMP RSI,U64 GS:CCPU.idle_task[RAX]
JE I32 RESTORE_SETH_TASK_IF_READY
JE I32 RESTORE_DAEMON_TASK_IF_READY
JMP I32 RESTORE_RSI_TASK
//************************************
INT_FAULT::
@ -144,7 +144,7 @@ interrupt U0 IntNop()
{//Make unplanned IRQs stop by all means!
OutU8(PIC2,PIC_EOI);
OutU8(PIC1,PIC_EOI);
 *(dev.uncached_alias + LAPIC_EOI)(U32 *) = 0;
*(dev.uncached_alias + LAPIC_EOI)(U32 *) = 0;
}
interrupt U0 IntDivZero()

View file

@ -60,7 +60,7 @@ Bool Kill(CTask *task,Bool wait=TRUE,Bool just_break=FALSE)
} else {
if (task!=sys_winmgr_task) {
for (i=0;i<mp_count;i++)
if (task==cpu_structs[i].seth_task)
if (task==cpu_structs[i].daemon_task)
return FALSE;
LBts(&task->task_flags,TASKf_KILL_TASK);
if (wait) {
@ -254,7 +254,7 @@ CTask *Spawn(U0 (*fp_start_addr)(U8 *data),U8 *data=NULL,U8 *task_name=NULL,
task=CAlloc(sizeof(CTask),zenith_task->code_heap);
task->task_signature=TASK_SIGNATURE_VAL;
if (!task_name) task_name="Unnamed Task";
if (!parent) parent=Gs->seth_task;
if (!parent) parent=Gs->daemon_task;
task->parent_task=parent;
task->gs=parent->gs;
if (sys_code_bp)

File diff suppressed because one or more lines are too long

View file

@ -496,6 +496,9 @@ class CKernel
#help_index "Processor"
//CPUID leaf flag bits
#define CPUIDf_RDX_APIC 9
//Programmable Interrupt Controller
#define PIC1 0x20
#define PIC1_DATA 0x21
@ -2861,7 +2864,7 @@ class CMemRange
#define MEM_EXTRA_HASH2_PAGS 2
#define MEM_ZENITH_STACK (MEM_PAG_SIZE*512) //Like 16384*MEM_PAG_SIZE
#define MEM_SETH_STACK (MEM_PAG_SIZE*512)
#define MEM_DAEMON_STACK (MEM_PAG_SIZE*512)
#define MEM_INTERRUPT_STACK (MEM_PAG_SIZE*512)
#define MEM_DEFAULT_STACK (MEM_PAG_SIZE*512)
@ -3419,7 +3422,7 @@ public class CCPU //The Gs segment reg points to current CCPU.
idle_pt_hits;
F64 idle_factor;
I64 total_jiffies;
CTask *seth_task,*idle_task;
CTask *daemon_task,*idle_task;
I64 tr, //task reg
swap_counter;
U0 (*profiler_timer_irq)(CTask *task);

View file

@ -625,7 +625,7 @@ extern U0 MouseUpdate(I64 x,I64 y,I64 z,Bool l,Bool r);
#help_index "MultiCore"
extern U0 Core0StartMP();
extern U0 CoreAPSethTask();
extern U0 CoreAPDaemonTask();
public extern U0 MPInt(U8 num,I64 cpu_num=1);
public extern U0 MPIntAll(U8 num);
public extern U0 MPNMInt();

View file

@ -59,7 +59,7 @@ USE64
FNINIT
MOV RAX,RSI
CALL SET_GS_BASE
@@10: MOV RAX,U64 CCPU.seth_task[RSI]
@@10: MOV RAX,U64 CCPU.daemon_task[RSI]
TEST RAX,RAX
JZ @@10
MOV U64 CTask.gs[RAX],RSI
@ -113,8 +113,8 @@ CTSS *TSSNew(I64 cpu_num)
return tss;
}
CCPU *CPUStructInit(I64 num,CCPU *c,CTask *seth_task)
{//Seth is null when called by zenith on CSysFixedArea.boot_cpu0
CCPU *CPUStructInit(I64 num,CCPU *c,CTask *daemon_task)
{//Daemon is null when called by zenith on CSysFixedArea.boot_cpu0
MemSet(c,0,sizeof(CCPU));
c->addr=c;
c->num=num;
@ -125,7 +125,7 @@ CCPU *CPUStructInit(I64 num,CCPU *c,CTask *seth_task)
LBts(&c->idle_task->task_flags,TASKf_IDLE);
c->tss=TSSNew(num);
}
c->seth_task=seth_task;// It waits for this to be filled-in: $LK,"seth_task",A="FF:::/Kernel/MultiProc.CC,seth_task"$
c->daemon_task=daemon_task;// It waits for this to be filled-in: $LK,"daemon_task",A="FF:::/Kernel/MultiProc.CC,daemon_task"$
return c;
}
@ -191,7 +191,7 @@ U0 MPAPICInit()
#assert !offset(CJobCtrl.next_waiting)
U0 CoreAPSethTask()
U0 CoreAPDaemonTask()
{
CJobCtrl *ctrl=&Fs->server_ctrl;
while (TRUE) {
@ -213,12 +213,12 @@ U0 CoreAPSethTask()
CJob *JobQueue(I64 (*fp_addr)(U8 *data),U8 *data=NULL,
I64 target_cpu=1,I64 flags=1<<JOBf_FREE_ON_COMPLETE,
I64 job_code=JOBT_CALL,U8 *aux_str=NULL,I64 aux1=0,I64 aux2=0)
{//Queue multicore jobs, handled by Seth tasks.
{//Queue multicore jobs, handled by Daemon tasks.
//Set flags to zero if you wish to get the res.
//See $LK,"::/Demo/MultiCore/Lock.CC"$
CJobCtrl *ctrl;
CJob *tmpc;
CTask *seth;
CTask *daemon;
if (!(0<=target_cpu<mp_count))
throw('MultCore');
tmpc=ZCAlloc(sizeof(CJob));
@ -230,13 +230,13 @@ CJob *JobQueue(I64 (*fp_addr)(U8 *data),U8 *data=NULL,
tmpc->flags=flags;
tmpc->aux1=aux1;
tmpc->aux2=aux2;
seth=cpu_structs[target_cpu].seth_task;
tmpc->ctrl=ctrl=&seth->server_ctrl;
daemon=cpu_structs[target_cpu].daemon_task;
tmpc->ctrl=ctrl=&daemon->server_ctrl;
PUSHFD
CLI
while (LBts(&ctrl->flags,JOBCf_LOCKED))
Yield;
if (ctrl->next_waiting==ctrl && LBtr(&seth->task_flags,TASKf_AWAITING_MESSAGE))
if (ctrl->next_waiting==ctrl && LBtr(&daemon->task_flags,TASKf_AWAITING_MESSAGE))
MPInt(I_WAKE,target_cpu);
QueueInsert(tmpc,ctrl->last_waiting);
LBtr(&ctrl->flags,JOBCf_LOCKED);
@ -272,11 +272,11 @@ CTask *SpawnQueue(U0 (*fp_addr)(U8 *data),U8 *data=NULL,U8 *task_name=NULL,
return res;
}
U0 CoreAPSethInit()
{//Called by multicore's seth task after $LK,"Core0StartMP",A="MN:Core0StartMP"$()
U0 CoreAPDaemonInit()
{//Called by multicore's daemon dask after $LK,"Core0StartMP",A="MN:Core0StartMP"$()
//as the first thing a CPU does before waiting for jobs.
MPAPICInit;
Fs->rip=&CoreAPSethTask;
Fs->rip=&CoreAPDaemonTask;
TaskContextRestore;
}
@ -300,8 +300,8 @@ U0 Core0StartMP()
MPHalt; //sets mp_count to 1
for (i=1;i<my_mp_count;i++) {
c=&cpu_structs[i];
JobQueueDel(&c->seth_task->server_ctrl.next_waiting);
JobQueueDel(&c->seth_task->server_ctrl.next_done);
JobQueueDel(&c->daemon_task->server_ctrl.next_waiting);
JobQueueDel(&c->daemon_task->server_ctrl.next_done);
}
}
MemSet(&cpu_structs[1],0,sizeof(CCPU)*(MP_PROCESSORS_NUM-1));
@ -334,17 +334,17 @@ U0 Core0StartMP()
my_mp_count=MP_PROCESSORS_NUM;
for (i=1;i<my_mp_count;i++) {
StrPrint(buf,"Seth Task CPU%02X",i);
task=Spawn(&CoreAPSethInit,NULL,buf,,,MEM_SETH_STACK,0);
StrPrint(buf,"Daemon Task CPU%02X",i);
task=Spawn(&CoreAPDaemonInit,NULL,buf,,,MEM_DAEMON_STACK,0);
task->rflags=RFLAGG_START;
//$LK,"CTask",A="MN:CTask"$ alloced off this core's seth_task's heap (Which is Zenith)
//$LK,"CTask",A="MN:CTask"$ alloced off this core's daemon_task's heap (Which is Zenith)
CPUStructInit(i,&cpu_structs[i],task);
WBINVD //Not sure why this is needed. Might just need delay.
}
//Make sure they're all up-and-running
for (i=1;i<my_mp_count;i++)
while (!Bt(&cpu_structs[i].seth_task->task_flags,TASKf_AWAITING_MESSAGE))
while (!Bt(&cpu_structs[i].daemon_task->task_flags,TASKf_AWAITING_MESSAGE))
PAUSE;
POPFD

View file

@ -1,6 +1,6 @@
/*On each core, tasks are linked in a
circular doubly-linked list queue with
the Seth task as the head.On Core0,
the Daemon task as the head.On Core0,
the queue order represents the front-to-back
window stack order with the window mgr
as the wallpaper.
@ -30,9 +30,9 @@ The scheduler checks for a few keys:
<CTRL-ALT-c> breaks execution of a program.
Each core has its own circular task queue.
For AP processors, they have a "Seth" task
For AP processors, they have a "Daemon" task
which stays in a loop waiting for jobs or
requests to spawn tasks.See $LK,"CoreAPSethTask",A="MN:CoreAPSethTask"$().
requests to spawn tasks.See $LK,"CoreAPDaemonTask",A="MN:CoreAPDaemonTask"$().
$HL,1$*/
U0 TaskFocusNext()
@ -190,8 +190,8 @@ RESTORE_RSI_TASK2:
@@25: MOV RSI,U64 CTask.next_task[RSI]
XOR RAX,RAX
CMP U64 GS:CCPU.seth_task[RAX],RSI
JNE @@20 //Jmp if not Seth
CMP U64 GS:CCPU.daemon_task[RAX],RSI
JNE @@20 //Jmp if not Daemon
BTR U32 GS:CCPU.cpu_flags[RAX],CPUf_RAN_A_TASK
JC @@20 //Jmp if had chance for IRQ already
MOV RAX,U64 GS:CCPU.idle_task[RAX]
@ -203,9 +203,9 @@ RESTORE_RSI_TASK2:
SYS_IDLE_PT::
CLI
RESTORE_SETH_TASK_IF_READY:
RESTORE_DAEMON_TASK_IF_READY:
XOR RAX,RAX
MOV RSI,GS:CCPU.seth_task[RAX]
MOV RSI,GS:CCPU.daemon_task[RAX]
JMP RESTORE_RSI_TASK
HANDLE_SYSF_KEY_EVENT:
@ -222,7 +222,7 @@ HANDLE_SYSF_KEY_EVENT:
JC I32 &Reboot
CMP U64 GS:CCPU.idle_task[RBX],RSI
JE RESTORE_SETH_TASK_IF_READY
JE RESTORE_DAEMON_TASK_IF_READY
LOCK
BTR U32 [RAX],CTRL_ALT_TAB
@ -240,7 +240,7 @@ HANDLE_SYSF_KEY_EVENT:
BREAK_FOCUS_USER:
MOV RSI,U64 [SYS_FOCUS_TASK]
TEST RSI,RSI
JZ RESTORE_SETH_TASK_IF_READY
JZ RESTORE_DAEMON_TASK_IF_READY
BT U64 CTask.win_inhibit[RSI],WIf_SELF_FOCUS
JC I32 RESTORE_RSI_TASK
LOCK
@ -265,7 +265,7 @@ END_FOCUS_USER:
MOV RSI,U64 [SYS_FOCUS_TASK]
CALL &TaskFocusNext
TEST RSI,RSI
JZ I32 RESTORE_SETH_TASK_IF_READY
JZ I32 RESTORE_DAEMON_TASK_IF_READY
MOV RAX,RSI
CALL SET_FS_BASE
BT U64 CTask.win_inhibit[RSI],WIf_SELF_FOCUS

Binary file not shown.

View file

@ -74,7 +74,7 @@ U0 GrUpdateTasks()
} while (task!=task1);
for (i=0;i<mp_count;i++) { //Loop through all cores.
task1=task=cpu_structs[i].seth_task;
task1=task=cpu_structs[i].daemon_task;
do {
if (!TaskValidate(task)) break;
GrUpdateTaskODEs(task);

View file

@ -143,7 +143,7 @@ Bool MemRepTask(CTask *task,Bool override_validate=FALSE)
for (i=0;i<mp_count;i++) {
c=&cpu_structs[i];
k+=TSSSize(c->tss);
task1=c->seth_task;
task1=c->daemon_task;
do {
if (task1!=zenith_task) {//zenith task located in Kernel mem
j+=MSize2(task1);
@ -153,7 +153,7 @@ Bool MemRepTask(CTask *task,Bool override_validate=FALSE)
}
n+=TaskQueueSize(task1);
task1=task1->next_task;
} while (task1!=c->seth_task);
} while (task1!=c->daemon_task);
task1=c->idle_task;
j+=MSize2(task1);
m+=MSize2(task1->code_heap);
@ -219,12 +219,12 @@ public U0 MemRep()
for (i=0;i<mp_count;i++) {
c=&cpu_structs[i];
"$$PURPLE$$CPU%d$$FG$$\n$$ID,2$$",i;
task=c->seth_task;
task=c->daemon_task;
do {
if (!MemRepTask(task))
break;
task=task->next_task;
} while (task!=c->seth_task);
} while (task!=c->daemon_task);
MemRepTask(c->idle_task,TRUE);
"$$ID,-2$$";
}

View file

@ -24,7 +24,7 @@ public U0 TaskRep()
for (i=0;i<mp_count;i++) {
c=&cpu_structs[i];
"$$PURPLE$$CPU%02X$$FG$$\n",i;
TaskRepTask(c->seth_task,2);
TaskRepTask(c->daemon_task,2);
}
POPFD
}

Binary file not shown.