code: 9ferno

Download patch

ref: 83906bfb6b2102104cb242ad578caa994785f72f
parent: d23bfd38b2761edef6752c73449f389f1a742a55
author: 9ferno <gophone2015@gmail.com>
date: Tue Dec 14 22: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);
 }