code: 9ferno

Download patch

ref: 04b419c602ed75deaed50b89fa164660fd679e8f
parent: 5567d0285c57c557345a8253748fb2d262d7261b
author: 9ferno <gophone2015@gmail.com>
date: Sun Jan 23 02:52:22 EST 2022

more changes from 9front

--- a/os/pc/devarch.c
+++ b/os/pc/devarch.c
@@ -923,7 +923,7 @@
 	return (*arch->fastclock)(hz);
 }
 
-u64
+u32
 µs(void)
 {
 	return fastticks2us((*arch->fastclock)(nil));
--- a/os/pc/irq.c
+++ b/os/pc/irq.c
@@ -71,7 +71,7 @@
 				if(up->delaysched)
 					sched();
 			} else {
-				preemption(0);
+				preempted();
 			}
 		}
 		return 1;
--- a/os/pc/sdiahci.c
+++ b/os/pc/sdiahci.c
@@ -1294,7 +1294,7 @@
 		i = led2[8*p->led + seq%8];
 	if(i != p->ledbits){
 		p->ledbits = i;
-		ledprint("ledstate %,.011ub %ud\n", p->ledbits, seq);
+		ledprint("ledstate %,.011ud %ud\n", p->ledbits, seq);
 		return 1;
 	}
 	return 0;
--- a/os/pc64/bindings.s
+++ b/os/pc64/bindings.s
@@ -164,7 +164,7 @@
 	PUSH(TOP)			/* ( -- n a fd n n ) */
 	MOVQ CX, TOP		/* ( n a fd -- n a fd n a ) */
 
-	CALL validatebuffer(SB)
+	CALL validatebuffer(SB)	/* ( n a fd n a -- n a fd ) */
 
 	MOVQ UP, 24(SP)
 	F_TO_C_3
--- a/os/pc64/l.s
+++ b/os/pc64/l.s
@@ -972,7 +972,7 @@
  * The size of each entry in the vector table (6 bytes) is known in trapinit0().
  * Volume 3A 6-14
  * Stack is (high -> low)
- * SS, RSP, RFLAGS, CS, RIP, Error Code (if any), Vectortable(SB) return PC
+ * SS, RSP, RFLAGS, CS, RIP, Error Code (if any), vectortable(SB) return PC
  * (SP) = Vectortable(SB) return PC. The first byte of this return PC will be the
  * byte we used to identify the trap type.
  * Removed the nested check that 9front does as we are not using different code
@@ -980,15 +980,21 @@
  */
 
 TEXT _strayintr(SB), 1, $-4	/* no error code pushed */
-	PUSHQ	AX				/* save AX, some junk to fill the ecode slot in the stack */
-	MOVQ	8(SP), AX		/* vectortable(SB) PC */
+	PUSHQ	AX			/* some value to fill the ecode slot in the stack and also store AX value */
+	MOVQ	8(SP), AX	/* vectortable(SB) PC */
+						/* Stack is SS, RSP, RFLAGS, CS, RIP, vectortable(SB) Return PC, AX
+							AX = vectortable(SB) return PC */
 	JMP	_intrcommon
 
 TEXT _strayintrx(SB), 1, $-4/* error code pushed */
-	XCHGQ	AX, (SP)		/* exchange AX with pointer to trap type */
+	XCHGQ	AX, (SP)	/* exchange AX with pointer to trap type */
+						/* Stack is SS, RSP, RFLAGS, CS, RIP, Error Code, AX
+							AX = vectortable(SB) return PC */
 _intrcommon:
-	MOVBQZX	(AX), AX		/* extract trap type from the vectortable(SB) return PC -> AX */
-	XCHGQ	AX, (SP)		/* exchange vectortable(SB) return PC with the trap type in AX */
+	MOVBQZX	(AX), AX	/* extract trap type from the vectortable(SB) return PC -> AX */
+	XCHGQ	AX, (SP)	/* exchange vectortable(SB) return PC with the trap type in AX */
+						/* Stack is SS, RSP, RFLAGS, CS, RIP, Error Code or vectortable(SB) Return PC, trap type
+								AX = AX */
 
 	PUSHW	GS
 	PUSHW	FS
--- a/os/pc64/trap.c
+++ b/os/pc64/trap.c
@@ -200,7 +200,7 @@
 
 		if(ctl->isintr){
 			if(up && ctl->irq != IrqTIMER && ctl->irq != IrqCLOCK)
-				preemption(0);
+				preempted();
 		}
 	}
 	else if(vno <= nelem(excname) && up->type == Interp){
@@ -528,9 +528,7 @@
 	p->kparg = arg;
 }
 
-
-
-ulong
+uintptr
 dbgpc(Proc *p)
 {
 	Ureg *ureg;
--- a/os/port/edf.c
+++ b/os/port/edf.c
@@ -1,5 +1,5 @@
 /* EDF scheduling */
-#include	"u.h"
+#include	<u.h>
 #include	"../port/lib.h"
 #include	"mem.h"
 #include	"dat.h"
@@ -9,10 +9,13 @@
 #include	<trace.h>
 
 /* debugging */
-int	edfprint = 0;
-#define DPRINT	if(edfprint)print
+enum {
+	Dontprint = 1,
+};
 
-static vlong	now;
+#define DPRINT	if(Dontprint){}else print
+
+static long	now;	/* Low order 32 bits of time in µs */
 extern ulong	delayedscheds;
 extern Schedq	runq[Nrq];
 extern int	nrdy;
@@ -21,7 +24,6 @@
 /* Statistics stuff */
 ulong		nilcount;
 ulong		scheds;
-vlong		edfruntime;
 ulong		edfnrun;
 int		misseddeadlines;
 
@@ -39,11 +41,10 @@
 static Proc *qschedulability;
 
 enum {
-	Onemicrosecond =	1000ULL,
-	Onemillisecond =	1000000ULL,
-	Onesecond =		1000000000ULL,
-	OneRound = 		Onemillisecond/2LL,
-	MilliRound = 		Onemicrosecond/2LL,
+	Onemicrosecond =	1,
+	Onemillisecond =	1000,
+	Onesecond =		1000000,
+	OneRound = 		Onemillisecond/2,
 };
 
 static int
@@ -57,8 +58,8 @@
 	case 'U':
 		t = va_arg(f->args, uvlong);
 		break;
-	case 't':	// vlong in nanoseconds
-		t = va_arg(f->args, vlong);
+	case 't':			/* vlong in nanoseconds */
+		t = va_arg(f->args, long);
 		break;
 	default:
 		return fmtstrcpy(f, "(timeconv)");
@@ -71,17 +72,18 @@
 		sign = "";
 	if (t > Onesecond){
 		t += OneRound;
-		sprint(buf, "%s%d.%.3ds", sign, (int)(t / Onesecond), (int)(t % Onesecond)/1000000);
-	}else if (t > Onemillisecond){
-		t += MilliRound;
-		sprint(buf, "%s%d.%.3dms", sign, (int)(t / Onemillisecond), (int)(t % Onemillisecond)/1000);
-	}else if (t > Onemicrosecond)
-		sprint(buf, "%s%d.%.3dµs", sign, (int)(t / Onemicrosecond), (int)(t % Onemicrosecond));
+		sprint(buf, "%s%d.%.3ds", sign, (int)(t / Onesecond),
+			(int)(t % Onesecond)/Onemillisecond);
+	}else if (t > Onemillisecond)
+		sprint(buf, "%s%d.%.3dms", sign, (int)(t / Onemillisecond),
+			(int)(t % Onemillisecond));
 	else
-		sprint(buf, "%s%dns", sign, (int)t);
+		sprint(buf, "%s%dµs", sign, (int)t);
 	return fmtstrcpy(f, buf);
 }
 
+long edfcycles;
+
 Edf*
 edflock(Proc *p)
 {
@@ -90,8 +92,12 @@
 	if (p->edf == nil)
 		return nil;
 	ilock(&thelock);
-	if ((e = p->edf) && (e->flags & Admitted)){
-		now = todget(nil);
+	if((e = p->edf) && (e->flags & Admitted)){
+		thelock.pc = getcallerpc(&p);
+#ifdef EDFCYCLES
+		edfcycles -= lcycles();
+#endif
+		now = µs();
 		return e;
 	}
 	iunlock(&thelock);
@@ -101,7 +107,10 @@
 void
 edfunlock(void)
 {
-	edfruntime += todget(nil) - now;
+
+#ifdef EDFCYCLES
+	edfcycles += lcycles();
+#endif
 	edfnrun++;
 	iunlock(&thelock);
 }
@@ -113,8 +122,8 @@
 		fmtinstall('t', timeconv);
 		edfinited++;
 	}
-	now = todget(nil);
-	DPRINT("%t edfinit %lud[%s]\n", now, p->pid, statename[p->state]);
+	now = µs();
+	DPRINT("%lud edfinit %lud[%s]\n", now, p->pid, statename[p->state]);
 	p->edf = malloc(sizeof(Edf));
 	if(p->edf == nil)
 		error(Enomem);
@@ -133,8 +142,8 @@
 		return;
 
 	p = t->ta;
-
-	DPRINT("%t deadlineintr %lud[%s]\n", todget(nil), p->pid, statename[p->state]);
+	now = µs();
+	DPRINT("%lud deadlineintr %lud[%s]\n", now, p->pid, statename[p->state]);
 	/* If we're interrupting something other than the proc pointed to by t->a,
 	 * we've already achieved recheduling, so we need not do anything
 	 * Otherwise, we must cause a reschedule, but if we call sched()
@@ -142,9 +151,8 @@
 	 * Instead, we cause the resched to happen when the interrupted proc
 	 * returns to user space
 	 */
-	if (p == up){
-		pt = proctrace;
-		if(up->trace && pt)
+	if(p == up){
+		if(up->trace && (pt = proctrace))
 			pt(up, SInts, 0);
 		up->delaysched++;
  		delayedscheds++;
@@ -157,18 +165,26 @@
 	/* Called with edflock held */
 	Edf *e;
 	void (*pt)(Proc*, int, vlong);
+	long n;
+	vlong nowns;
 
 	e = p->edf;
 	e->flags &= ~Yield;
-	if (e->d < now){
+	if(e->d - now < 0){
 		e->periods++;
 		e->r = now;
-		if ((e->flags & Sporadic) == 0){
-			/* Non sporadic processes stay true to their period;
-			 * calculate next release time
+		if((e->flags & Sporadic) == 0){
+			/*
+			 * Non sporadic processes stay true to their period;
+			 * calculate next release time.
+			 * Second test limits duration of while loop.
 			 */
-			while(e->t <= now)
-				e->t += e->T;
+			if((n = now - e->t) > 0){
+				if(n < e->T)
+					e->t += e->T;
+				else
+					e->t = now + e->T - (n % e->T);
+			}
 		}else{
 			/* Sporadic processes may not be released earlier than
 			 * one period after this release
@@ -177,20 +193,21 @@
 		}
 		e->d = e->r + e->D;
 		e->S = e->C;
-		DPRINT("%t release %lud[%s], r=%t, d=%t, t=%t, S=%t\n",
+		DPRINT("%lud release %lud[%s], r=%lud, d=%lud, t=%lud, S=%lud\n",
 			now, p->pid, statename[p->state], e->r, e->d, e->t, e->S);
-		if (pt = proctrace){
-			pt(p, SRelease, e->r);
-			pt(p, SDeadline, e->d);
+		if(pt = proctrace){
+			nowns = todget(nil);
+			pt(p, SRelease, nowns);
+			pt(p, SDeadline, nowns + 1000LL*e->D);
 		}
 	}else{
-		DPRINT("%t release %lud[%s], too late t=%t, called from 0x%lux\n",
+		DPRINT("%lud release %lud[%s], too late t=%lud, called from %#p\n",
 			now, p->pid, statename[p->state], e->t, getcallerpc(&p));
 	}
 }
 
 static void
-releaseintr(Ureg*, Timer *t)
+releaseintr(Ureg *u, Timer *t)
 {
 	Proc *p;
 	extern int panicking;
@@ -202,7 +219,7 @@
 	p = t->ta;
 	if((edflock(p)) == nil)
 		return;
-	DPRINT("%t releaseintr %lud[%s]\n", now, p->pid, statename[p->state]);
+	DPRINT("%lud releaseintr %lud[%s]\n", now, p->pid, statename[p->state]);
 	switch(p->state){
 	default:
 		edfunlock();
@@ -209,8 +226,8 @@
 		return;
 	case Ready:
 		/* remove proc from current runq */
-		rq = &runq[p->pri];
-		if (dequeueproc(rq, p) != p){
+		rq = &runq[p->priority];
+		if(dequeueproc(rq, p) != p){
 			DPRINT("releaseintr: can't find proc or lock race\n");
 			release(p);	/* It'll start best effort */
 			edfunlock();
@@ -221,8 +238,11 @@
 	case Waitrelease:
 		release(p);
 		edfunlock();
+		if(p->state == Wakeme){
+			iprint("releaseintr: wakeme\n");
+		}
 		ready(p);
-		if (up){
+		if(up){
 			up->delaysched++;
 			delayedscheds++;
 		}
@@ -234,10 +254,8 @@
 	case Wakeme:
 		release(p);
 		edfunlock();
-		if (p->trend)
-			wakeup(p->trend);
-		p->trend = nil;
-		if (up){
+		twakeup(u, t);
+		if(up){
 			up->delaysched++;
 			delayedscheds++;
 		}
@@ -249,7 +267,7 @@
 void
 edfrecord(Proc *p)
 {
-	vlong used;
+	long used;
 	Edf *e;
 	void (*pt)(Proc*, int, vlong);
 
@@ -256,15 +274,15 @@
 	if((e = edflock(p)) == nil)
 		return;
 	used = now - e->s;
-	if (e->d <= now)
+	if(e->d - now <= 0)
 		e->edfused += used;
 	else
 		e->extraused += used;
-	if (e->S > 0){
-		if (e->S <= used){
+	if(e->S > 0){
+		if(e->S <= used){
 			if(pt = proctrace)
-				pt(p, SSlice, now);
-			DPRINT("%t edfrecord slice used up\n", now);
+				pt(p, SSlice, 0);
+			DPRINT("%lud edfrecord slice used up\n", now);
 			e->d = now;
 			e->S = 0;
 		}else
@@ -279,11 +297,13 @@
 {
 	Edf *e;
 	void (*pt)(Proc*, int, vlong);
+	long tns;
 
 	e = p->edf;
 	/* Called with edflock held */
 	if(edfpri){
-		if (e->d <= now || e->S == 0){
+		tns = e->d - now;
+		if(tns <= 0 || e->S == 0){
 			/* Deadline reached or resources exhausted,
 			 * deschedule forthwith
 			 */
@@ -292,17 +312,19 @@
 			e->s = now;
 			return;
 		}
-		e->tns = now + e->S;
-		if (e->d < e->tns)
-			e->tns = e->d;
+		if(e->S < tns)
+			tns = e->S;
+		if(tns < 20)
+			tns = 20;
+		e->tns = 1000LL * tns;	/* µs to ns */
 		if(e->tt == nil || e->tf != deadlineintr){
-			DPRINT("%t edfrun, deadline=%t\n", now, e->tns);
+			DPRINT("%lud edfrun, deadline=%lud\n", now, tns);
 		}else{
 			DPRINT("v");
 		}
 		if(p->trace && (pt = proctrace))
-			pt(p, SInte, e->tns);
-		e->tmode = Tabsolute;
+			pt(p, SInte, todget(nil) + e->tns);
+		e->tmode = Trelative;
 		e->tf = deadlineintr;
 		e->ta = p;
 		timeradd(e);
@@ -320,6 +342,7 @@
 	int i;
 	Proc *r;
 	void (*pt)(Proc*, int, vlong);
+	long tns;
 
 	e = p->edf;
 	if (e->flags & Admitted)
@@ -346,8 +369,8 @@
 
 	edflock(p);
 
-	if(pt = proctrace)
-		pt(p, SAdmit, now);
+	if(p->trace && (pt = proctrace))
+		pt(p, SAdmit, 0);
 
 	/* Look for another proc with the same period to synchronize to */
 	SET(r);
@@ -366,13 +389,13 @@
 		e->d = 0;
 		release(p);
 		if (p == up){
-			DPRINT("%t edfadmit self %lud[%s], release now: r=%t d=%t t=%t\n",
+			DPRINT("%lud edfadmit self %lud[%s], release now: r=%lud d=%lud t=%lud\n",
 				now, p->pid, statename[p->state], e->r, e->d, e->t);
 			/* We're already running */
 			edfrun(p, 1);
 		}else{
 			/* We're releasing another proc */
-			DPRINT("%t edfadmit other %lud[%s], release now: r=%t d=%t t=%t\n",
+			DPRINT("%lud edfadmit other %lud[%s], release now: r=%lud d=%lud t=%lud\n",
 				now, p->pid, statename[p->state], e->r, e->d, e->t);
 			p->ta = p;
 			edfunlock();
@@ -384,19 +407,22 @@
 		/* Release in synch to something else */
 		e->t = r->edf->t;
 		if (p == up){
-			DPRINT("%t edfadmit self %lud[%s], release at %t\n",
+			DPRINT("%lud edfadmit self %lud[%s], release at %lud\n",
 				now, p->pid, statename[p->state], e->t);
 			edfunlock();
 			qunlock(&edfschedlock);
 			return nil;
 		}else{
-			DPRINT("%t edfadmit other %lud[%s], release at %t\n",
+			DPRINT("%lud edfadmit other %lud[%s], release at %lud\n",
 				now, p->pid, statename[p->state], e->t);
 			if(e->tt == nil){
 				e->tf = releaseintr;
 				e->ta = p;
-				e->tns = e->t;
-				e->tmode = Tabsolute;
+				tns = e->t - now;
+				if(tns < 20)
+					tns = 20;
+				e->tns = 1000LL * tns;
+				e->tmode = Trelative;
 				timeradd(e);
 			}
 		}
@@ -412,13 +438,12 @@
 	Edf *e;
 	void (*pt)(Proc*, int, vlong);
 
-	if (e = edflock(p)){
-		DPRINT("%t edfstop %lud[%s]\n", now, p->pid, statename[p->state]);
-		if(pt = proctrace)
-			pt(p, SExpel, now);
+	if(e = edflock(p)){
+		DPRINT("%lud edfstop %lud[%s]\n", now, p->pid, statename[p->state]);
+		if(p->trace && (pt = proctrace))
+			pt(p, SExpel, 0);
 		e->flags &= ~Admitted;
-		if (e->tt)
-			timerdel(e);
+		timerdel(e);
 		edfunlock();
 	}
 }
@@ -426,7 +451,8 @@
 static int
 yfn(void *)
 {
-	return up->trend == nil || todget(nil) >= up->edf->r;
+	now = µs();
+	return up->trend == nil || now - up->edf->r >= 0;
 }
 
 void
@@ -435,27 +461,38 @@
 	/* sleep until next release */
 	Edf *e;
 	void (*pt)(Proc*, int, vlong);
+	long n;
 
 	if((e = edflock(up)) == nil)
 		return;
-	if(pt = proctrace)
-		pt(up, SYield, now);
-	while(e->t < now)
-		e->t += e->T;
+	if(up->trace && (pt = proctrace))
+		pt(up, SYield, 0);
+	if((n = now - e->t) > 0){
+		if(n < e->T)
+			e->t += e->T;
+		else
+			e->t = now + e->T - (n % e->T);
+	}
 	e->r = e->t;
 	e->flags |= Yield;
 	e->d = now;
-	if (up->tt == nil){
-		up->tns = e->t;
-		up->tf = releaseintr;
-		up->tmode = Tabsolute;
-		up->ta = up;
-		up->trend = &up->sleep;
-		timeradd(up);
-	}else if(up->tf != releaseintr)
-		print("edfyield: surprise! 0x%lux\n", up->tf);
+	n = e->t - now;
+	if(n < 20)
+		n = 20;
+	up->tns = 1000LL * n;
+	up->tf = releaseintr;
+	up->tmode = Trelative;
+	up->ta = up;
+	up->trend = &up->sleep;
+	timeradd(up);
 	edfunlock();
+	if(waserror()){
+		up->trend = nil;
+		timerdel(up);
+		nexterror();
+	}
 	sleep(&up->sleep, yfn, nil);
+	poperror();
 }
 
 int
@@ -465,25 +502,40 @@
 	Schedq *rq;
 	Proc *l, *pp;
 	void (*pt)(Proc*, int, vlong);
+	long n;
 
 	if((e = edflock(p)) == nil)
 		return 0;
-	if (e->d <= now){
+
+	if(p->state == Wakeme && p->r){
+		iprint("edfready: wakeme\n");
+	}
+	if(e->d - now <= 0){
 		/* past deadline, arrange for next release */
-		if ((e->flags & Sporadic) == 0){
-			/* Non sporadic processes stay true to their period, calculate next release time */
-			while(e->t < now)
-				e->t += e->T;
-		}	
-		if (now < e->t){
+		if((e->flags & Sporadic) == 0){
+			/*
+			 * Non sporadic processes stay true to their period;
+			 * calculate next release time.
+			 */
+			if((n = now - e->t) > 0){
+				if(n < e->T)
+					e->t += e->T;
+				else
+					e->t = now + e->T - (n % e->T);
+			}
+		}
+		if(now - e->t < 0){
 			/* Next release is in the future, schedule it */
-			if (e->tt == nil || e->tf != releaseintr){
-				e->tns = e->t;
-				e->tmode = Tabsolute;
+			if(e->tt == nil || e->tf != releaseintr){
+				n = e->t - now;
+				if(n < 20)
+					n = 20;
+				e->tns = 1000LL * n;
+				e->tmode = Trelative;
 				e->tf = releaseintr;
 				e->ta = p;
 				timeradd(e);
-				DPRINT("%t edfready %lud[%s], release=%t\n",
+				DPRINT("%lud edfready %lud[%s], release=%lud\n",
 					now, p->pid, statename[p->state], e->t);
 			}
 			if(p->state == Running && (e->flags & (Yield|Yieldonblock)) == 0 && (e->flags & Extratime)){
@@ -493,17 +545,18 @@
 				 * best effort
 				 */
 				DPRINT(">");
-				p->pri = PriExtra;
+				p->basepri = PriExtra;
+				p->fixedpri = 1;
 				edfunlock();
 				return 0;	/* Stick on runq[PriExtra] */
 			}
-			DPRINT("%t edfready %lud[%s] wait release at %t\n",
+			DPRINT("%lud edfready %lud[%s] wait release at %lud\n",
 				now, p->pid, statename[p->state], e->t);
 			p->state = Waitrelease;
 			edfunlock();
 			return 1;	/* Make runnable later */
 		}
-		DPRINT("%t edfready %lud %s release now\n", now, p->pid, statename[p->state]);
+		DPRINT("%lud edfready %lud %s release now\n", now, p->pid, statename[p->state]);
 		/* release now */
 		release(p);
 	}
@@ -528,12 +581,12 @@
 	rq->n++;
 	nrdy++;
 	runvec |= 1 << PriEdf;
-	p->pri = PriEdf;
+	p->priority = PriEdf;
 	p->readytime = m->ticks;
 	p->state = Ready;
 	unlock(runq);
-	if(pt = proctrace)
-		pt(p, SReady, now);
+	if(p->trace && (pt = proctrace))
+		pt(p, SReady, 0);
 	return 1;
 }
 
@@ -553,7 +606,7 @@
 	SET(xp);
 	for (xpp = &qschedulability; *xpp; xpp = &xp->edf->testnext) {
 		xp = *xpp;
-		if (e->testtime < xp->edf->testtime
+		if (e->testtime - xp->edf->testtime < 0
 		|| (e->testtime == xp->edf->testtime && e->testtype < xp->edf->testtype)){
 			e->testnext = xp;
 			*xpp = p;
@@ -568,7 +621,7 @@
 testschedulability(Proc *theproc)
 {
 	Proc *p;
-	vlong H, G, Cb, ticks;
+	long H, G, Cb, ticks;
 	int steps, i;
 
 	/* initialize */
@@ -595,7 +648,7 @@
 		case Dl:
 			H += p->edf->C;
 			Cb = 0;
-			DPRINT("\tStep %3d, Ticks %t, pid %lud, deadline, H += %t → %t, Cb = %t\n",
+			DPRINT("\tStep %3d, Ticks %lud, pid %lud, deadline, H += %lud → %lud, Cb = %lud\n",
 				steps, ticks, p->pid, p->edf->C, H, Cb);
 			if (H+Cb>ticks){
 				DPRINT("not schedulable\n");
@@ -606,7 +659,7 @@
 			testenq(p);
 			break;
 		case Rl:
-			DPRINT("\tStep %3d, Ticks %t, pid %lud, release, G  %t, C%t\n",
+			DPRINT("\tStep %3d, Ticks %lud, pid %lud, release, G  %lud, C%lud\n",
 				steps, ticks, p->pid, p->edf->C, G);
 			if(ticks && G <= ticks){
 				DPRINT("schedulable\n");
--- a/os/port/edf.h
+++ b/os/port/edf.h
@@ -16,29 +16,30 @@
 typedef struct Edf		Edf;
 
 struct Edf {
+	/* All times in µs */
 	/* time intervals */
-	vlong		D;			/* Deadline */
-	vlong		Delta;		/* Inherited deadline */
-	vlong		T;			/* period */
-	vlong		C;			/* Cost */
-	vlong		S;			/* Slice: time remaining in this period */
-	/* times */
-	vlong		r;			/* (this) release time */
-	vlong		d;			/* (this) deadline */
-	vlong		t;			/* Start of next period, t += T at release */
-	vlong		s;			/* Time at which this proc was last scheduled */
+	long		D;		/* Deadline */
+	long		Delta;		/* Inherited deadline */
+	long		T;		/* period */
+	long		C;		/* Cost */
+	long		S;		/* Slice: time remaining in this period */
+	/* times (only low-order bits of absolute time) */
+	long		r;		/* (this) release time */
+	long		d;		/* (this) deadline */
+	long		t;		/* Start of next period, t += T at release */
+	long		s;		/* Time at which this proc was last scheduled */
 	/* for schedulability testing */
-	vlong		testDelta;
-	int			testtype;	/* Release or Deadline */
-	vlong		testtime;
+	long		testDelta;
+	int		testtype;	/* Release or Deadline */
+	long		testtime;
 	Proc		*testnext;
 	/* other */
 	ushort		flags;
 	Timer;
 	/* Stats */
-	vlong		edfused;
-	vlong		extraused;
-	vlong		aged;
+	long		edfused;
+	long		extraused;
+	long		aged;
 	ulong		periods;
 	ulong		missed;
 };
@@ -45,7 +46,7 @@
 
 extern Lock	edftestlock;	/* for atomic admitting/expelling */
 
-#pragma	varargck	type	"t"		vlong
+#pragma	varargck	type	"t"		long
 #pragma	varargck	type	"U"		uvlong
 
 /* Interface: */
--- a/os/port/pgrp.c
+++ b/os/port/pgrp.c
@@ -33,6 +33,7 @@
 	if(mh == nil)
 		return;
 
+	USED(s);
 	dumpchan("		from ", mh->from);
 	print("			to\n");
 	m = mh->mount;
--- a/os/port/portdat.h
+++ b/os/port/portdat.h
@@ -508,7 +508,7 @@
 enum {
 	/* Mode */
 	Trelative,	/* timer programmed in ns from now */
-	Tabsolute,	/* timer programmed in ns since epoch */
+	Tabsolute,	/* timer programmed in ns since epoch - not used in 9front */
 	Tperiodic,	/* periodic timer, period in ns */
 };
 
@@ -548,6 +548,7 @@
 	Proc_exitme,
 	Proc_traceme,
 	Proc_exitbig,
+	Proc_tracesyscall,
 
 	TUser = 0, 		/* Proc.time */
 	TSys,
@@ -556,7 +557,7 @@
 	TCSys,
 	TCReal,
 
-	NERR		= 30,
+	NERR		= 64,
 	NNOTE = 5,
 
 	Unknown		= 0,
@@ -565,18 +566,23 @@
 	Forth,
 	BusyGC,
 
-	PriLock		= 0,	/* Holding Spin lock */
-	PriEdf,	/* active edf processes */
-	PriRelease,	/* released edf processes */
-	PriRealtime,		/* Video telephony */
-	PriHicodec,		/* MPEG codec */
-	PriLocodec,		/* Audio codec */
-	PriHi,			/* Important task */
-	PriNormal,
-	PriLo,
-	PriBackground,
-	PriExtra,	/* edf processes we don't care about */
-	Nrq
+	Npriq		= 20,		/* number of scheduler priority levels */
+	Nrq		= Npriq+2,	/* number of priority levels including real time */
+	PriRelease	= Npriq,	/* released edf processes */
+	PriEdf		= Npriq+1,	/* active edf processes */
+	PriNormal	= 10,		/* base priority for normal processes */
+	PriExtra	= Npriq-1,	/* edf processes at high best-effort pri */
+	PriKproc	= 13,		/* base priority for kernel processes */
+	PriRoot		= 13,		/* base priority for root processes */
+
+	/* used by inferno, remove them at some point when /prog is removed */
+	PriLock		= Npriq,	/* Holding Spin lock */
+	PriRealtime = Npriq+1,	/* Video telephony */
+	PriHicodec	= Npriq,	/* MPEG codec */
+	PriLocodec	= Npriq,	/* Audio codec */
+	PriHi		= Npriq,	/* Important task */
+	PriLo		= 7,
+	PriBackground = 4,
 };
 
 struct Schedq
@@ -604,10 +610,6 @@
 
 	Proc	*rnext;		/* next process in run queue */
 	Proc	*qnext;		/* next process on queue for a QLock */
-							/* check notes in proc.c for how these 2 fields are used */
-	void	*blockinglock;	/* address of QLock or RWLock being queued for, DEBUG */
-						/* not in 9front as we can reason that info from qpc */
-	uintptr	qpc;		/* last call that blocked in QLock or RWLock */
 
 	char	*psstate;	/* What /proc/#/status reports */
 	s32		state;
@@ -634,10 +636,10 @@
 
 /*	Fgrp	*closingfgrp;*/	/* used during teardown */
 
-/*	int	insyscall;*/
+	int	insyscall;
 	u32	time[6];	/* User, Sys, Real; child U, S, R */
 
-	uvlong	kentry;		/* Kernel entry time stamp (for profiling) */
+	u64	kentry;		/* Kernel entry time stamp (for profiling) */
 	/*
 	 * pcycles: cycles spent in this process (updated on procswitch)
 	 * when this is the current proc and we're in the kernel
@@ -646,7 +648,7 @@
 	 * when this is not the current process or we're in user mode
 	 * (procrestores and procsaves balance), it is pcycles.
 	 */
-	vlong	pcycles;
+	s64	pcycles;
 
 	QLock	debug;		/* to access debugging elements of User */
 	Proc	*pdbg;		/* the debugging process */
@@ -720,6 +722,7 @@
 	Edf	*edf;		/* if non-null, real-time proc, edf contains scheduling params */
 	int	trace;		/* process being traced? */
 
+	uintptr	qpc;		/* pc calling last blocking qlock */
 	QLock	*eql;		/* interruptable eqlock */
 
 	void	*ureg;		/* User registers for notes */
@@ -740,7 +743,7 @@
 	Osenv	*env;
 	Osenv	defenv;
 	s32		swipend;	/* software interrupt pending for Prog TODO replace with notepending? */
-	Lock	sysio;		/* note handler lock */
+	Lock	sysio;		/* note handler lock */ 
 
 	/* inferno specific fields that are obsolete? */
 	int		fpstate;
@@ -752,8 +755,8 @@
 	/* forth specific fields */
 	Proc	*fprev, *fnext;	/* forth processes linked list */
 	void	*fmem;			/* forth process memory - sandboxed except for macro primitives */
-	void	*shm;		/* for devshm */
-	void	*readyfds;	/* for devready.c */
+	void	*shm;		/* for devshm. move this into Osenv or maybe remove Osenv at some point to get more in sync with 9front */
+	void	*canread;	/* for devready.c */
 	u8		fstarted;	/* 0 while waiting for the pctl message */
 };
 
@@ -1080,3 +1083,32 @@
 	uint n;
 	char buf[16384];
 } kmesg;
+
+/*
+ * shared memory data structures. Modeled after Egrp. used by devshm.
+ */
+typedef struct Svalue Svalue;
+struct Svalue
+{
+	Ref;
+	RWlock;
+	char	*name;
+	char	*value;
+	s32	len;
+	s32 vers;
+	u8 dead;	/* set by remove() */
+};
+
+typedef struct Sgrp Sgrp;
+struct Sgrp
+{
+	Ref;
+	RWlock;
+	union{		/* array of Svalue pointers */
+		Svalue	**entries;
+		Svalue	**ent;
+	};
+	int	nent;	/* number of entries used */
+	int	ment;	/* maximum number of entries */
+	u32	vers;	/* of Sgrp */
+};
--- a/os/port/portfns.h
+++ b/os/port/portfns.h
@@ -29,6 +29,7 @@
 void		ccloseq(Chan*);
 void		closeegrp(Egrp*);
 void		closefgrp(Fgrp*);
+void		closergrp(Rgrp*);
 void		closemount(Mount*);
 void		closepgrp(Pgrp*);
 void		closesigs(Skeyset*);
@@ -51,8 +52,10 @@
 void		cursoron(void);
 void		cursoroff(void);
 void		cwrite(Chan*, uchar*, int, vlong);
+uintptr		dbgpc(Proc*);
 void		debugkey(Rune, char *, void(*)(), int);
 s32		decref(Ref*);
+Proc*		dequeueproc(Schedq*, Proc*);
 Chan*		devattach(int, char*);
 Block*		devbread(Chan*, s32, u32);
 s32		devbwrite(Chan*, Block*, u32);
@@ -82,6 +85,13 @@
 void		dumppgrp(char *s, Pgrp *p);
 void		dumpstack(void);
 Fgrp*		dupfgrp(Fgrp*);
+void		edfinit(Proc*);
+char*		edfadmit(Proc*);
+int		edfready(Proc*);
+void		edfrecord(Proc*);
+void		edfrun(Proc*, int);
+void		edfstop(Proc*);
+void		edfyield(void);
 void		egrpcpy(Egrp*, Egrp*);
 int		emptystr(char*);
 int		eqchan(Chan*, Chan*, int);
@@ -102,7 +112,6 @@
 Chan*		fdtochan(Fgrp*, int, int, int, int);
 int		findmount(Chan**, Mhead**, int, int, Qid);
 void		forceclosefgrp(void);
-void		forthmain(void *);
 void		free(void*);
 void		freeb(Block*);
 void		freeblist(Block*);
@@ -223,10 +232,11 @@
 int		preempted(void);
 int		preemption(int);
 void		printinit(void);
-void		procctl(Proc*);
+void		procctl(void);
 void		procdump(void);
 int		procindex(ulong);
 void		procinit(void);
+void		procpriority(Proc*, int, int);
 Proc*		proctab(int);
 void	(*proctrace)(Proc*, int, vlong); 
 int		progfdprint(Chan*, int, int, char*, int);
@@ -295,6 +305,8 @@
 int		setpri(int);
 void		setrealloctag(void*, uintptr);
 void		setupwatchpts(Proc*, Watchpt*, int);
+Sgrp*	shmgrpnew(void);
+void	shmgrpclose(Sgrp *g);
 void	showconf(void);
 void	shownotes(Proc*);
 char*		skipslash(char*);
@@ -322,6 +334,7 @@
 int		tready(void*);
 Block*		trimblock(Block*, int, int);
 void		tsleep(Rendez*, int (*)(void*), void*, int);
+void		twakeup(Ureg*, Timer *);
 int		uartctl(Uart*, char*);
 int		uartgetc(void);
 void		uartkick(void*);
@@ -359,3 +372,5 @@
 u64		nhgetv(void*);
 u32		nhgetl(void*);
 u16		nhgets(void*);
+u32		µs(void);
+long		lcycles(void);
--- a/os/port/proc.c
+++ b/os/port/proc.c
@@ -4,26 +4,26 @@
 #include	"dat.h"
 #include	"fns.h"
 #include	"../port/error.h"
+#include	"edf.h"
+#include	<trace.h>
+#include	"tos.h"
 #include	<interp.h>
+#include	"ureg.h"
 
 static int debug = 0;
 
-/* Ref	pidalloc; */
 int	schedgain = 30;	/* units in seconds */
 int	nrdy;
 
+void updatecpu(Proc*);
+int reprioritize(Proc*);
+
 ulong	delayedscheds;	/* statistics */
 ulong	skipscheds;
 ulong	preempts;
+ulong	pload;
 s32	prevpid;
 
-/* bitmap of priorities of procs ready to run. When any process is
- * queued, the bit corresponding to that priority gets set.
- * when there are no more processes to run at a priority, then the
- * corresponding bit gets cleared.
- */
-static u32	occupied;
-
 static struct Procalloc
 {
 	Lock;
@@ -31,12 +31,19 @@
 	Proc*	free;
 } procalloc;
 
+enum
+{
+	Q=10,
+	DQ=4,
+	Scaling=2,
+};
+
 /* multiple run queues by priority, different from Brian's book
  * Per Brian's book, it is the struct Procs == struct Schedq.
  * Now, inferno maintains multiple Schedq based on priority.
  */
-static Schedq	runq[Nrq];
-int	nrdy;
+Schedq	runq[Nrq];
+ulong	runvec;
 
 char *statename[] =
 {			/* BUG: generate automatically */
@@ -55,6 +62,7 @@
 	"Waitrelease",
 };
 
+static void rebalance(void);
 static void pidinit(void);
 static void pidfree(Proc*);
 
@@ -89,9 +97,6 @@
   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.
@@ -99,16 +104,17 @@
 void
 schedinit(void)		/* never returns */
 {
+	Edf *e;
+
 	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){
+		default:
+			updatecpu(up);
+			break;
 		case Running:
 			/*
 			 * process state from Runnning -> Ready
@@ -118,13 +124,14 @@
 			break;
 		case Moribund:
 			up->state = Dead;
-/*
 			edfstop(up);
-			if(up->edf){
+			if(up->edf != nil){
 				free(up->edf);
 				up->edf = nil;
 			}
-*/
+
+			/* mmurelease(up); linear memory on 9front */
+
 			lock(&procalloc);
 			up->mach = nil;
 			up->qnext = procalloc.free;
@@ -145,6 +152,36 @@
 	sched();
 }
 
+/*
+int
+kenter(Ureg *ureg)
+{
+	int user;
+
+	user = userureg(ureg);
+	if(user){
+		up->dbgreg = ureg;
+		cycles(&up->kentry);
+	}
+	return user;
+}
+
+void
+kexit(Ureg*)
+{
+	uvlong t;
+	Tos *tos;
+
+	cycles(&t);
+
+	\/* precise time accounting, kernel exit *\/
+	tos = (Tos*)(USTKTOP-sizeof(Tos));
+	tos->kcycles += t - up->kentry;
+	tos->pcycles = t + up->pcycles;
+	tos->pid = up->pid;
+}
+*/
+
 static void
 procswitch(void)
 {
@@ -154,6 +191,7 @@
 	m->cs++;
 
 	cycles(&t);
+	up->kentry -= t;
 	up->pcycles += t;
 
 	procsave(up);
@@ -165,6 +203,7 @@
 	procrestore(up);
 
 	cycles(&t);
+	up->kentry += t;
 	up->pcycles -= t;
 }
 
@@ -202,9 +241,8 @@
 		if(up->nlocks)
 		if(up->state != Moribund)
 		if(up->delaysched < 20
-/*		|| palloc.Lock.p == up
-		|| fscache.Lock.p == up
-*/
+		/*|| palloc.Lock.p == up
+		|| fscache.Lock.p == up */
 		|| procalloc.Lock.p == up){
 			up->delaysched++;
  			delayedscheds++;
@@ -221,6 +259,13 @@
 	 * first time entering schedinit()
 	 */
 	p = runproc();
+	if(p->edf == nil){
+		updatecpu(p);
+		p->priority = reprioritize(p);
+	}
+	if(p != m->readied)
+		m->schedticks = m->ticks + HZ/10;
+	m->readied = nil;
 	up = p;
 	up->state = Running;
 	up->mach = MACHP(m->machno);
@@ -228,39 +273,175 @@
 	gotolabel(&up->sched);
 }
 
+int
+anyready(void)
+{
+	return runvec;
+}
+
+int
+anyhigher(void)
+{
+	return runvec & ~((1<<(up->priority+1))-1);
+}
+
 /*
- * ready(p) is simpler as we do not change process priorities
- * puts the current process at the end of the run queue
- * p->state = Running -> Ready
+ *  here once per clock tick to see if we should resched
  */
 void
-ready(Proc *p)
+hzsched(void)
 {
-	int s;
-	Schedq *rq;
+	/* once a second, rebalance will reprioritize ready procs */
+	if(m->machno == 0)
+		rebalance();
 
-	if(p->state == Ready){
-		print("double ready %s %ud pc %p\n", p->text, p->pid, getcallerpc(&p));
-		return;
+	/* unless preempted, get to run for at least 100ms */
+	if(anyhigher()
+	|| (!up->fixedpri && (long)(m->ticks - m->schedticks) > 0 && anyready())){
+		m->readied = nil;	/* avoid cooperative scheduling */
+		up->delaysched++;
 	}
+}
 
-	s = splhi();
 /*
-	if(edfready(p)){
-		splx(s);
+ *  here at the end of non-clock interrupts to see if we should preempt the
+ *  current process.  Returns 1 if preempted, 0 otherwise.
+ */
+int
+preempted(void)
+{
+	if(up != nil && up->state == Running)
+	if(up->preempted == 0)
+	if(anyhigher())
+	if(!active.exiting){
+		m->readied = nil;	/* avoid cooperative scheduling */
+		up->preempted = 1;
+		sched();
+		splhi();
+		up->preempted = 0;
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * Update the cpu time average for this particular process,
+ * which is about to change from up -> not up or vice versa.
+ * p->lastupdate is the last time an updatecpu happened.
+ *
+ * The cpu time average is a decaying average that lasts
+ * about D clock ticks.  D is chosen to be approximately
+ * the cpu time of a cpu-intensive "quick job".  A job has to run
+ * for approximately D clock ticks before we home in on its 
+ * actual cpu usage.  Thus if you manage to get in and get out
+ * quickly, you won't be penalized during your burst.  Once you
+ * start using your share of the cpu for more than about D
+ * clock ticks though, your p->cpu hits 1000 (1.0) and you end up 
+ * below all the other quick jobs.  Interactive tasks, because
+ * they basically always use less than their fair share of cpu,
+ * will be rewarded.
+ *
+ * If the process has not been running, then we want to
+ * apply the filter
+ *
+ *	cpu = cpu * (D-1)/D
+ *
+ * n times, yielding 
+ * 
+ *	cpu = cpu * ((D-1)/D)^n
+ *
+ * but D is big enough that this is approximately 
+ *
+ * 	cpu = cpu * (D-n)/D
+ *
+ * so we use that instead.
+ * 
+ * If the process has been running, we apply the filter to
+ * 1 - cpu, yielding a similar equation.  Note that cpu is 
+ * stored in fixed point (* 1000).
+ *
+ * Updatecpu must be called before changing up, in order
+ * to maintain accurate cpu usage statistics.  It can be called
+ * at any time to bring the stats for a given proc up-to-date.
+ */
+void
+updatecpu(Proc *p)
+{
+	ulong t, ocpu, n, D;
+
+	if(p->edf != nil)
 		return;
+
+	t = MACHP(0)->ticks*Scaling + Scaling/2;
+	n = t - p->lastupdate;
+	if(n == 0)
+		return;
+	p->lastupdate = t;
+
+	D = schedgain*HZ*Scaling;
+	if(n > D)
+		n = D;
+
+	ocpu = p->cpu;
+	if(p != up)
+		p->cpu = (ocpu*(D-n))/D;
+	else{
+		t = 1000 - ocpu;
+		t = (t*(D-n))/D;
+		p->cpu = 1000 - t;
 	}
-*/
+//iprint("pid %lud %s for %lud cpu %lud -> %lud\n", p->pid,p==up?"active":"inactive",n, ocpu,p->cpu);
+}
 
-	/* 9front does this. Not sure what it does yet
-	if(up != p && (p->wired == nil || p->wired == MACHP(m->machno)))
-		m->readied = p;	*//* group scheduling */
+/*
+ * On average, p has used p->cpu of a cpu recently.
+ * Its fair share is conf.nmach/m->load of a cpu.  If it has been getting
+ * too much, penalize it.  If it has been getting not enough, reward it.
+ * I don't think you can get much more than your fair share that 
+ * often, so most of the queues are for using less.  Having a priority
+ * of 3 means you're just right.  Having a higher priority (up to p->basepri) 
+ * means you're not using as much as you could.
+ */
+int
+reprioritize(Proc *p)
+{
+	int fairshare, n, load, ratio;
 
-	/* add to the end of the run queue */
-	rq = &runq[p->priority];
+	load = MACHP(0)->load;
+	if(load == 0)
+		return p->basepri;
+
+	/*
+	 * fairshare = 1.000 * conf.nmach * 1.000/load,
+	 * except the decimal point is moved three places
+	 * on both load and fairshare.
+	 */
+	fairshare = (conf.nmach*1000*1000)/load;
+	n = p->cpu;
+	if(n == 0)
+		n = 1;
+	ratio = (fairshare+n/2) / n;
+	if(ratio > p->basepri)
+		ratio = p->basepri;
+	if(ratio < 0)
+		panic("reprioritize");
+//iprint("pid %lud cpu %lud load %d fair %d pri %d\n", p->pid, p->cpu, load, fairshare, ratio);
+	return ratio;
+}
+
+/*
+ * add a process to a scheduling queue
+ */
+void
+queueproc(Schedq *rq, Proc *p)
+{
+	int pri;
+
+	pri = rq - runq;
 	lock(runq);
-	p->rnext = 0;
-	if(rq->tail)
+	p->priority = pri;
+	p->rnext = nil;
+	if(rq->tail != nil)
 		rq->tail->rnext = p;
 	else
 		rq->head = p;
@@ -267,63 +448,171 @@
 	rq->tail = p;
 	rq->n++;
 	nrdy++;
-	occupied |= 1<<p->priority;
-	p->state = Ready;
+	runvec |= 1<<pri;
 	unlock(runq);
-	splx(s);
 }
 
-int
-anyready(void)
+/*
+ *  try to remove a process from a scheduling queue (called splhi)
+ */
+Proc*
+dequeueproc(Schedq *rq, Proc *tp)
 {
-	/* same priority only */
-	return occupied & (1<<up->priority);
+	Proc *l, *p;
+
+	if(!canlock(runq))
+		return nil;
+
+	/*
+	 *  the queue may have changed before we locked runq,
+	 *  refind the target process.
+	 */
+	l = nil;
+	for(p = rq->head; p != nil; p = p->rnext){
+		if(p == tp)
+			break;
+		l = p;
+	}
+
+	/*
+	 *  p->mach==0 only when process state is saved
+	 */
+	if(p == nil || p->mach != nil){
+		unlock(runq);
+		return nil;
+	}
+	if(p->rnext == nil)
+		rq->tail = l;
+	if(l != nil)
+		l->rnext = p->rnext;
+	else
+		rq->head = p->rnext;
+	if(rq->head == nil)
+		runvec &= ~(1<<(rq-runq));
+	rq->n--;
+	nrdy--;
+	if(p->state != Ready)
+		print("dequeueproc %s %ud %s\n", p->text, p->pid, statename[p->state]);
+
+	unlock(runq);
+	return p;
 }
 
 /*
- * the higher the priority, the lower the number
- * unlike 9front
+ *  ready(p) picks a new priority for a process and sticks it in the
+ *  runq for that priority.
  */
-int
-anyhigher(void)
+void
+ready(Proc *p)
 {
-	return occupied & ((1<<up->priority)-1);
+	int s, pri;
+	Schedq *rq;
+	void (*pt)(Proc*, int, vlong);
+
+	if(p->state == Ready){
+		print("double ready %s %ud pc %p\n", p->text, p->pid, getcallerpc(&p));
+		return;
+	}
+
+	s = splhi();
+	if(edfready(p)){
+		splx(s);
+		return;
+	}
+
+	if(up != p && (p->wired == nil || p->wired == MACHP(m->machno)))
+		m->readied = p;	/* group scheduling */
+
+	updatecpu(p);
+	pri = reprioritize(p);
+	p->priority = pri;
+	rq = &runq[pri];
+	p->state = Ready;
+	queueproc(rq, p);
+	pt = proctrace;
+	if(pt != nil)
+		pt(p, SReady, 0);
+	splx(s);
 }
 
 /*
- *  here at the end of non-clock interrupts to see if we should preempt the
- *  current process.  Returns 1 if preempted, 0 otherwise.
- *  similar to 9front's preempted()
+ *  yield the processor and drop our priority
  */
-int
-preemption(int tick)
+void
+yield(void)
 {
-	if(up != nil && up->state == Running &&
-		up->preempted == 0 &&
-		active.exiting == 0 &&
-		(anyhigher() || tick && anyready())){
-		up->preempted = 1;
+	if(anyready()){
+		/* pretend we just used 1/2 tick */
+		up->lastupdate -= Scaling/2;  
 		sched();
-		splhi();
-		up->preempted = 0;
-		return 1;
 	}
-	return 0;
 }
 
+/*
+ *  recalculate priorities once a second.  We need to do this
+ *  since priorities will otherwise only be recalculated when
+ *  the running process blocks.
+ */
+ulong balancetime;
+
+static void
+rebalance(void)
+{
+	int pri, npri, x;
+	Schedq *rq;
+	Proc *p;
+	ulong t;
+
+	t = m->ticks;
+	if(t - balancetime < HZ)
+		return;
+	balancetime = t;
+
+	for(pri=0, rq=runq; pri<Npriq; pri++, rq++){
+another:
+		p = rq->head;
+		if(p == nil)
+			continue;
+		if(pri == p->basepri)
+			continue;
+		updatecpu(p);
+		npri = reprioritize(p);
+		if(npri != pri){
+			x = splhi();
+			p = dequeueproc(rq, p);
+			if(p != nil)
+				queueproc(&runq[npri], p);
+			splx(x);
+			goto another;
+		}
+	}
+}
+
+/*
+ *  pick a process to run
+ */
 Proc*
 runproc(void)
 {
-	Schedq *rq, *erq;
-	Proc *p, *tp, *last;
-	u64 start, now;
+	Schedq *rq;
+	Proc *p;
+	ulong start, now;
 	int i;
-/*	void (*pt)(Proc*, int, vlong); */
+	void (*pt)(Proc*, int, vlong);
 
 	start = perfticks();
+
+	/* cooperative scheduling until the clock ticks */
+	if((p = m->readied) != nil && p->mach == nil && p->state == Ready
+	&& (p->wired == nil || p->wired == MACHP(m->machno))
+	&& runq[Nrq-1].head == nil && runq[Nrq-2].head == nil){
+		skipscheds++;
+		rq = &runq[p->priority];
+		goto found;
+	}
+
 	preempts++;
 
-	erq = runq + Nrq - 1;
 loop:
 	/*
 	 *  find a process that last ran on this processor (affinity),
@@ -332,15 +621,14 @@
 	spllo();
 	for(i = 0;; i++){
 		/*
-		 * find the highest priority target process that this
-		 * processor can run given affinity constraints.
-		 * when i == 0, thats where we pick the associated procs
-		 * after this, we take anyone even from other cores
+		 *  find the highest priority target process that this
+		 *  processor can run given affinity constraints.
+		 *
 		 */
-		for(rq = runq; rq <= erq; rq++){
-			for(tp = rq->head; tp != nil; tp = tp->rnext){
-				if(tp->mp == nil || tp->mp == MACHP(m->machno)
-				|| (tp->wired == nil && i > 0))
+		for(rq = &runq[Nrq-1]; rq >= runq; rq--){
+			for(p = rq->head; p != nil; p = p->rnext){
+				if(p->mp == nil || p->mp == MACHP(m->machno)
+				|| (p->wired == nil && i > 0))
 					goto found;
 			}
 		}
@@ -355,82 +643,21 @@
 	}
 
 found:
-/*	print("runproc\n");
-	procdump();
-*/
 	splhi();
-	/*
-	 * try to remove the process from a scheduling queue
-	 * similar to 9front's dequeueproc()
-	 */
-	if(!canlock(runq))
+	p = dequeueproc(rq, p);
+	if(p == nil)
 		goto loop;
 
-	/*
-	 *  the queue may have changed before we locked runq,
-	 *  refind the target process.
-	 */
-	last = nil;
-	for(p = rq->head; p != nil; p = p->rnext){
-		if(p == tp)
-			break;
-		last = p;
-	}
-
-	/*
-	 *  p->mach==0 only when process state is saved
-	 */
-	if(p == nil || p->mach != nil){
-		unlock(runq);
-		goto loop;
-	}
-	/* if p is the last in the run queue
-	 * update run queue tail to point to the last */
-	if(p->rnext == nil)
-		rq->tail = last;
-	/* remove p from the linked list */
-	if(last != nil)
-		last->rnext = p->rnext;
-	else
-		rq->head = p->rnext;
-	/* no other procs in the run queue */
-	if(rq->head == nil){
-		rq->tail = nil;
-		occupied &= ~(1<<p->priority);
-	}
-	rq->n--;
-	nrdy--;
-	if(p->dbgstop){
-		p->state = Stopped;
-		unlock(runq);
-		goto loop;
-	}
-	if(p->state != Ready)
-		print("runproc %s %ud %s\n", p->text, p->pid, statename[p->state]);
-	unlock(runq);
-
 	p->state = Scheding;
 	p->mp = MACHP(m->machno);
 
-/*	if(edflock(p)){
-		edfrun(p, rq == &runq[PriEdf]);	*//* start deadline timer and do admin *//*
+	if(edflock(p)){
+		edfrun(p, rq == &runq[PriEdf]);	/* start deadline timer and do admin */
 		edfunlock();
 	}
 	pt = proctrace;
 	if(pt != nil)
 		pt(p, SRun, 0);
-*/
-/* for debugging */
-/*	if(p->pid != prevpid){
-		prevpid = p->pid;
-		if(p->type == Interp && p->iprog != nil){
-			print(" %d:%s,%d %s ",
-				p->pid, p->text, ((Prog*)p->iprog)->pid, ((Prog*)p->iprog)->R.M->m->path);
-		}else
-			print(" %d:%s", p->pid, p->text);
-	}else
-		print(".");
-*/
 	return p;
 }
 
@@ -460,15 +687,10 @@
 	p->dbgreg = nil;
 	p->nerrlab = 0;
 	p->type = Unknown;
-	p->state = Scheding;
-	p->priority = PriNormal;
-	p->mach = 0;
-	p->qnext = 0;
-	p->kp = 0;
-	p->killed = 0; /* TODO replace these 2 with notepending */
-	p->swipend = 0;
 	p->nlocks = 0;
 	p->delaysched = 0;
+	p->trace = 0;
+
 	memset(&p->defenv, 0, sizeof(p->defenv));
 	p->env = &p->defenv;
 	kstrdup(&p->env->user, "*nouser");
@@ -475,18 +697,13 @@
 	p->env->errstr = p->env->errbuf0;
 	p->env->syserrstr = p->env->errbuf1;
 
-	/* clear any previous notes */
-	p->nnote = 0;
-	p->notify = nil;
-	p->notified = 0;
-	p->notepending = 0;
-
 	/* sched params */
 	p->mp = 0;
 	p->wired = 0;
+	procpriority(p, PriNormal, 0);
+	p->cpu = 0;
+	p->lastupdate = MACHP(0)->ticks*Scaling;
 	p->edf = nil;
-	p->noteid = 0;
-	p->trace = 0;
 
 	pidalloc(p);
 	if(p->pid == 0)
@@ -532,19 +749,23 @@
 	p->mp = p->wired;
 }
 
-int
-setpri(int priority)
+void
+procpriority(Proc *p, int pri, int fixed)
 {
-	int p;
-
-	/* called by up so not on run queue */
-	p = up->priority;
-	up->priority = priority;
-	if(up->state == Running && anyhigher())
-		sched();
-	return p;
+	if(pri >= Npriq)
+		pri = Npriq - 1;
+	else if(pri < 0)
+		pri = 0;
+	p->basepri = pri;
+	p->priority = pri;
+	if(fixed){
+		p->fixedpri = 1;
+	} else {
+		p->fixedpri = 0;
+	}
 }
 
+/* called procinit0 on 9front */
 void
 procinit(void)
 {
@@ -560,8 +781,6 @@
 	}
 	procalloc.arena = p;
 	procalloc.free = p;
-
-	p = procalloc.free;
 	for(i=0; i<conf.nproc-1; i++,p++)
 		p->qnext = p+1;
 	p->qnext = 0;
@@ -582,7 +801,7 @@
 sleep(Rendez *r, int (*f)(void*), void *arg)
 {
 	int s;
-/*	void (*pt)(Proc*, int, vlong);*/
+	void (*pt)(Proc*, int, vlong);
 
 	if(up == nil)
 		panic("sleep() not in process (%zux)", getcallerpc(&r));
@@ -603,7 +822,6 @@
 	if(r->p != nil){
 		print("double sleep called from %#p, %ud %ud\n", getcallerpc(&r), r->p->pid, up->pid);
 		dumpstack();
-		panic("sleep");
 	}
 
 	/*
@@ -627,9 +845,9 @@
 		 * now we are committed to
 		 * change state and call scheduler
 		 */
-/*		pt = proctrace;
+		pt = proctrace;
 		if(pt != nil)
-			pt(up, SSleep, 0); */
+			pt(up, SSleep, 0);
 		up->state = Wakeme;
 		up->r = r;	/* for swiproc */
 		unlock(&up->rlock);
@@ -867,11 +1085,69 @@
 }
 
 /*
- * 9front maintains broken processes. Not bothering with them
- * as there should not be any broken proc's in inferno
+ * weird thing: keep at most NBROKEN around
  */
+#define	NBROKEN 4
+struct
+{
+	QLock;
+	int	n;
+	Proc	*p[NBROKEN];
+}broken;
 
+static void
+addbroken(void)
+{
+	qlock(&broken);
+	if(broken.n == NBROKEN) {
+		ready(broken.p[0]);
+		memmove(&broken.p[0], &broken.p[1], sizeof(Proc*)*(NBROKEN-1));
+		--broken.n;
+	}
+	broken.p[broken.n++] = up;
+	qunlock(&broken);
+
+	edfstop(up);
+	up->state = Broken;
+	up->psstate = nil;
+	sched();
+}
+
 void
+unbreak(Proc *p)
+{
+	int b;
+
+	qlock(&broken);
+	for(b=0; b < broken.n; b++)
+		if(broken.p[b] == p) {
+			broken.n--;
+			memmove(&broken.p[b], &broken.p[b+1],
+					sizeof(Proc*)*(NBROKEN-(b+1)));
+			ready(p);
+			break;
+		}
+	qunlock(&broken);
+}
+
+int
+freebroken(void)
+{
+	int i, n;
+
+	qlock(&broken);
+	n = broken.n;
+	for(i=0; i<n; i++) {
+		ready(broken.p[i]);
+		broken.p[i] = nil;
+	}
+	broken.n = 0;
+	qunlock(&broken);
+	return n;
+}
+
+
+void
 notkilled(void)
 {
 	lock(&up->rlock);
@@ -885,12 +1161,12 @@
 	Proc *p;
 /*	Segment **s;*/
 	ulong utime, stime;
-/*	Waitq *wq;*/
+	Waitq *wq;
 	Fgrp *fgrp;
 	Egrp *egrp;
 	Rgrp *rgrp;
 	Pgrp *pgrp;
-/*	Chan *dot;*/
+	Chan *dot;
 	void (*pt)(Proc*, int, vlong);
 
 	up->fpstate &= ~FPillegal;
@@ -897,8 +1173,8 @@
 	up->alarm = 0;
 	timerdel(up);
 	pt = proctrace;
-/*	if(pt != nil)
-		pt(up, SDead, 0);*/
+	if(pt != nil)
+		pt(up, SDead, 0);
 
 	/* nil out all the resources under lock (free later) */
 	qlock(&up->debug);
@@ -908,10 +1184,10 @@
 	up->env->egrp = nil;
 	rgrp = up->env->rgrp;
 	up->env->rgrp = nil;
+/*	dot = up->env->pgrp->dot;
+	up->env->pgrp->dot = nil;*/
 	pgrp = up->env->pgrp;
 	up->env->pgrp = nil;
-/*	dot = up->dot;
-	up->dot = nil;*/
 	qunlock(&up->debug);
 
 	if(fgrp != nil)
@@ -918,20 +1194,19 @@
 		closefgrp(fgrp);
 	if(egrp != nil)
 		closeegrp(egrp);
-/*	if(rgrp != nil)
+	if(rgrp != nil)
 		closergrp(rgrp);
-	if(dot != nil)
-		cclose(dot);*/
+/*	if(dot != nil)
+		cclose(dot); closepgrp() takes care of this */
 	if(pgrp != nil)
 		closepgrp(pgrp);
-
-/*	if(up->parentpid == 0){
+	if(up->parentpid == 0){
 		if(exitstr == nil)
 			exitstr = "unknown";
 		panic("boot process died: %s", exitstr);
-	}*/
+	}
 
-/*	p = up->parent;
+	p = up->parent;
 	if(p != nil && p->pid == up->parentpid && p->state != Broken){
 		wq = smalloc(sizeof(Waitq));
 		wq->w.pid = up->pid;
@@ -941,25 +1216,25 @@
 		wq->w.time[TSys] = tk2ms(stime);
 		wq->w.time[TReal] = tk2ms(MACHP(0)->ticks - up->time[TReal]);
 		if(exitstr != nil && exitstr[0])
-			snprint(wq->w.msg, sizeof(wq->w.msg), "%s %lud: %s", up->text, up->pid, exitstr);
+			snprint(wq->w.msg, sizeof(wq->w.msg), "%s %ud: %s", up->text, up->pid, exitstr);
 		else
 			wq->w.msg[0] = '\0';
 
 		lock(&p->exl);
-		\/*
+		/*
 		 * Check that parent is still alive.
-		 *\/
+		 */
 		if(p->pid == up->parentpid && p->state != Broken) {
 			p->nchild--;
 			p->time[TCUser] += utime;
 			p->time[TCSys] += stime;
-			\/*
+			/*
 			 * If there would be more than 128 wait records
 			 * processes for my parent, then don't leave a wait
 			 * record behind.  This helps prevent badly written
 			 * daemon processes from accumulating lots of wait
 			 * records.
-		 	 *\/
+		 	 */
 			if(p->nwait < 128) {
 				wq->next = p->waitq;
 				p->waitq = wq;
@@ -975,10 +1250,10 @@
 
 	if(!freemem)
 		addbroken();
-*/
+
 	qlock(&up->debug);
 
-/*	lock(&up->exl);		\/* Prevent my children from leaving waits *\/
+	lock(&up->exl);		/* Prevent my children from leaving waits */
 	pidfree(up);
 	up->parent = nil;
 	up->nchild = up->nwait = 0;
@@ -989,16 +1264,16 @@
 		up->waitq = wq->next;
 		free(wq);
 	}
-*/
+
 	/* release debuggers */
 	if(up->pdbg != nil) {
 		wakeup(&up->pdbg->sleep);
 		up->pdbg = nil;
 	}
-/*	if(up->syscalltrace != nil) {
+	if(up->syscalltrace != nil) {
 		free(up->syscalltrace);
 		up->syscalltrace = nil;
-	}*/
+	}
 	if(up->watchpt != nil){
 		free(up->watchpt);
 		up->watchpt = nil;
@@ -1015,12 +1290,58 @@
 	}
 	qunlock(&up->seglock);*/
 
-/*	edfstop(up); */
+	edfstop(up);
 	up->state = Moribund;
 	sched();
 	panic("pexit");
 }
 
+static int
+haswaitq(void *x)
+{
+	return ((Proc*)x)->waitq != nil;
+}
+
+ulong
+pwait(Waitmsg *w)
+{
+	ulong cpid;
+	Waitq *wq;
+
+	if(!canqlock(&up->qwaitr))
+		error(Einuse);
+
+	if(waserror()) {
+		qunlock(&up->qwaitr);
+		nexterror();
+	}
+
+	lock(&up->exl);
+	while(up->waitq == nil) {
+		if(up->nchild == 0) {
+			unlock(&up->exl);
+			error(Enochild);
+		}
+		unlock(&up->exl);
+		sleep(&up->waitr, haswaitq, up);
+		lock(&up->exl);
+	}
+	wq = up->waitq;
+	up->waitq = wq->next;
+	up->nwait--;
+	unlock(&up->exl);
+
+	qunlock(&up->qwaitr);
+	poperror();
+
+	if(w != nil)
+		memmove(w, &wq->w, sizeof(Waitmsg));
+	cpid = wq->w.pid;
+	free(wq);
+	return cpid;
+}
+
+
 /* macro for speed? */
 Proc*
 proctab(int i)
@@ -1032,19 +1353,23 @@
 void
 dumpaproc(Proc *p)
 {
+	/*ulong bss; 9front shows this */
 	char *s;
-	char tmp[14];
 
+	if(p == nil)
+		return;
+
+	/*bss = 0;
+	if(p->seg[BSEG] != nil)
+		bss = p->seg[BSEG]->top;*/
+
 	s = p->psstate;
 	if(s == nil)
-		s = "kproc";
-	if(p->state == Wakeme)
-		snprint(tmp, sizeof(tmp), " /%.8lux", p->r);
-	else
-		*tmp = '\0';
-	print("%p:%3ud:%14s pc %.8zux %s/%s qpc %.8zux priority %d%s\n",
-		p, p->pid, p->text, p->pc, s, statename[p->state], p->qpc,
-		p->priority, tmp);
+		s = statename[p->state];
+	print("%3ud:%10s pc %#p dbgpc %#p  %8s (%s) ut %d st %d bss %ux qpc %#p nl %d nd %ud lpc %#p pri %ud\n",
+		p->pid, p->text, p->pc, dbgpc(p),  s, statename[p->state],
+		p->time[0], p->time[1], 0/*bss*/, p->qpc, p->nlocks, p->delaysched,
+		p->lastlock ? p->lastlock->pc : 0, p->priority);
 }
 
 void
@@ -1063,6 +1388,7 @@
 	}
 }
 
+/* different from 9front, need to change after dis is removed */
 void
 kproc(char *name, void (*func)(void *), void *arg, int flags)
 {
@@ -1072,19 +1398,11 @@
 	Egrp *eg;
 
 	while((p = newproc()) == nil){
-/* TODO		freebroken(); */
+		freebroken();
 		resrcwait("no procs for kproc");
 	}
 
 	qlock(&p->debug);
-	p->psstate = 0;
-	p->kp = 1;
-
-	p->fpsave = up->fpsave;
-/*	p->scallnr = up->scallnr; */
-	p->nerrlab = 0;
-
-	kstrdup(&p->env->user, up->env->user);
 	if(flags & KPDUPPG) {
 		pg = up->env->pgrp;
 		incref(pg);
@@ -1119,7 +1437,11 @@
 /* this does all of the above 3 lines */
 	kprocchild(p, func, arg);
 
-	strcpy(p->text, name);
+	kstrdup(&p->env->user, up->env->user);
+	kstrdup(&p->text, name);
+	kstrdup(&p->args, "");
+	p->nargs = 0;
+	p->setargs = 0;
 
 /*	if(kpgrp == nil)
 		kpgrp = newpgrp();
@@ -1126,21 +1448,77 @@
 	p->pgrp = kpgrp;
 	incref(kpgrp);*/
 
+	p->kp = 1;
+
 	memset(p->time, 0, sizeof(p->time));
 	p->time[TReal] = MACHP(0)->ticks;
-/*	cycles(&p->kentry);
-	p->pcycles = -p->kentry;*/
+	cycles(&p->kentry);
+	p->pcycles = -p->kentry;
 
+	/* pidalloc(p); is done in newproc() */
+
+	p->fpsave = up->fpsave;
+/*	p->scallnr = up->scallnr; */
+	p->nerrlab = 0;
+
 	qunlock(&p->debug);
 
-	/* leaving the priority at PriNormal */
-/*	procpriority(p, PriKproc, 0);*/
+	procpriority(p, PriKproc, 0);
 
 	p->psstate = nil;
 	ready(p);
 }
 
+/*
+ *  called splhi() by notify().  See comment in notify for the
+ *  reasoning.
+ */
 void
+procctl(void)
+{
+	char *state;
+	ulong s;
+
+	switch(up->procctl) {
+	case Proc_exitbig:
+		spllo();
+		up->fpstate &= ~FPillegal;
+		pprint("Killed: Insufficient physical memory\n");
+		pexit("Killed: Insufficient physical memory", 1);
+
+	case Proc_exitme:
+		spllo();		/* pexit has locks in it */
+		pexit("Killed", 1);
+
+	case Proc_traceme:
+		if(up->nnote == 0)
+			return;
+		/* No break */
+
+	case Proc_stopme:
+		up->procctl = 0;
+		state = up->psstate;
+		up->psstate = "Stopped";
+		/* free a waiting debugger */
+		s = spllo();
+		qlock(&up->debug);
+		if(up->pdbg != nil) {
+			wakeup(&up->pdbg->sleep);
+			up->pdbg = nil;
+		}
+		qunlock(&up->debug);
+		splhi();
+		up->state = Stopped;
+		sched();
+		up->psstate = state;
+		splx(s);
+		return;
+	}
+}
+
+#include "errstr.h"
+
+void
 errorf(char *fmt, ...)
 {
 	va_list arg;
@@ -1174,6 +1552,7 @@
 	if(err == nil)
 		panic("error: nil parameter");
 	kstrcpy(up->env->errstr, err, ERRMAX);
+	setlabel(&up->errlab[NERR-1]);
 	if(emptystr(err) == 1){
 		DBG("error nil error err %s caller 0x%p up->pid %d\n", err, getcallerpc(&err), up->pid);
 		up->env->errpc = 0;
@@ -1197,7 +1576,6 @@
 	gotolabel(&up->errlab[--up->nerrlab]);
 }
 
-#include "errstr.h"
 
 /* Set kernel error string */
 void
@@ -1278,24 +1656,6 @@
 	error(buf);
 }
 
-/*
- *  change ownership to 'new' of all processes owned by 'old'.  Used when
- *  eve changes.
- */
-void
-renameuser(char *old, char *new)
-{
-	Proc *p, *ep;
-	Osenv *o;
-
-	ep = procalloc.arena+conf.nproc;
-	for(p = procalloc.arena; p < ep; p++) {
-		o = &p->defenv;
-		if(o->user != nil && strcmp(o->user, old) == 0)
-			kstrdup(&o->user, new);
-	}
-}
-
 int
 return0(void*)
 {
@@ -1403,6 +1763,84 @@
 }
 
 /*
+ *  change ownership to 'new' of all processes owned by 'old'.  Used when
+ *  eve changes.
+ */
+void
+renameuser(char *old, char *new)
+{
+	Proc *p;
+	int i;
+
+	for(i = 0; i < conf.nproc; i++){
+		p = proctab(i);
+		qlock(&p->debug);
+		if(p->user != nil && strcmp(old, p->user) == 0)
+			kstrdup(&p->user, new);
+		qunlock(&p->debug);
+	}
+}
+
+void
+procsetuser(char *new)
+{
+	qlock(&up->debug);
+	kstrdup(&up->user, new);
+	up->basepri = PriNormal;
+	qunlock(&up->debug);
+}
+
+/*
+ *  time accounting called by clock() splhi'd
+ */
+void
+accounttime(void)
+{
+	Proc *p;
+	ulong n, per;
+	static ulong nrun;
+
+	p = m->proc;
+	if(p != nil) {
+		nrun++;
+		p->time[p->insyscall]++;
+	}
+
+	/* calculate decaying duty cycles */
+	n = perfticks();
+	per = n - m->perf.last;
+	m->perf.last = n;
+	per = ((uvlong)m->perf.period*(HZ-1) + per)/HZ;
+	if(per != 0)
+		m->perf.period = per;
+
+	m->perf.avg_inidle = ((uvlong)m->perf.avg_inidle*(HZ-1)+m->perf.inidle)/HZ;
+	m->perf.inidle = 0;
+
+	m->perf.avg_inintr = ((uvlong)m->perf.avg_inintr*(HZ-1)+m->perf.inintr)/HZ;
+	m->perf.inintr = 0;
+
+	/* only one processor gets to compute system load averages */
+	if(m->machno != 0)
+		return;
+
+	/*
+	 * calculate decaying load average.
+	 * if we decay by (n-1)/n then it takes
+	 * n clock ticks to go from load L to .36 L once
+	 * things quiet down.  it takes about 5 n clock
+	 * ticks to go to zero.  so using HZ means this is
+	 * approximately the load over the last second,
+	 * with a tail lasting about 5 seconds.
+	 */
+	n = nrun;
+	nrun = 0;
+	n = (nrdy+n)*1000*100;
+	pload = ((uvlong)pload*(HZ-1)+n)/HZ;
+	m->load = pload/100;
+}
+
+/*
  *  A Pid structure is a reference counted hashtable entry
  *  with "pid" being the key and "procindex" being the value.
  *  A entry is allocated atomically by changing the key from
@@ -1550,7 +1988,6 @@
 	return p->noteid = i->pid;
 }
 
-/*
 static ulong
 setparentpid(Proc *p, Proc *pp)
 {
@@ -1558,7 +1995,7 @@
 
 	i = pidadd(pp->pid);
 	return p->parentpid = i->pid;
-} */
+}
 
 /*
  *  allocate pid, noteid and parentpid to a process
@@ -1569,8 +2006,8 @@
 	Pid *i;
 
 	/* skip for the boot process */
-/*	if(up != nil)
-		setparentpid(p, up);*/
+	if(up != nil)
+		setparentpid(p, up);
 	i = pidadd(0);
 	i->procindex = (int)(p - procalloc.arena);
 
@@ -1598,10 +2035,8 @@
 		i = pidlookup(p->noteid);
 	piddel(i);
 
-/*	if(p->parentpid != 0)
+	if(p->parentpid != 0)
 		piddel(pidlookup(p->parentpid));
 
 	p->pid = p->noteid = p->parentpid = 0;
-*/
-	p->pid = p->noteid = 0;
 }
--- a/os/port/qlock.c
+++ b/os/port/qlock.c
@@ -13,24 +13,6 @@
 	ulong qlockq;
 } rwstats;
 
-/*
-	*lock()
-		blockinglock = qpc = nil
-	*unlock()
-		blockinglock = qpc = nil
-
-	*lock()
-		blockinglock = qpc = nil
-	placed in the queue
-		blockinglock = lock address
-		qpc = pc that called lock()
-	out of the queue, ready to run
-		blockinglock = nil
-		qpc = pc that called lock()
-	*unlock()
-		blockinglock = qpc = nil
- */
-
 void
 eqlock(QLock *q)
 {
@@ -66,20 +48,17 @@
 	else
 		p->qnext = up;
 	q->tail = up;
-	up->qnext = nil;
-	up->blockinglock = q;
 	up->eql = q;
+	up->qnext = nil;
 	up->qpc = getcallerpc(&q);
 	up->state = Queueing;
 	unlock(&q->use);
 	sched();
-	up->blockinglock = nil;
 	if(up->eql == nil){
 		up->notepending = 0;
 		interrupted();
 	}
 	up->eql = nil;
-	up->qpc = 0;
 }
 
 void
@@ -110,9 +89,7 @@
 		q->head = up;
 	else
 		p->qnext = up;
-	up->qnext = nil;
 	q->tail = up;
-	up->blockinglock = q;
 	up->eql = nil;
 	up->state = Queueing;
 	up->qpc = getcallerpc(&q);
@@ -134,7 +111,6 @@
 	return 1;
 }
 
-/* blockinglock should not be nil */
 void
 qunlock(QLock *q)
 {
@@ -144,11 +120,6 @@
 	if (q->locked == 0)
 		print("qunlock called with qlock not held, from %#p\n",
 			getcallerpc(&q));
-	if (up != nil && up->blockinglock != nil)
-		print("qunlock called with blockinglock %#p, from %#p\n",
-			up->blockinglock, getcallerpc(&q));
-	if (up != nil)
-			up->qpc = 0;
 	p = q->head;
 	if(p != nil) {
 		/* some other process is waiting for this lock */
@@ -155,7 +126,6 @@
 		q->head = p->qnext;
 		if(q->head == nil)
 			q->tail = nil;
-		p->blockinglock = nil;
 		unlock(&q->use);
 		ready(p);
 		return;
@@ -189,8 +159,6 @@
 		p->qnext = up;
 	q->tail = up;
 	up->qnext = nil;
-	up->blockinglock = q;
-	up->eql = nil;
 	up->state = QueueingR;
 	up->qpc = getcallerpc(&q);
 	unlock(&q->use);
@@ -197,22 +165,6 @@
 	sched();
 }
 
-/* same as rlock but punts if there are any writers waiting */
-int
-canrlock(RWlock *q)
-{
-	lock(&q->use);
-	rwstats.rlock++;
-	if(q->writer == 0 && q->head == nil){
-		/* no writer, go for it */
-		q->readers++;
-		unlock(&q->use);
-		return 1;
-	}
-	unlock(&q->use);
-	return 0;
-}
-
 void
 runlock(RWlock *q)
 {
@@ -219,11 +171,6 @@
 	Proc *p;
 
 	lock(&q->use);
-	if (up != nil && up->blockinglock != nil)
-		print("runlock called with blockinglock %#p, from %#p\n",
-			up->blockinglock, getcallerpc(&q));
-	if (up != nil)
-			up->qpc = 0;
 	p = q->head;
 	if(--(q->readers) > 0 || p == nil){
 		unlock(&q->use);
@@ -237,7 +184,6 @@
 	if(q->head == nil)
 		q->tail = nil;
 	q->writer = 1;
-	p->blockinglock = nil;
 	unlock(&q->use);
 	ready(p);
 }
@@ -269,10 +215,7 @@
 		p->qnext = up;
 	q->tail = up;
 	up->qnext = nil;
-	up->blockinglock = q;
-	up->eql = nil;
 	up->state = QueueingW;
-	up->qpc = getcallerpc(&q);
 	unlock(&q->use);
 	sched();
 }
@@ -283,11 +226,6 @@
 	Proc *p;
 
 	lock(&q->use);
-	if (up != nil && up->blockinglock != nil)
-		print("runlock called with blockinglock %#p, from %#p\n",
-			up->blockinglock, getcallerpc(&q));
-	if (up != nil)
-			up->qpc = 0;
 	p = q->head;
 	if(p == nil){
 		q->writer = 0;
@@ -299,7 +237,6 @@
 		q->head = p->qnext;
 		if(q->head == nil)
 			q->tail = nil;
-		p->blockinglock = nil;
 		unlock(&q->use);
 		ready(p);
 		return;
@@ -313,7 +250,6 @@
 		p = q->head;
 		q->head = p->qnext;
 		q->readers++;
-		p->blockinglock = nil;
 		ready(p);
 	}
 	if(q->head == nil)
@@ -320,4 +256,21 @@
 		q->tail = nil;
 	q->writer = 0;
 	unlock(&q->use);
+}
+
+
+/* same as rlock but punts if there are any writers waiting */
+int
+canrlock(RWlock *q)
+{
+	lock(&q->use);
+	rwstats.rlock++;
+	if(q->writer == 0 && q->head == nil){
+		/* no writer, go for it */
+		q->readers++;
+		unlock(&q->use);
+		return 1;
+	}
+	unlock(&q->use);
+	return 0;
 }