ref: 83906bfb6b2102104cb242ad578caa994785f72f
parent: d23bfd38b2761edef6752c73449f389f1a742a55
author: 9ferno <gophone2015@gmail.com>
date: Tue Dec 14 15:28:54 EST 2021
starting forth process with dictionary
--- a/os/pc64/bindings.s
+++ b/os/pc64/bindings.s
@@ -115,9 +115,9 @@
NEXT
/* no link register in amd64
- * 8 bytes for saving UP
- * 24 bytes for the arguments to write
- * the space for the return PC is taken care of by the compiler
+ * 3 arguments for kwrite = 24 bytes
+ * 1 local for storing UP = 8 bytes
+ * Hence, need 32 bytes on the stack
*/
TEXT fthwrite(SB), 1, $32 /* ( n a fd -- n2 ) */
MOVQ (PSP), CX /* address = start of heap + address */
--- a/os/pc64/forth.s
+++ b/os/pc64/forth.s
@@ -95,9 +95,11 @@
words - lower case
*/
+/* HEAPSTART, HEAPEND, HERE, DTOP are loaded by the caller */
TEXT forthmain(SB), 1, $0 /* not a tail function, can RET back to the caller */
/* Argument has the start of heap */
MOVQ RARG, UP /* start of heap memory */
+ MOVQ 8(UP), UPE /* HEAPEND populated by the caller */
MOVQ UP, RSP
ADDQ $RSTACK_END, RSP /* return stack pointer, reset */
--- a/os/pc64/mem.h
+++ b/os/pc64/mem.h
@@ -214,6 +214,8 @@
#define FORTHHEAPSIZE (9*BY2PG)
#define HEAPSTART (0ull)
#define HEAPEND (HEAPSTART+(BY2WD*1))
+
+/* storage for Forth registers when calling C */
#define FORTHTOP (HEAPSTART+(BY2WD*2))
#define FORTHPSP (HEAPSTART+(BY2WD*3))
#define FORTHRSP (HEAPSTART+(BY2WD*4))
@@ -221,6 +223,7 @@
#define FORTHW (HEAPSTART+(BY2WD*6))
#define FORTHUP (HEAPSTART+(BY2WD*7))
#define FORTHUPE (HEAPSTART+(BY2WD*8))
+
#define HERE (HEAPSTART+(BY2WD*9))
#define DTOP (HEAPSTART+(BY2WD*10))
#define ARGS (HEAPSTART+(BY2WD*11))
@@ -228,11 +231,11 @@
#define WORDB (HEAPSTART+(BY2WD*144)) /* word buffer */
#define DICTIONARY (HEAPSTART+(BY2WD*256)) /* dictionary */
-#define DICTIONARY_END (HEAPSTART+(6*BY2PG))
-#define PSTACK (HEAPSTART+(6*BY2PG))
-#define PSTACK_END (HEAPSTART+(7*BY2PG))
-#define TIB (HEAPSTART+(7*BY2PG)) /* text input buffer */
-#define RSTACK (HEAPSTART+(8*BY2PG))
-#define RSTACK_END (HEAPSTART+(9*BY2PG))
+#define DICTIONARY_END (HEAPSTART+(16*BY2PG))
+#define PSTACK (HEAPSTART+(16*BY2PG))
+#define PSTACK_END (HEAPSTART+(17*BY2PG))
+#define TIB (HEAPSTART+(17*BY2PG)) /* text input buffer */
+#define RSTACK (HEAPSTART+(18*BY2PG))
+#define RSTACK_END (HEAPSTART+(19*BY2PG))
#define FORTHEND RSTACK_END
#define HEAPSIZE FORTHEND
--- a/os/port/proc.c
+++ b/os/port/proc.c
@@ -59,16 +59,39 @@
static void pidfree(Proc*);
/*
- * The kernel scheduler state is in m->sched. It is set to the address
- * of schedinit().
- * When sched() is switching processes, it transfers control to the kernel
- * scheduler by using the m->sched label. The kernel scheduler then updates
- * the running process's state and picks the next process to run.
- * By using m->sched, we are creating a loop from sched() to schedinit()
- * after every process switch.
- *
- * inferno does not change the process priorities. So, ignoring updatecpu().
- * process priorities are set with setpri()
+ There is a loop created between schedinit() and a process' run path.
+ In schedinit(), setlabel(&m->sched) sets a pc and stack pointer
+ in the Mach for a process to return to.
+ In procswitch()(called by sched(), the setlabel(&up->sched) stores the
+ return pc and stack pointer of the run path in Proc and goes to the pc
+ in m->sched to start the scheduler loop.
+ In sched(), we use the pc and sp in Proc.sched to resume execution later on.
+ Thus the stacks and execution paths are switched from the Mach (scheduler)
+ to that of a specific process.
+
+ The execution path from Mach.sched to Proc.sched is the kernel scheduler run path
+ The execution path from Proc.sched to Mach.sched is the process run path
+
+ first process on entering schedinit() sets up Mach.sched
+ process run path calls sched(), which calls procswitch()
+ stack and pc changed to the contents of Mach.sched() - scheduler run path
+ schedinit() adds the current running process to the end of ready queue, sets up = nil
+ and calls sched()
+ sched() picks the next process to run (runproc()) and switches to
+ that Proc's pc and sp.
+
+ schedinit() calls sched() after setting up = nil and putting the running process in the ready queue
+
+ The kernel scheduler state is in m->sched. It is set to the address
+ of schedinit().
+ When sched() is switching processes, it transfers control to the kernel
+ scheduler by using the m->sched label. The kernel scheduler then updates
+ the running process's state and picks the next process to run.
+ By using m->sched, we are creating a loop from sched() to schedinit()
+ after every process switch.
+
+ inferno does not change the process priorities. So, ignoring updatecpu().
+ process priorities are set with setpri()
*/
/*
* Always splhi()'ed.
@@ -78,12 +101,14 @@
{
setlabel(&m->sched);
if(up != nil) {
+ if(up->pid == 28 || up->pid == 0)
+ print("schedinit up->pid = %d up->state %d\n", up->pid, up->state);
/*
if((e = up->edf) && (e->flags & Admitted))
edfrecord(up);
*/
m->proc = nil;
- switch(up->state) {
+ switch(up->state){
case Running:
/*
* process state from Runnning -> Ready
@@ -133,7 +158,7 @@
procsave(up);
- if(!setlabel(&up->sched))
+ if(setlabel(&up->sched) == 0) /* always returns 0 */
gotolabel(&m->sched);
/* process wakes up here next time */
--- a/tests/mkfile
+++ b/tests/mkfile
@@ -16,4 +16,6 @@
BIN=$ROOT/$OBJDIR/bin
+$O.asmconventions: asmconventions.$O asmconventions_asm.$O
+
<$ROOT/mkfiles/mkmany-$SHELLTYPE
--- a/tests/testp.c
+++ b/tests/testp.c
@@ -7,6 +7,8 @@
main(int, void**)
{
intptr **q, *v = H;
+ char buf[512];
+ int n;
q = &v;
if(*q == H)
@@ -14,5 +16,8 @@
if(*q != H)
print("not equal to H\n");
print("testing q=0x%p *q=0x%p v=0x%p\n", q, *q, v);
+ fprint(2, "testing the 2 fd\n");
+ n = read(0,buf,18);
+ fprint(1, "read %d bytes from 0: %s\n", n, buf);
exits(0);
}