xref: /plan9/sys/src/9/port/proc.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include	"u.h"
23e12c5d1SDavid du Colombier #include	"../port/lib.h"
33e12c5d1SDavid du Colombier #include	"mem.h"
43e12c5d1SDavid du Colombier #include	"dat.h"
53e12c5d1SDavid du Colombier #include	"fns.h"
63e12c5d1SDavid du Colombier #include	"../port/error.h"
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier Ref	pidalloc;
93e12c5d1SDavid du Colombier Ref	noteidalloc;
103e12c5d1SDavid du Colombier 
113e12c5d1SDavid du Colombier struct
123e12c5d1SDavid du Colombier {
133e12c5d1SDavid du Colombier 	Lock;
143e12c5d1SDavid du Colombier 	Proc	*arena;
153e12c5d1SDavid du Colombier 	Proc	*free;
163e12c5d1SDavid du Colombier }procalloc;
173e12c5d1SDavid du Colombier 
183e12c5d1SDavid du Colombier struct
193e12c5d1SDavid du Colombier {
203e12c5d1SDavid du Colombier 	Lock;
213e12c5d1SDavid du Colombier 	Waitq	*free;
223e12c5d1SDavid du Colombier }waitqalloc;
233e12c5d1SDavid du Colombier 
243e12c5d1SDavid du Colombier typedef struct
253e12c5d1SDavid du Colombier {
263e12c5d1SDavid du Colombier 	Lock;
273e12c5d1SDavid du Colombier 	Proc	*head;
283e12c5d1SDavid du Colombier 	Proc	*tail;
29*219b2ee8SDavid du Colombier 	int	n;
303e12c5d1SDavid du Colombier } Schedq;
313e12c5d1SDavid du Colombier 
323e12c5d1SDavid du Colombier int	nrdy;
33*219b2ee8SDavid du Colombier int	lastreadied;
34*219b2ee8SDavid du Colombier Schedq	runq[Nrq];
353e12c5d1SDavid du Colombier 
363e12c5d1SDavid du Colombier char *statename[] =
373e12c5d1SDavid du Colombier {			/* BUG: generate automatically */
383e12c5d1SDavid du Colombier 	"Dead",
393e12c5d1SDavid du Colombier 	"Moribund",
403e12c5d1SDavid du Colombier 	"Ready",
413e12c5d1SDavid du Colombier 	"Scheding",
423e12c5d1SDavid du Colombier 	"Running",
433e12c5d1SDavid du Colombier 	"Queueing",
443e12c5d1SDavid du Colombier 	"Wakeme",
453e12c5d1SDavid du Colombier 	"Broken",
463e12c5d1SDavid du Colombier 	"Stopped",
473e12c5d1SDavid du Colombier 	"Rendez",
483e12c5d1SDavid du Colombier };
493e12c5d1SDavid du Colombier 
503e12c5d1SDavid du Colombier /*
513e12c5d1SDavid du Colombier  * Always splhi()'ed.
523e12c5d1SDavid du Colombier  */
533e12c5d1SDavid du Colombier void
543e12c5d1SDavid du Colombier schedinit(void)		/* never returns */
553e12c5d1SDavid du Colombier {
563e12c5d1SDavid du Colombier 	Proc *p;
573e12c5d1SDavid du Colombier 
583e12c5d1SDavid du Colombier 	setlabel(&m->sched);
593e12c5d1SDavid du Colombier 	if(u){
603e12c5d1SDavid du Colombier 		m->proc = 0;
613e12c5d1SDavid du Colombier 		p = u->p;
623e12c5d1SDavid du Colombier 		invalidateu();	/* safety first */
633e12c5d1SDavid du Colombier 		u = 0;
643e12c5d1SDavid du Colombier 		if(p->state == Running)
653e12c5d1SDavid du Colombier 			ready(p);
663e12c5d1SDavid du Colombier 		else
673e12c5d1SDavid du Colombier 		if(p->state == Moribund) {
683e12c5d1SDavid du Colombier 			p->pid = 0;
693e12c5d1SDavid du Colombier 			p->state = Dead;
703e12c5d1SDavid du Colombier 			/*
713e12c5d1SDavid du Colombier 			 * Holding locks from pexit:
72*219b2ee8SDavid du Colombier 			 * 	procalloc, palloc
733e12c5d1SDavid du Colombier 			 */
743e12c5d1SDavid du Colombier 			mmurelease(p);
753e12c5d1SDavid du Colombier 			simpleputpage(p->upage);
763e12c5d1SDavid du Colombier 			p->upage = 0;
773e12c5d1SDavid du Colombier 
783e12c5d1SDavid du Colombier 			p->qnext = procalloc.free;
793e12c5d1SDavid du Colombier 			procalloc.free = p;
803e12c5d1SDavid du Colombier 
813e12c5d1SDavid du Colombier 			unlock(&palloc);
823e12c5d1SDavid du Colombier 			unlock(&procalloc);
833e12c5d1SDavid du Colombier 		}
843e12c5d1SDavid du Colombier 		p->mach = 0;
853e12c5d1SDavid du Colombier 	}
863e12c5d1SDavid du Colombier 	sched();
873e12c5d1SDavid du Colombier }
883e12c5d1SDavid du Colombier 
893e12c5d1SDavid du Colombier void
903e12c5d1SDavid du Colombier sched(void)
913e12c5d1SDavid du Colombier {
923e12c5d1SDavid du Colombier 	Proc *p;
933e12c5d1SDavid du Colombier 
943e12c5d1SDavid du Colombier 	if(u){
953e12c5d1SDavid du Colombier 		splhi();
963e12c5d1SDavid du Colombier 		m->cs++;
973e12c5d1SDavid du Colombier 		procsave(u->p);
983e12c5d1SDavid du Colombier 		if(setlabel(&u->p->sched)){	/* woke up */
993e12c5d1SDavid du Colombier 			p = u->p;
1003e12c5d1SDavid du Colombier 			p->state = Running;
1013e12c5d1SDavid du Colombier 			p->mach = m;
1023e12c5d1SDavid du Colombier 			m->proc = p;
1033e12c5d1SDavid du Colombier 			procrestore(p);
1043e12c5d1SDavid du Colombier 			spllo();
1053e12c5d1SDavid du Colombier 			return;
1063e12c5d1SDavid du Colombier 		}
1073e12c5d1SDavid du Colombier 		gotolabel(&m->sched);
1083e12c5d1SDavid du Colombier 	}
1093e12c5d1SDavid du Colombier 	p = runproc();
1103e12c5d1SDavid du Colombier 	mapstack(p);
1113e12c5d1SDavid du Colombier 	gotolabel(&p->sched);
1123e12c5d1SDavid du Colombier }
1133e12c5d1SDavid du Colombier 
114*219b2ee8SDavid du Colombier /*
115*219b2ee8SDavid du Colombier  *  this should be called in clock() to implement round robin
116*219b2ee8SDavid du Colombier  */
1173e12c5d1SDavid du Colombier int
1183e12c5d1SDavid du Colombier anyready(void)
1193e12c5d1SDavid du Colombier {
120*219b2ee8SDavid du Colombier 	return nrdy;
1213e12c5d1SDavid du Colombier }
1223e12c5d1SDavid du Colombier 
123*219b2ee8SDavid du Colombier /*
124*219b2ee8SDavid du Colombier  *  this should be called in non-clock traps to implement preemptive scheduling
125*219b2ee8SDavid du Colombier  */
126*219b2ee8SDavid du Colombier int
127*219b2ee8SDavid du Colombier anyhigher(void)
128*219b2ee8SDavid du Colombier {
129*219b2ee8SDavid du Colombier 	int x;
130*219b2ee8SDavid du Colombier 
131*219b2ee8SDavid du Colombier 	x = lastreadied;
132*219b2ee8SDavid du Colombier 	lastreadied = 0;
133*219b2ee8SDavid du Colombier 	return nrdy && x >= u->p->priority;
134*219b2ee8SDavid du Colombier }
135*219b2ee8SDavid du Colombier 
136*219b2ee8SDavid du Colombier enum
137*219b2ee8SDavid du Colombier {
138*219b2ee8SDavid du Colombier 	Squantum = (HZ+Nrq-1)/Nrq,
139*219b2ee8SDavid du Colombier };
140*219b2ee8SDavid du Colombier 
1413e12c5d1SDavid du Colombier void
1423e12c5d1SDavid du Colombier ready(Proc *p)
1433e12c5d1SDavid du Colombier {
144*219b2ee8SDavid du Colombier 	int s, pri;
1453e12c5d1SDavid du Colombier 	Schedq *rq;
1463e12c5d1SDavid du Colombier 
1473e12c5d1SDavid du Colombier 	s = splhi();
1483e12c5d1SDavid du Colombier 
149*219b2ee8SDavid du Colombier 	/* history counts */
150*219b2ee8SDavid du Colombier 	if(p->state == Running){
151*219b2ee8SDavid du Colombier 		p->rt++;
152*219b2ee8SDavid du Colombier 		pri = ((p->art + (p->rt<<1))>>2)/Squantum;
153*219b2ee8SDavid du Colombier 	} else {
154*219b2ee8SDavid du Colombier 		p->art = (p->art + (p->rt<<1))>>2;
155*219b2ee8SDavid du Colombier 		p->rt = 0;
156*219b2ee8SDavid du Colombier 		pri = p->art/Squantum;
157*219b2ee8SDavid du Colombier 	}
158*219b2ee8SDavid du Colombier 	pri = p->basepri - pri;
159*219b2ee8SDavid du Colombier 	if(pri < 0)
160*219b2ee8SDavid du Colombier 		pri = 0;
1613e12c5d1SDavid du Colombier 
162*219b2ee8SDavid du Colombier 	/* the only intersection between the classes is at PriNormal */
163*219b2ee8SDavid du Colombier 	if(pri < PriNormal && p->basepri > PriNormal)
164*219b2ee8SDavid du Colombier 		pri = PriNormal;
165*219b2ee8SDavid du Colombier 	p->priority = pri;
166*219b2ee8SDavid du Colombier 	rq = &runq[p->priority];
167*219b2ee8SDavid du Colombier 
168*219b2ee8SDavid du Colombier 	lock(runq);
1693e12c5d1SDavid du Colombier 	p->rnext = 0;
1703e12c5d1SDavid du Colombier 	if(rq->tail)
1713e12c5d1SDavid du Colombier 		rq->tail->rnext = p;
1723e12c5d1SDavid du Colombier 	else
1733e12c5d1SDavid du Colombier 		rq->head = p;
1743e12c5d1SDavid du Colombier 	rq->tail = p;
175*219b2ee8SDavid du Colombier 	rq->n++;
1763e12c5d1SDavid du Colombier 	nrdy++;
177*219b2ee8SDavid du Colombier 	p->readytime = m->ticks;
1783e12c5d1SDavid du Colombier 	p->state = Ready;
179*219b2ee8SDavid du Colombier 	if(p->priority > lastreadied)
180*219b2ee8SDavid du Colombier 		lastreadied = p->priority;
181*219b2ee8SDavid du Colombier 	unlock(runq);
1823e12c5d1SDavid du Colombier 	splx(s);
1833e12c5d1SDavid du Colombier }
1843e12c5d1SDavid du Colombier 
1853e12c5d1SDavid du Colombier /*
1863e12c5d1SDavid du Colombier  * Always called splhi
1873e12c5d1SDavid du Colombier  */
188*219b2ee8SDavid du Colombier #include "io.h"
1893e12c5d1SDavid du Colombier Proc*
1903e12c5d1SDavid du Colombier runproc(void)
1913e12c5d1SDavid du Colombier {
192*219b2ee8SDavid du Colombier 	int i;
1933e12c5d1SDavid du Colombier 	Schedq *rq;
194*219b2ee8SDavid du Colombier 	Proc *p, *l;
195*219b2ee8SDavid du Colombier 	static ulong lastfair;
1963e12c5d1SDavid du Colombier 
1973e12c5d1SDavid du Colombier loop:
198*219b2ee8SDavid du Colombier 
199*219b2ee8SDavid du Colombier 	/*
200*219b2ee8SDavid du Colombier 	 *  find a process that last ran on this processor (affinity),
201*219b2ee8SDavid du Colombier 	 *  or one that hasn't moved in a while (load balancing).
202*219b2ee8SDavid du Colombier 	 */
2033e12c5d1SDavid du Colombier 	spllo();
204*219b2ee8SDavid du Colombier 	for(;;){
205*219b2ee8SDavid du Colombier 		/*
206*219b2ee8SDavid du Colombier 		 *  Once a second we look for a long waiting process
207*219b2ee8SDavid du Colombier 		 *  in the lowest priority queue to make sure nothing
208*219b2ee8SDavid du Colombier 		 *  gets starved out by a malfunctioning high priority
209*219b2ee8SDavid du Colombier 		 *  process.
210*219b2ee8SDavid du Colombier 		 */
211*219b2ee8SDavid du Colombier 		if(m->machno == 0 && m->ticks - lastfair > HZ){
212*219b2ee8SDavid du Colombier 			lastfair = m->ticks;
213*219b2ee8SDavid du Colombier 			for(rq = runq; rq < &runq[Nrq]; rq++){
2143e12c5d1SDavid du Colombier 				p = rq->head;
215*219b2ee8SDavid du Colombier 				if(p){
216*219b2ee8SDavid du Colombier 					i = m->ticks - p->readytime;
217*219b2ee8SDavid du Colombier 					if(i > HZ){
218*219b2ee8SDavid du Colombier 						p->art = 0;
219*219b2ee8SDavid du Colombier 						p->movetime = 0;
220*219b2ee8SDavid du Colombier 						goto found;
221*219b2ee8SDavid du Colombier 					}
222*219b2ee8SDavid du Colombier 					break;
223*219b2ee8SDavid du Colombier 				}
224*219b2ee8SDavid du Colombier 			}
225*219b2ee8SDavid du Colombier 		}
226*219b2ee8SDavid du Colombier 
227*219b2ee8SDavid du Colombier 		/*
228*219b2ee8SDavid du Colombier 		 *  get highest priority process that this
229*219b2ee8SDavid du Colombier 		 *  processor can run given affinity constraints
230*219b2ee8SDavid du Colombier 		 */
231*219b2ee8SDavid du Colombier 		for(rq = &runq[Nrq-1]; rq >= runq; rq--){
232*219b2ee8SDavid du Colombier 			if(rq->head == 0)
233*219b2ee8SDavid du Colombier 				continue;
234*219b2ee8SDavid du Colombier 			for(p = rq->head; p; p = p->rnext){
235*219b2ee8SDavid du Colombier 				if(p->mp == m || m->ticks - p->movetime > HZ/2)
236*219b2ee8SDavid du Colombier 					goto found;
237*219b2ee8SDavid du Colombier 			}
238*219b2ee8SDavid du Colombier 		}
239*219b2ee8SDavid du Colombier 	}
240*219b2ee8SDavid du Colombier 
241*219b2ee8SDavid du Colombier 
242*219b2ee8SDavid du Colombier found:
243*219b2ee8SDavid du Colombier 	splhi();
244*219b2ee8SDavid du Colombier 	lock(runq);
245*219b2ee8SDavid du Colombier 
246*219b2ee8SDavid du Colombier 	l = 0;
247*219b2ee8SDavid du Colombier 	for(p = rq->head; p; p = p->rnext){
248*219b2ee8SDavid du Colombier 		if(p->mp == m || m->ticks - p->movetime > HZ/2)
249*219b2ee8SDavid du Colombier 			break;
250*219b2ee8SDavid du Colombier 		l = p;
251*219b2ee8SDavid du Colombier 	}
252*219b2ee8SDavid du Colombier 
253*219b2ee8SDavid du Colombier 	/*
254*219b2ee8SDavid du Colombier 	 *  p->mach==0 only when process state is saved
255*219b2ee8SDavid du Colombier 	 */
256*219b2ee8SDavid du Colombier 	if(p == 0 || p->mach){
257*219b2ee8SDavid du Colombier 		unlock(runq);
2583e12c5d1SDavid du Colombier 		goto loop;
2593e12c5d1SDavid du Colombier 	}
2603e12c5d1SDavid du Colombier 	if(p->rnext == 0)
261*219b2ee8SDavid du Colombier 		rq->tail = l;
262*219b2ee8SDavid du Colombier 	if(l)
263*219b2ee8SDavid du Colombier 		l->rnext = p->rnext;
264*219b2ee8SDavid du Colombier 	else
2653e12c5d1SDavid du Colombier 		rq->head = p->rnext;
266*219b2ee8SDavid du Colombier 	rq->n--;
2673e12c5d1SDavid du Colombier 	nrdy--;
2683e12c5d1SDavid du Colombier 	if(p->state != Ready)
2693e12c5d1SDavid du Colombier 		print("runproc %s %d %s\n", p->text, p->pid, statename[p->state]);
270*219b2ee8SDavid du Colombier 	unlock(runq);
271*219b2ee8SDavid du Colombier 
2723e12c5d1SDavid du Colombier 	p->state = Scheding;
273*219b2ee8SDavid du Colombier 	if(p->mp != m)
274*219b2ee8SDavid du Colombier 		p->movetime = m->ticks;
275*219b2ee8SDavid du Colombier 	p->mp = m;
2763e12c5d1SDavid du Colombier 	return p;
2773e12c5d1SDavid du Colombier }
2783e12c5d1SDavid du Colombier 
2793e12c5d1SDavid du Colombier int
2803e12c5d1SDavid du Colombier canpage(Proc *p)
2813e12c5d1SDavid du Colombier {
2823e12c5d1SDavid du Colombier 	int ok = 0;
2833e12c5d1SDavid du Colombier 
2843e12c5d1SDavid du Colombier 	splhi();
285*219b2ee8SDavid du Colombier 	lock(&runq[0]);
2863e12c5d1SDavid du Colombier 	/* Only reliable way to see if we are Running */
2873e12c5d1SDavid du Colombier 	if(p->mach == 0) {
2883e12c5d1SDavid du Colombier 		p->newtlb = 1;
2893e12c5d1SDavid du Colombier 		ok = 1;
2903e12c5d1SDavid du Colombier 	}
291*219b2ee8SDavid du Colombier 	unlock(&runq[0]);
2923e12c5d1SDavid du Colombier 	spllo();
2933e12c5d1SDavid du Colombier 
2943e12c5d1SDavid du Colombier 	return ok;
2953e12c5d1SDavid du Colombier }
2963e12c5d1SDavid du Colombier 
2973e12c5d1SDavid du Colombier Proc*
2983e12c5d1SDavid du Colombier newproc(void)
2993e12c5d1SDavid du Colombier {
3003e12c5d1SDavid du Colombier 	Proc *p;
3013e12c5d1SDavid du Colombier 
3023e12c5d1SDavid du Colombier 	for(;;) {
3033e12c5d1SDavid du Colombier 		lock(&procalloc);
3043e12c5d1SDavid du Colombier 		if(p = procalloc.free){		/* assign = */
3053e12c5d1SDavid du Colombier 			procalloc.free = p->qnext;
3063e12c5d1SDavid du Colombier 			p->state = Scheding;
3073e12c5d1SDavid du Colombier 			p->psstate = "New";
3083e12c5d1SDavid du Colombier 			unlock(&procalloc);
3093e12c5d1SDavid du Colombier 			p->mach = 0;
3103e12c5d1SDavid du Colombier 			p->qnext = 0;
3113e12c5d1SDavid du Colombier 			p->nchild = 0;
3123e12c5d1SDavid du Colombier 			p->nwait = 0;
3133e12c5d1SDavid du Colombier 			p->waitq = 0;
3143e12c5d1SDavid du Colombier 			p->pgrp = 0;
3153e12c5d1SDavid du Colombier 			p->egrp = 0;
3163e12c5d1SDavid du Colombier 			p->fgrp = 0;
3173e12c5d1SDavid du Colombier 			p->pdbg = 0;
3183e12c5d1SDavid du Colombier 			p->fpstate = FPinit;
3193e12c5d1SDavid du Colombier 			p->kp = 0;
3203e12c5d1SDavid du Colombier 			p->procctl = 0;
3213e12c5d1SDavid du Colombier 			p->notepending = 0;
322*219b2ee8SDavid du Colombier 			p->mp = 0;
323*219b2ee8SDavid du Colombier 			p->movetime = 0;
3243e12c5d1SDavid du Colombier 			memset(p->seg, 0, sizeof p->seg);
3253e12c5d1SDavid du Colombier 			p->pid = incref(&pidalloc);
3263e12c5d1SDavid du Colombier 			p->noteid = incref(&noteidalloc);
3273e12c5d1SDavid du Colombier 			if(p->pid==0 || p->noteid==0)
3283e12c5d1SDavid du Colombier 				panic("pidalloc");
3293e12c5d1SDavid du Colombier 			return p;
3303e12c5d1SDavid du Colombier 		}
3313e12c5d1SDavid du Colombier 		unlock(&procalloc);
3323e12c5d1SDavid du Colombier 		resrcwait("no procs");
3333e12c5d1SDavid du Colombier 	}
3343e12c5d1SDavid du Colombier 	return 0;		/* not reached */
3353e12c5d1SDavid du Colombier }
3363e12c5d1SDavid du Colombier 
3373e12c5d1SDavid du Colombier void
3383e12c5d1SDavid du Colombier procinit0(void)		/* bad planning - clashes with devproc.c */
3393e12c5d1SDavid du Colombier {
3403e12c5d1SDavid du Colombier 	Proc *p;
3413e12c5d1SDavid du Colombier 	int i;
3423e12c5d1SDavid du Colombier 
3433e12c5d1SDavid du Colombier 	procalloc.free = xalloc(conf.nproc*sizeof(Proc));
3443e12c5d1SDavid du Colombier 	procalloc.arena = procalloc.free;
3453e12c5d1SDavid du Colombier 
3463e12c5d1SDavid du Colombier 	p = procalloc.free;
3473e12c5d1SDavid du Colombier 	for(i=0; i<conf.nproc-1; i++,p++)
3483e12c5d1SDavid du Colombier 		p->qnext = p+1;
3493e12c5d1SDavid du Colombier 	p->qnext = 0;
3503e12c5d1SDavid du Colombier }
3513e12c5d1SDavid du Colombier 
3523e12c5d1SDavid du Colombier void
3533e12c5d1SDavid du Colombier sleep1(Rendez *r, int (*f)(void*), void *arg)
3543e12c5d1SDavid du Colombier {
3553e12c5d1SDavid du Colombier 	Proc *p;
3563e12c5d1SDavid du Colombier 	int s;
3573e12c5d1SDavid du Colombier 
3583e12c5d1SDavid du Colombier 	/*
3593e12c5d1SDavid du Colombier 	 * spl is to allow lock to be called
3603e12c5d1SDavid du Colombier 	 * at interrupt time. lock is mutual exclusion
3613e12c5d1SDavid du Colombier 	 */
3623e12c5d1SDavid du Colombier 	s = splhi();
3633e12c5d1SDavid du Colombier 	p = u->p;
3643e12c5d1SDavid du Colombier 	p->r = r;	/* early so postnote knows */
3653e12c5d1SDavid du Colombier 	lock(r);
3663e12c5d1SDavid du Colombier 
3673e12c5d1SDavid du Colombier 	/*
3683e12c5d1SDavid du Colombier 	 * if condition happened, never mind
3693e12c5d1SDavid du Colombier 	 */
3703e12c5d1SDavid du Colombier 	if((*f)(arg)){
3713e12c5d1SDavid du Colombier 		p->r = 0;
3723e12c5d1SDavid du Colombier 		unlock(r);
3733e12c5d1SDavid du Colombier 		splx(s);
3743e12c5d1SDavid du Colombier 		return;
3753e12c5d1SDavid du Colombier 	}
3763e12c5d1SDavid du Colombier 
3773e12c5d1SDavid du Colombier 	/*
3783e12c5d1SDavid du Colombier 	 * now we are committed to
3793e12c5d1SDavid du Colombier 	 * change state and call scheduler
3803e12c5d1SDavid du Colombier 	 */
3813e12c5d1SDavid du Colombier 	if(r->p){
3823e12c5d1SDavid du Colombier 		print("double sleep %d %d\n", r->p->pid, p->pid);
3833e12c5d1SDavid du Colombier 		dumpstack();
3843e12c5d1SDavid du Colombier 	}
3853e12c5d1SDavid du Colombier 	p->state = Wakeme;
3863e12c5d1SDavid du Colombier 	r->p = p;
3873e12c5d1SDavid du Colombier 	unlock(r);
3883e12c5d1SDavid du Colombier }
3893e12c5d1SDavid du Colombier 
3903e12c5d1SDavid du Colombier void
3913e12c5d1SDavid du Colombier sleep(Rendez *r, int (*f)(void*), void *arg)
3923e12c5d1SDavid du Colombier {
3933e12c5d1SDavid du Colombier 	Proc *p;
3943e12c5d1SDavid du Colombier 	int s;
3953e12c5d1SDavid du Colombier 
3963e12c5d1SDavid du Colombier 	p = u->p;
3973e12c5d1SDavid du Colombier 	sleep1(r, f, arg);
3983e12c5d1SDavid du Colombier 	if(p->notepending == 0)
3993e12c5d1SDavid du Colombier 		sched();	/* notepending may go true while asleep */
4003e12c5d1SDavid du Colombier 	if(p->notepending){
4013e12c5d1SDavid du Colombier 		p->notepending = 0;
4023e12c5d1SDavid du Colombier 		s = splhi();
4033e12c5d1SDavid du Colombier 		lock(r);
4043e12c5d1SDavid du Colombier 		if(r->p == p)
4053e12c5d1SDavid du Colombier 			r->p = 0;
4063e12c5d1SDavid du Colombier 		unlock(r);
4073e12c5d1SDavid du Colombier 		splx(s);
4083e12c5d1SDavid du Colombier 		error(Eintr);
4093e12c5d1SDavid du Colombier 	}
4103e12c5d1SDavid du Colombier }
4113e12c5d1SDavid du Colombier 
4123e12c5d1SDavid du Colombier int
4133e12c5d1SDavid du Colombier tfn(void *arg)
4143e12c5d1SDavid du Colombier {
4153e12c5d1SDavid du Colombier 	Proc *p;
4163e12c5d1SDavid du Colombier 
4173e12c5d1SDavid du Colombier 	p = u->p;
4183e12c5d1SDavid du Colombier 	return MACHP(0)->ticks >= p->twhen || (*p->tfn)(arg);
4193e12c5d1SDavid du Colombier }
4203e12c5d1SDavid du Colombier 
4213e12c5d1SDavid du Colombier void
4223e12c5d1SDavid du Colombier tsleep(Rendez *r, int (*fn)(void*), void *arg, int ms)
4233e12c5d1SDavid du Colombier {
4243e12c5d1SDavid du Colombier 	ulong when;
4253e12c5d1SDavid du Colombier 	Proc *p, *f, **l;
4263e12c5d1SDavid du Colombier 
4273e12c5d1SDavid du Colombier 	p = u->p;
4283e12c5d1SDavid du Colombier 	when = MS2TK(ms)+MACHP(0)->ticks;
4293e12c5d1SDavid du Colombier 
4303e12c5d1SDavid du Colombier 	lock(&talarm);
4313e12c5d1SDavid du Colombier 	/* take out of list if checkalarm didn't */
4323e12c5d1SDavid du Colombier 	if(p->trend) {
4333e12c5d1SDavid du Colombier 		l = &talarm.list;
4343e12c5d1SDavid du Colombier 		for(f = *l; f; f = f->tlink) {
4353e12c5d1SDavid du Colombier 			if(f == p) {
4363e12c5d1SDavid du Colombier 				*l = p->tlink;
4373e12c5d1SDavid du Colombier 				break;
4383e12c5d1SDavid du Colombier 			}
4393e12c5d1SDavid du Colombier 			l = &f->tlink;
4403e12c5d1SDavid du Colombier 		}
4413e12c5d1SDavid du Colombier 	}
4423e12c5d1SDavid du Colombier 	/* insert in increasing time order */
4433e12c5d1SDavid du Colombier 	l = &talarm.list;
4443e12c5d1SDavid du Colombier 	for(f = *l; f; f = f->tlink) {
4453e12c5d1SDavid du Colombier 		if(f->twhen >= when)
4463e12c5d1SDavid du Colombier 			break;
4473e12c5d1SDavid du Colombier 		l = &f->tlink;
4483e12c5d1SDavid du Colombier 	}
4493e12c5d1SDavid du Colombier 	p->trend = r;
4503e12c5d1SDavid du Colombier 	p->twhen = when;
4513e12c5d1SDavid du Colombier 	p->tfn = fn;
4523e12c5d1SDavid du Colombier 	p->tlink = *l;
4533e12c5d1SDavid du Colombier 	*l = p;
4543e12c5d1SDavid du Colombier 	unlock(&talarm);
4553e12c5d1SDavid du Colombier 
4563e12c5d1SDavid du Colombier 	sleep(r, tfn, arg);
4573e12c5d1SDavid du Colombier 	p->twhen = 0;
4583e12c5d1SDavid du Colombier }
4593e12c5d1SDavid du Colombier 
4603e12c5d1SDavid du Colombier /*
4613e12c5d1SDavid du Colombier  * Expects that only one process can call wakeup for any given Rendez
4623e12c5d1SDavid du Colombier  */
4633e12c5d1SDavid du Colombier void
4643e12c5d1SDavid du Colombier wakeup(Rendez *r)
4653e12c5d1SDavid du Colombier {
4663e12c5d1SDavid du Colombier 	Proc *p;
4673e12c5d1SDavid du Colombier 	int s;
4683e12c5d1SDavid du Colombier 
4693e12c5d1SDavid du Colombier 	s = splhi();
4703e12c5d1SDavid du Colombier 	lock(r);
4713e12c5d1SDavid du Colombier 	p = r->p;
4723e12c5d1SDavid du Colombier 	if(p){
4733e12c5d1SDavid du Colombier 		r->p = 0;
4743e12c5d1SDavid du Colombier 		if(p->state != Wakeme)
4753e12c5d1SDavid du Colombier 			panic("wakeup: state");
4763e12c5d1SDavid du Colombier 		p->r = 0;
4773e12c5d1SDavid du Colombier 		ready(p);
4783e12c5d1SDavid du Colombier 	}
4793e12c5d1SDavid du Colombier 	unlock(r);
4803e12c5d1SDavid du Colombier 	splx(s);
4813e12c5d1SDavid du Colombier }
4823e12c5d1SDavid du Colombier 
4833e12c5d1SDavid du Colombier int
4843e12c5d1SDavid du Colombier postnote(Proc *p, int dolock, char *n, int flag)
4853e12c5d1SDavid du Colombier {
4863e12c5d1SDavid du Colombier 	User *up;
4873e12c5d1SDavid du Colombier 	KMap *k;
4883e12c5d1SDavid du Colombier 	int s, ret;
4893e12c5d1SDavid du Colombier 	Rendez *r;
4903e12c5d1SDavid du Colombier 	Proc *d, **l;
4913e12c5d1SDavid du Colombier 
4923e12c5d1SDavid du Colombier 	if(dolock)
4933e12c5d1SDavid du Colombier 		qlock(&p->debug);
4943e12c5d1SDavid du Colombier 
495*219b2ee8SDavid du Colombier 	if(p->kp)
496*219b2ee8SDavid du Colombier 		print("sending %s to kproc %d %s\n", n, p->pid, p->text);
497*219b2ee8SDavid du Colombier 
4983e12c5d1SDavid du Colombier 	if(p->upage == 0){
4993e12c5d1SDavid du Colombier 		if(dolock)
5003e12c5d1SDavid du Colombier 			qunlock(&p->debug);
5013e12c5d1SDavid du Colombier 		return 0;
5023e12c5d1SDavid du Colombier 	}
5033e12c5d1SDavid du Colombier 
5043e12c5d1SDavid du Colombier 	SET(k);
5053e12c5d1SDavid du Colombier 	if(u == 0 || p != u->p){
5063e12c5d1SDavid du Colombier 		k = kmap(p->upage);
5073e12c5d1SDavid du Colombier 		up = (User*)VA(k);
5083e12c5d1SDavid du Colombier 	}else
5093e12c5d1SDavid du Colombier 		up = u;
5103e12c5d1SDavid du Colombier 	USED(k);
5113e12c5d1SDavid du Colombier 
5123e12c5d1SDavid du Colombier 	if(flag!=NUser && (up->notify==0 || up->notified))
5133e12c5d1SDavid du Colombier 		up->nnote = 0;	/* force user's hand */
5143e12c5d1SDavid du Colombier 
5153e12c5d1SDavid du Colombier 	ret = 0;
5163e12c5d1SDavid du Colombier 	if(up->nnote < NNOTE){
5173e12c5d1SDavid du Colombier 		strcpy(up->note[up->nnote].msg, n);
5183e12c5d1SDavid du Colombier 		up->note[up->nnote++].flag = flag;
5193e12c5d1SDavid du Colombier 		ret = 1;
5203e12c5d1SDavid du Colombier 	}
5213e12c5d1SDavid du Colombier 	p->notepending = 1;
5223e12c5d1SDavid du Colombier 	if(up != u)
5233e12c5d1SDavid du Colombier 		kunmap(k);
5243e12c5d1SDavid du Colombier 	if(dolock)
5253e12c5d1SDavid du Colombier 		qunlock(&p->debug);
5263e12c5d1SDavid du Colombier 
5273e12c5d1SDavid du Colombier 	if(r = p->r){		/* assign = */
5283e12c5d1SDavid du Colombier 		/* wake up; can't call wakeup itself because we're racing with it */
5293e12c5d1SDavid du Colombier 		for(;;) {
5303e12c5d1SDavid du Colombier 			s = splhi();
5313e12c5d1SDavid du Colombier 			if(canlock(r))
5323e12c5d1SDavid du Colombier 				break;
5333e12c5d1SDavid du Colombier 			splx(s);
5343e12c5d1SDavid du Colombier 		}
5353e12c5d1SDavid du Colombier 		if(p->r==r && r->p==p && p->state==Wakeme){	/* check we won the race */
5363e12c5d1SDavid du Colombier 			r->p = 0;
5373e12c5d1SDavid du Colombier 			p->r = 0;
5383e12c5d1SDavid du Colombier 			ready(p);
5393e12c5d1SDavid du Colombier 		}
5403e12c5d1SDavid du Colombier 		unlock(r);
5413e12c5d1SDavid du Colombier 		splx(s);
5423e12c5d1SDavid du Colombier 	}
5433e12c5d1SDavid du Colombier 
544bd389b36SDavid du Colombier 	if(p->state != Rendezvous)
545bd389b36SDavid du Colombier 		return ret;
546bd389b36SDavid du Colombier 
547bd389b36SDavid du Colombier 	/* Try and pull out of a rendezvous */
5483e12c5d1SDavid du Colombier 	lock(p->pgrp);
5493e12c5d1SDavid du Colombier 	if(p->state == Rendezvous) {
5503e12c5d1SDavid du Colombier 		p->rendval = ~0;
5513e12c5d1SDavid du Colombier 		l = &REND(p->pgrp, p->rendtag);
5523e12c5d1SDavid du Colombier 		for(d = *l; d; d = d->rendhash) {
5533e12c5d1SDavid du Colombier 			if(d == p) {
5543e12c5d1SDavid du Colombier 				*l = p->rendhash;
555*219b2ee8SDavid du Colombier 				ready(p);
5563e12c5d1SDavid du Colombier 				break;
5573e12c5d1SDavid du Colombier 			}
5583e12c5d1SDavid du Colombier 			l = &d->rendhash;
5593e12c5d1SDavid du Colombier 		}
5603e12c5d1SDavid du Colombier 	}
5613e12c5d1SDavid du Colombier 	unlock(p->pgrp);
5623e12c5d1SDavid du Colombier 	return ret;
5633e12c5d1SDavid du Colombier }
5643e12c5d1SDavid du Colombier 
5653e12c5d1SDavid du Colombier /*
5663e12c5d1SDavid du Colombier  * weird thing: keep at most NBROKEN around
5673e12c5d1SDavid du Colombier  */
5683e12c5d1SDavid du Colombier #define	NBROKEN 4
569bd389b36SDavid du Colombier struct
570bd389b36SDavid du Colombier {
571bd389b36SDavid du Colombier 	QLock;
5723e12c5d1SDavid du Colombier 	int	n;
5733e12c5d1SDavid du Colombier 	Proc	*p[NBROKEN];
5743e12c5d1SDavid du Colombier }broken;
5753e12c5d1SDavid du Colombier 
5763e12c5d1SDavid du Colombier void
577bd389b36SDavid du Colombier addbroken(Proc *p)
5783e12c5d1SDavid du Colombier {
579bd389b36SDavid du Colombier 	qlock(&broken);
5803e12c5d1SDavid du Colombier 	if(broken.n == NBROKEN) {
5813e12c5d1SDavid du Colombier 		ready(broken.p[0]);
5823e12c5d1SDavid du Colombier 		memmove(&broken.p[0], &broken.p[1], sizeof(Proc*)*(NBROKEN-1));
5833e12c5d1SDavid du Colombier 		--broken.n;
5843e12c5d1SDavid du Colombier 	}
585bd389b36SDavid du Colombier 	broken.p[broken.n++] = p;
586bd389b36SDavid du Colombier 	qunlock(&broken);
587bd389b36SDavid du Colombier 
588bd389b36SDavid du Colombier 	p->state = Broken;
589bd389b36SDavid du Colombier 	p->psstate = 0;
590bd389b36SDavid du Colombier 	sched();
591bd389b36SDavid du Colombier }
592bd389b36SDavid du Colombier 
593bd389b36SDavid du Colombier void
594bd389b36SDavid du Colombier unbreak(Proc *p)
595bd389b36SDavid du Colombier {
596bd389b36SDavid du Colombier 	int b;
597bd389b36SDavid du Colombier 
598bd389b36SDavid du Colombier 	qlock(&broken);
599bd389b36SDavid du Colombier 	for(b=0; b < broken.n; b++)
600bd389b36SDavid du Colombier 		if(broken.p[b] == p) {
6013e12c5d1SDavid du Colombier 			broken.n--;
602bd389b36SDavid du Colombier 			memmove(&broken.p[b], &broken.p[b+1],
603bd389b36SDavid du Colombier 					sizeof(Proc*)*(NBROKEN-(b+1)));
604bd389b36SDavid du Colombier 			ready(p);
6053e12c5d1SDavid du Colombier 			break;
6063e12c5d1SDavid du Colombier 		}
607bd389b36SDavid du Colombier 	qunlock(&broken);
6083e12c5d1SDavid du Colombier }
6093e12c5d1SDavid du Colombier 
6103e12c5d1SDavid du Colombier int
6113e12c5d1SDavid du Colombier freebroken(void)
6123e12c5d1SDavid du Colombier {
6133e12c5d1SDavid du Colombier 	int i, n;
6143e12c5d1SDavid du Colombier 
615bd389b36SDavid du Colombier 	qlock(&broken);
6163e12c5d1SDavid du Colombier 	n = broken.n;
617bd389b36SDavid du Colombier 	for(i=0; i<n; i++) {
6183e12c5d1SDavid du Colombier 		ready(broken.p[i]);
619bd389b36SDavid du Colombier 		broken.p[i] = 0;
620bd389b36SDavid du Colombier 	}
6213e12c5d1SDavid du Colombier 	broken.n = 0;
622bd389b36SDavid du Colombier 	qunlock(&broken);
6233e12c5d1SDavid du Colombier 	return n;
6243e12c5d1SDavid du Colombier }
6253e12c5d1SDavid du Colombier 
6263e12c5d1SDavid du Colombier void
6273e12c5d1SDavid du Colombier pexit(char *exitstr, int freemem)
6283e12c5d1SDavid du Colombier {
6293e12c5d1SDavid du Colombier 	int n;
6303e12c5d1SDavid du Colombier 	long utime, stime;
6313e12c5d1SDavid du Colombier 	Proc *p, *c;
632bd389b36SDavid du Colombier 	Segment **s, **es;
6333e12c5d1SDavid du Colombier 	Waitq *wq, *f, *next;
6343e12c5d1SDavid du Colombier 
6353e12c5d1SDavid du Colombier 	c = u->p;
6363e12c5d1SDavid du Colombier 	c->alarm = 0;
6373e12c5d1SDavid du Colombier 
6383e12c5d1SDavid du Colombier 	if(c->fgrp)
6393e12c5d1SDavid du Colombier 		closefgrp(c->fgrp);
6403e12c5d1SDavid du Colombier 	closepgrp(c->pgrp);
6413e12c5d1SDavid du Colombier 	close(u->dot);
6423e12c5d1SDavid du Colombier 	if(c->egrp)
6433e12c5d1SDavid du Colombier 		closeegrp(c->egrp);
6443e12c5d1SDavid du Colombier 
6453e12c5d1SDavid du Colombier 	/*
6463e12c5d1SDavid du Colombier 	 * if not a kernel process and have a parent,
6473e12c5d1SDavid du Colombier 	 * do some housekeeping.
6483e12c5d1SDavid du Colombier 	 */
6493e12c5d1SDavid du Colombier 	if(c->kp == 0) {
650bd389b36SDavid du Colombier 		p = c->parent;
651bd389b36SDavid du Colombier 		if(p == 0) {
6523e12c5d1SDavid du Colombier 			if(exitstr == 0)
6533e12c5d1SDavid du Colombier 				exitstr = "unknown";
6543e12c5d1SDavid du Colombier 			panic("boot process died: %s", exitstr);
6553e12c5d1SDavid du Colombier 		}
6563e12c5d1SDavid du Colombier 
6573e12c5d1SDavid du Colombier 		while(waserror())
6583e12c5d1SDavid du Colombier 			;
6593e12c5d1SDavid du Colombier 		wq = smalloc(sizeof(Waitq));
6603e12c5d1SDavid du Colombier 		poperror();
6613e12c5d1SDavid du Colombier 
6623e12c5d1SDavid du Colombier 		readnum(0, wq->w.pid, NUMSIZE, c->pid, NUMSIZE);
6633e12c5d1SDavid du Colombier 		utime = c->time[TUser] + c->time[TCUser];
6643e12c5d1SDavid du Colombier 		stime = c->time[TSys] + c->time[TCSys];
6653e12c5d1SDavid du Colombier 		readnum(0, &wq->w.time[TUser*12], NUMSIZE,
6663e12c5d1SDavid du Colombier 			TK2MS(utime), NUMSIZE);
6673e12c5d1SDavid du Colombier 		readnum(0, &wq->w.time[TSys*12], NUMSIZE,
6683e12c5d1SDavid du Colombier 			TK2MS(stime), NUMSIZE);
6693e12c5d1SDavid du Colombier 		readnum(0, &wq->w.time[TReal*12], NUMSIZE,
6703e12c5d1SDavid du Colombier 			TK2MS(MACHP(0)->ticks - c->time[TReal]), NUMSIZE);
6713e12c5d1SDavid du Colombier 		if(exitstr && exitstr[0]){
6723e12c5d1SDavid du Colombier 			n = sprint(wq->w.msg, "%s %d:", c->text, c->pid);
6733e12c5d1SDavid du Colombier 			strncpy(wq->w.msg+n, exitstr, ERRLEN-n);
674*219b2ee8SDavid du Colombier 			wq->w.msg[ERRLEN-1] = 0;
675bd389b36SDavid du Colombier 		}
676bd389b36SDavid du Colombier 		else
6773e12c5d1SDavid du Colombier 			wq->w.msg[0] = '\0';
6783e12c5d1SDavid du Colombier 
6793e12c5d1SDavid du Colombier 		lock(&p->exl);
6803e12c5d1SDavid du Colombier 		/* My parent still alive, processes are limited to 128 Zombies to
6813e12c5d1SDavid du Colombier 		 * prevent a badly written daemon lots of wait records
6823e12c5d1SDavid du Colombier 		 */
6833e12c5d1SDavid du Colombier 		if(p->pid == c->parentpid && p->state != Broken && p->nwait < 128) {
6843e12c5d1SDavid du Colombier 			p->nchild--;
6853e12c5d1SDavid du Colombier 			p->time[TCUser] += utime;
6863e12c5d1SDavid du Colombier 			p->time[TCSys] += stime;
6873e12c5d1SDavid du Colombier 
6883e12c5d1SDavid du Colombier 			wq->next = p->waitq;
6893e12c5d1SDavid du Colombier 			p->waitq = wq;
6903e12c5d1SDavid du Colombier 			p->nwait++;
6913e12c5d1SDavid du Colombier 			unlock(&p->exl);
6923e12c5d1SDavid du Colombier 
6933e12c5d1SDavid du Colombier 			wakeup(&p->waitr);
6943e12c5d1SDavid du Colombier 		}
6953e12c5d1SDavid du Colombier 		else {
6963e12c5d1SDavid du Colombier 			unlock(&p->exl);
6973e12c5d1SDavid du Colombier 			free(wq);
6983e12c5d1SDavid du Colombier 		}
6993e12c5d1SDavid du Colombier 	}
7003e12c5d1SDavid du Colombier 
7013e12c5d1SDavid du Colombier 	if(!freemem)
7023e12c5d1SDavid du Colombier 		addbroken(c);
7033e12c5d1SDavid du Colombier 
7043e12c5d1SDavid du Colombier 	es = &c->seg[NSEG];
7053e12c5d1SDavid du Colombier 	for(s = c->seg; s < es; s++)
706bd389b36SDavid du Colombier 		if(*s)
707bd389b36SDavid du Colombier 			putseg(*s);
7083e12c5d1SDavid du Colombier 
7093e12c5d1SDavid du Colombier 	lock(&c->exl);		/* Prevent my children from leaving waits */
7103e12c5d1SDavid du Colombier 	c->pid = 0;
7113e12c5d1SDavid du Colombier 	unlock(&c->exl);
7123e12c5d1SDavid du Colombier 
7133e12c5d1SDavid du Colombier 	for(f = c->waitq; f; f = next) {
7143e12c5d1SDavid du Colombier 		next = f->next;
7153e12c5d1SDavid du Colombier 		free(f);
7163e12c5d1SDavid du Colombier 	}
7173e12c5d1SDavid du Colombier 
7183e12c5d1SDavid du Colombier 	/*
7193e12c5d1SDavid du Colombier 	 * sched() cannot wait on these locks
7203e12c5d1SDavid du Colombier 	 */
7213e12c5d1SDavid du Colombier 	qlock(&c->debug);
7223e12c5d1SDavid du Colombier 	/* release debuggers */
7233e12c5d1SDavid du Colombier 	if(c->pdbg) {
7243e12c5d1SDavid du Colombier 		wakeup(&c->pdbg->sleep);
7253e12c5d1SDavid du Colombier 		c->pdbg = 0;
7263e12c5d1SDavid du Colombier 	}
7273e12c5d1SDavid du Colombier 
728*219b2ee8SDavid du Colombier 	qunlock(&u->p->debug);
7293e12c5d1SDavid du Colombier 	lock(&procalloc);
7303e12c5d1SDavid du Colombier 	lock(&palloc);
7313e12c5d1SDavid du Colombier 
7323e12c5d1SDavid du Colombier 	c->state = Moribund;
7333e12c5d1SDavid du Colombier 	sched();
7343e12c5d1SDavid du Colombier 	panic("pexit");
7353e12c5d1SDavid du Colombier }
7363e12c5d1SDavid du Colombier 
7373e12c5d1SDavid du Colombier int
7383e12c5d1SDavid du Colombier haswaitq(void *x)
7393e12c5d1SDavid du Colombier {
7403e12c5d1SDavid du Colombier 	Proc *p;
7413e12c5d1SDavid du Colombier 
7423e12c5d1SDavid du Colombier 	p = (Proc *)x;
7433e12c5d1SDavid du Colombier 	return p->waitq != 0;
7443e12c5d1SDavid du Colombier }
7453e12c5d1SDavid du Colombier 
7463e12c5d1SDavid du Colombier ulong
7473e12c5d1SDavid du Colombier pwait(Waitmsg *w)
7483e12c5d1SDavid du Colombier {
7493e12c5d1SDavid du Colombier 	Proc *p;
7503e12c5d1SDavid du Colombier 	ulong cpid;
7513e12c5d1SDavid du Colombier 	Waitq *wq;
7523e12c5d1SDavid du Colombier 
7533e12c5d1SDavid du Colombier 	p = u->p;
7543e12c5d1SDavid du Colombier 
755*219b2ee8SDavid du Colombier 	if(!canqlock(&p->qwaitr))
756*219b2ee8SDavid du Colombier 		error(Einuse);
757*219b2ee8SDavid du Colombier 
758*219b2ee8SDavid du Colombier 	if(waserror()) {
759*219b2ee8SDavid du Colombier 		qunlock(&p->qwaitr);
760*219b2ee8SDavid du Colombier 		nexterror();
761*219b2ee8SDavid du Colombier 	}
762*219b2ee8SDavid du Colombier 
7633e12c5d1SDavid du Colombier 	lock(&p->exl);
7643e12c5d1SDavid du Colombier 	if(p->nchild == 0 && p->waitq == 0) {
7653e12c5d1SDavid du Colombier 		unlock(&p->exl);
7663e12c5d1SDavid du Colombier 		error(Enochild);
7673e12c5d1SDavid du Colombier 	}
7683e12c5d1SDavid du Colombier 	unlock(&p->exl);
7693e12c5d1SDavid du Colombier 
7703e12c5d1SDavid du Colombier 	sleep(&p->waitr, haswaitq, u->p);
7713e12c5d1SDavid du Colombier 
7723e12c5d1SDavid du Colombier 	lock(&p->exl);
7733e12c5d1SDavid du Colombier 	wq = p->waitq;
7743e12c5d1SDavid du Colombier 	p->waitq = wq->next;
7753e12c5d1SDavid du Colombier 	p->nwait--;
7763e12c5d1SDavid du Colombier 	unlock(&p->exl);
7773e12c5d1SDavid du Colombier 
778*219b2ee8SDavid du Colombier 	qunlock(&p->qwaitr);
779*219b2ee8SDavid du Colombier 	poperror();
780*219b2ee8SDavid du Colombier 
7813e12c5d1SDavid du Colombier 	if(w)
7823e12c5d1SDavid du Colombier 		memmove(w, &wq->w, sizeof(Waitmsg));
7833e12c5d1SDavid du Colombier 	cpid = atoi(wq->w.pid);
7843e12c5d1SDavid du Colombier 	free(wq);
7853e12c5d1SDavid du Colombier 	return cpid;
7863e12c5d1SDavid du Colombier }
7873e12c5d1SDavid du Colombier 
7883e12c5d1SDavid du Colombier Proc*
7893e12c5d1SDavid du Colombier proctab(int i)
7903e12c5d1SDavid du Colombier {
7913e12c5d1SDavid du Colombier 	return &procalloc.arena[i];
7923e12c5d1SDavid du Colombier }
7933e12c5d1SDavid du Colombier 
7943e12c5d1SDavid du Colombier void
7953e12c5d1SDavid du Colombier procdump(void)
7963e12c5d1SDavid du Colombier {
7973e12c5d1SDavid du Colombier 	int i;
7983e12c5d1SDavid du Colombier 	char *s;
7993e12c5d1SDavid du Colombier 	Proc *p;
8003e12c5d1SDavid du Colombier 	ulong bss;
801*219b2ee8SDavid du Colombier 	Schedq *rq;
8023e12c5d1SDavid du Colombier 
8033e12c5d1SDavid du Colombier 	for(i=0; i<conf.nproc; i++){
8043e12c5d1SDavid du Colombier 		p = procalloc.arena+i;
8053e12c5d1SDavid du Colombier 		if(p->state != Dead){
8063e12c5d1SDavid du Colombier 			bss = 0;
8073e12c5d1SDavid du Colombier 			if(p->seg[BSEG])
8083e12c5d1SDavid du Colombier 				bss = p->seg[BSEG]->top;
8093e12c5d1SDavid du Colombier 
8103e12c5d1SDavid du Colombier 			s = p->psstate;
8113e12c5d1SDavid du Colombier 			if(s == 0)
8123e12c5d1SDavid du Colombier 				s = "kproc";
8133e12c5d1SDavid du Colombier 			print("%3d:%10s %10s pc %8lux %8s (%s) ut %ld st %ld r %lux qpc %lux bss %lux\n",
8143e12c5d1SDavid du Colombier 				p->pid, p->text, p->user, p->pc,
8153e12c5d1SDavid du Colombier 				s, statename[p->state], p->time[0],
8163e12c5d1SDavid du Colombier 				p->time[1], p->r, p->qlockpc, bss);
8173e12c5d1SDavid du Colombier 		}
8183e12c5d1SDavid du Colombier 	}
819*219b2ee8SDavid du Colombier 	for(rq = runq; rq < &runq[Nrq]; rq++){
820*219b2ee8SDavid du Colombier 		if(rq->head == 0)
821*219b2ee8SDavid du Colombier 			continue;
822*219b2ee8SDavid du Colombier 		print("rq%d:", rq-runq);
823*219b2ee8SDavid du Colombier 		for(p = rq->head; p; p = p->rnext)
824*219b2ee8SDavid du Colombier 			print(" %d(%d)", p->pid, m->ticks - p->readytime);
825*219b2ee8SDavid du Colombier 		print("\n");
826*219b2ee8SDavid du Colombier 	}
827*219b2ee8SDavid du Colombier 	print("nrdy %d\n", nrdy);
8283e12c5d1SDavid du Colombier }
8293e12c5d1SDavid du Colombier 
8303e12c5d1SDavid du Colombier void
8313e12c5d1SDavid du Colombier kproc(char *name, void (*func)(void *), void *arg)
8323e12c5d1SDavid du Colombier {
8333e12c5d1SDavid du Colombier 	Proc *p;
8343e12c5d1SDavid du Colombier 	int n;
8353e12c5d1SDavid du Colombier 	ulong upa;
8363e12c5d1SDavid du Colombier 	User *up;
8373e12c5d1SDavid du Colombier 	KMap *k;
8383e12c5d1SDavid du Colombier 	static Pgrp *kpgrp;
8393e12c5d1SDavid du Colombier 	char *user;
8403e12c5d1SDavid du Colombier 	int lastvar;	/* used to compute stack address */
8413e12c5d1SDavid du Colombier 
8423e12c5d1SDavid du Colombier 	/*
8433e12c5d1SDavid du Colombier 	 * Kernel stack
8443e12c5d1SDavid du Colombier 	 */
8453e12c5d1SDavid du Colombier 	p = newproc();
8463e12c5d1SDavid du Colombier 	p->psstate = 0;
8473e12c5d1SDavid du Colombier 	p->procmode = 0644;
8483e12c5d1SDavid du Colombier 	p->kp = 1;
8493e12c5d1SDavid du Colombier 	p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF));
8503e12c5d1SDavid du Colombier 	k = kmap(p->upage);
8513e12c5d1SDavid du Colombier 	upa = VA(k);
8523e12c5d1SDavid du Colombier 	up = (User*)upa;
8533e12c5d1SDavid du Colombier 
8543e12c5d1SDavid du Colombier 	/*
8553e12c5d1SDavid du Colombier 	 * Save time: only copy u-> data and useful stack
8563e12c5d1SDavid du Colombier 	 */
8573e12c5d1SDavid du Colombier 	memmove(up, u, sizeof(User));
8583e12c5d1SDavid du Colombier 	n = USERADDR+BY2PG - (ulong)&lastvar;
8593e12c5d1SDavid du Colombier 	n = (n+32) & ~(BY2WD-1);	/* be safe & word align */
8603e12c5d1SDavid du Colombier 	memmove((void*)(upa+BY2PG-n), (void*)(USERADDR+BY2PG-n), n);
8613e12c5d1SDavid du Colombier 	up->p = p;
8623e12c5d1SDavid du Colombier 
863*219b2ee8SDavid du Colombier 	p->basepri = PriKproc;
864*219b2ee8SDavid du Colombier 	p->priority = p->basepri;
865*219b2ee8SDavid du Colombier 
8663e12c5d1SDavid du Colombier 	/*
8673e12c5d1SDavid du Colombier 	 * Refs
8683e12c5d1SDavid du Colombier 	 */
8693e12c5d1SDavid du Colombier 	incref(up->dot);
8703e12c5d1SDavid du Colombier 	kunmap(k);
8713e12c5d1SDavid du Colombier 
8723e12c5d1SDavid du Colombier 	/*
8733e12c5d1SDavid du Colombier 	 * Sched
8743e12c5d1SDavid du Colombier 	 */
8753e12c5d1SDavid du Colombier 	if(setlabel(&p->sched)){
8763e12c5d1SDavid du Colombier  		p->state = Running;
8773e12c5d1SDavid du Colombier 		p->mach = m;
8783e12c5d1SDavid du Colombier 		m->proc = p;
8793e12c5d1SDavid du Colombier 		spllo();
8803e12c5d1SDavid du Colombier 		(*func)(arg);
8813e12c5d1SDavid du Colombier 		pexit(0, 1);
8823e12c5d1SDavid du Colombier 	}
8833e12c5d1SDavid du Colombier 
8843e12c5d1SDavid du Colombier 	user = eve;
8853e12c5d1SDavid du Colombier 	strcpy(p->user, user);
8863e12c5d1SDavid du Colombier 	if(kpgrp == 0){
8873e12c5d1SDavid du Colombier 		kpgrp = newpgrp();
8883e12c5d1SDavid du Colombier 	}
8893e12c5d1SDavid du Colombier 	p->pgrp = kpgrp;
8903e12c5d1SDavid du Colombier 	incref(kpgrp);
8913e12c5d1SDavid du Colombier 
8923e12c5d1SDavid du Colombier 	strcpy(p->text, name);
8933e12c5d1SDavid du Colombier 
8943e12c5d1SDavid du Colombier 	p->nchild = 0;
8953e12c5d1SDavid du Colombier 	p->parent = 0;
8963e12c5d1SDavid du Colombier 	memset(p->time, 0, sizeof(p->time));
8973e12c5d1SDavid du Colombier 	p->time[TReal] = MACHP(0)->ticks;
8983e12c5d1SDavid du Colombier 	ready(p);
8993e12c5d1SDavid du Colombier 	/*
9003e12c5d1SDavid du Colombier 	 *  since the bss/data segments are now shareable,
9013e12c5d1SDavid du Colombier 	 *  any mmu info about this process is now stale
9023e12c5d1SDavid du Colombier 	 *  and has to be discarded.
9033e12c5d1SDavid du Colombier 	 */
9043e12c5d1SDavid du Colombier 	flushmmu();
9053e12c5d1SDavid du Colombier }
9063e12c5d1SDavid du Colombier 
9073e12c5d1SDavid du Colombier /*
9083e12c5d1SDavid du Colombier  *  called splhi() by notify().  See comment in notify for the
9093e12c5d1SDavid du Colombier  *  reasoning.
9103e12c5d1SDavid du Colombier  */
9113e12c5d1SDavid du Colombier void
9123e12c5d1SDavid du Colombier procctl(Proc *p)
9133e12c5d1SDavid du Colombier {
9143e12c5d1SDavid du Colombier 	char *state;
915*219b2ee8SDavid du Colombier 	ulong s;
9163e12c5d1SDavid du Colombier 
9173e12c5d1SDavid du Colombier 	switch(p->procctl) {
9183e12c5d1SDavid du Colombier 	case Proc_exitme:
9193e12c5d1SDavid du Colombier 		spllo();	/* pexit has locks in it */
9203e12c5d1SDavid du Colombier 		pexit("Killed", 1);
9213e12c5d1SDavid du Colombier 
9223e12c5d1SDavid du Colombier 	case Proc_traceme:
9233e12c5d1SDavid du Colombier 		if(u->nnote == 0)
9243e12c5d1SDavid du Colombier 			return;
9253e12c5d1SDavid du Colombier 		/* No break */
9263e12c5d1SDavid du Colombier 
9273e12c5d1SDavid du Colombier 	case Proc_stopme:
9283e12c5d1SDavid du Colombier 		p->procctl = 0;
9293e12c5d1SDavid du Colombier 		state = p->psstate;
9303e12c5d1SDavid du Colombier 		p->psstate = "Stopped";
9313e12c5d1SDavid du Colombier 		/* free a waiting debugger */
932*219b2ee8SDavid du Colombier 		s = spllo();
9333e12c5d1SDavid du Colombier 		qlock(&p->debug);
9343e12c5d1SDavid du Colombier 		if(p->pdbg) {
9353e12c5d1SDavid du Colombier 			wakeup(&p->pdbg->sleep);
9363e12c5d1SDavid du Colombier 			p->pdbg = 0;
9373e12c5d1SDavid du Colombier 		}
9383e12c5d1SDavid du Colombier 		qunlock(&p->debug);
9393e12c5d1SDavid du Colombier 		splhi();
940*219b2ee8SDavid du Colombier 		p->state = Stopped;
941*219b2ee8SDavid du Colombier 		sched();
9423e12c5d1SDavid du Colombier 		p->psstate = state;
943*219b2ee8SDavid du Colombier 		splx(s);
9443e12c5d1SDavid du Colombier 		return;
9453e12c5d1SDavid du Colombier 	}
9463e12c5d1SDavid du Colombier }
9473e12c5d1SDavid du Colombier 
9483e12c5d1SDavid du Colombier #include "errstr.h"
9493e12c5d1SDavid du Colombier 
9503e12c5d1SDavid du Colombier void
9513e12c5d1SDavid du Colombier error(char *err)
9523e12c5d1SDavid du Colombier {
953*219b2ee8SDavid du Colombier 	spllo();
9543e12c5d1SDavid du Colombier 	strncpy(u->error, err, ERRLEN);
9553e12c5d1SDavid du Colombier 	nexterror();
9563e12c5d1SDavid du Colombier }
9573e12c5d1SDavid du Colombier 
9583e12c5d1SDavid du Colombier void
9593e12c5d1SDavid du Colombier nexterror(void)
9603e12c5d1SDavid du Colombier {
9613e12c5d1SDavid du Colombier 	gotolabel(&u->errlab[--u->nerrlab]);
9623e12c5d1SDavid du Colombier }
9633e12c5d1SDavid du Colombier 
9643e12c5d1SDavid du Colombier void
9653e12c5d1SDavid du Colombier exhausted(char *resource)
9663e12c5d1SDavid du Colombier {
9673e12c5d1SDavid du Colombier 	char buf[ERRLEN];
9683e12c5d1SDavid du Colombier 
9693e12c5d1SDavid du Colombier 	sprint(buf, "no free %s", resource);
9703e12c5d1SDavid du Colombier 	error(buf);
9713e12c5d1SDavid du Colombier }
972