xref: /plan9-contrib/sys/src/9k/port/proc.c (revision 4498a2438a086713d814ef7bd3d66ca21846c7c5)
19ef1f84bSDavid du Colombier #include	<u.h>
29ef1f84bSDavid du Colombier #include	"../port/lib.h"
39ef1f84bSDavid du Colombier #include	"mem.h"
49ef1f84bSDavid du Colombier #include	"dat.h"
59ef1f84bSDavid du Colombier #include	"fns.h"
69ef1f84bSDavid du Colombier #include	"../port/error.h"
79ef1f84bSDavid du Colombier 
89ef1f84bSDavid du Colombier #include	"../port/edf.h"
99ef1f84bSDavid du Colombier #include	"errstr.h"
10d46407a3SDavid du Colombier #include	<ptrace.h>
119ef1f84bSDavid du Colombier 
129ef1f84bSDavid du Colombier int	nrdy;
139ef1f84bSDavid du Colombier Ref	noteidalloc;
149ef1f84bSDavid du Colombier 
159ef1f84bSDavid du Colombier ulong delayedscheds;	/* statistics */
169ef1f84bSDavid du Colombier long skipscheds;
179ef1f84bSDavid du Colombier long preempts;
189ef1f84bSDavid du Colombier 
199ef1f84bSDavid du Colombier static Ref pidalloc;
209ef1f84bSDavid du Colombier 
219ef1f84bSDavid du Colombier struct Procalloc procalloc;
229ef1f84bSDavid du Colombier 
239ef1f84bSDavid du Colombier extern Proc* psalloc(void);
249ef1f84bSDavid du Colombier extern void pshash(Proc*);
259ef1f84bSDavid du Colombier extern void psrelease(Proc*);
269ef1f84bSDavid du Colombier extern void psunhash(Proc*);
279ef1f84bSDavid du Colombier 
289ef1f84bSDavid du Colombier enum
299ef1f84bSDavid du Colombier {
309ef1f84bSDavid du Colombier 	Scaling=2,
319ef1f84bSDavid du Colombier };
329ef1f84bSDavid du Colombier 
339ef1f84bSDavid du Colombier static int reprioritize(Proc*);
349ef1f84bSDavid du Colombier static void updatecpu(Proc*);
359ef1f84bSDavid du Colombier static int schedgain = 30;	/* units in seconds */
369ef1f84bSDavid du Colombier 
379ef1f84bSDavid du Colombier static void rebalance(void);
389ef1f84bSDavid du Colombier static ulong balancetime;
399ef1f84bSDavid du Colombier 
409ef1f84bSDavid du Colombier Schedq	runq[Nrq];
419ef1f84bSDavid du Colombier ulong	runvec;
429ef1f84bSDavid du Colombier 
439ef1f84bSDavid du Colombier char *statename[] =
449ef1f84bSDavid du Colombier {	/* BUG: generate automatically */
459ef1f84bSDavid du Colombier 	"Dead",
469ef1f84bSDavid du Colombier 	"Moribund",
479ef1f84bSDavid du Colombier 	"Ready",
489ef1f84bSDavid du Colombier 	"Scheding",
499ef1f84bSDavid du Colombier 	"Running",
509ef1f84bSDavid du Colombier 	"Queueing",
519ef1f84bSDavid du Colombier 	"QueueingR",
529ef1f84bSDavid du Colombier 	"QueueingW",
539ef1f84bSDavid du Colombier 	"Wakeme",
549ef1f84bSDavid du Colombier 	"Broken",
559ef1f84bSDavid du Colombier 	"Stopped",
569ef1f84bSDavid du Colombier 	"Rendez",
579ef1f84bSDavid du Colombier 	"Waitrelease",
589ef1f84bSDavid du Colombier };
599ef1f84bSDavid du Colombier 
609ef1f84bSDavid du Colombier /*
619ef1f84bSDavid du Colombier  * Always splhi()'ed.
629ef1f84bSDavid du Colombier  */
639ef1f84bSDavid du Colombier void
schedinit(void)649ef1f84bSDavid du Colombier schedinit(void)		/* never returns */
659ef1f84bSDavid du Colombier {
669ef1f84bSDavid du Colombier 	Edf *e;
679ef1f84bSDavid du Colombier 
689ef1f84bSDavid du Colombier 	setlabel(&m->sched);
699ef1f84bSDavid du Colombier 	if(up) {
709ef1f84bSDavid du Colombier 		if((e = up->edf) && (e->flags & Admitted))
719ef1f84bSDavid du Colombier 			edfrecord(up);
729ef1f84bSDavid du Colombier 		updatecpu(up);
73*4498a243SDavid du Colombier 		m->proc = nil;
749ef1f84bSDavid du Colombier 		switch(up->state) {
759ef1f84bSDavid du Colombier 		case Running:
769ef1f84bSDavid du Colombier 			ready(up);
779ef1f84bSDavid du Colombier 			break;
789ef1f84bSDavid du Colombier 		case Moribund:
799ef1f84bSDavid du Colombier 			up->state = Dead;
809ef1f84bSDavid du Colombier 
819ef1f84bSDavid du Colombier 			/*
829ef1f84bSDavid du Colombier 			 * Holding locks from pexit:
839ef1f84bSDavid du Colombier 			 * 	procalloc
849ef1f84bSDavid du Colombier 			 *	palloc
859ef1f84bSDavid du Colombier 			 */
869ef1f84bSDavid du Colombier 			mmurelease(up);
879ef1f84bSDavid du Colombier 			unlock(&palloc);
889ef1f84bSDavid du Colombier 
899ef1f84bSDavid du Colombier 			psrelease(up);
909ef1f84bSDavid du Colombier 			unlock(&procalloc);
919ef1f84bSDavid du Colombier 			break;
929ef1f84bSDavid du Colombier 		}
939ef1f84bSDavid du Colombier 		up->mach = nil;
949ef1f84bSDavid du Colombier 		up = nil;
959ef1f84bSDavid du Colombier 	}
969ef1f84bSDavid du Colombier 	sched();
979ef1f84bSDavid du Colombier }
989ef1f84bSDavid du Colombier 
999ef1f84bSDavid du Colombier /*
1009ef1f84bSDavid du Colombier  *  If changing this routine, look also at sleep().  It
1019ef1f84bSDavid du Colombier  *  contains a copy of the guts of sched().
1029ef1f84bSDavid du Colombier  */
1039ef1f84bSDavid du Colombier void
sched(void)1049ef1f84bSDavid du Colombier sched(void)
1059ef1f84bSDavid du Colombier {
1069ef1f84bSDavid du Colombier 	Proc *p;
1079ef1f84bSDavid du Colombier 
1089ef1f84bSDavid du Colombier 	if(m->ilockdepth)
1099ef1f84bSDavid du Colombier 		panic("cpu%d: ilockdepth %d, last lock %#p at %#p, sched called from %#p",
1109ef1f84bSDavid du Colombier 			m->machno,
1119ef1f84bSDavid du Colombier 			m->ilockdepth,
1129ef1f84bSDavid du Colombier 			up? up->lastilock: nil,
1139ef1f84bSDavid du Colombier 			(up && up->lastilock)? up->lastilock->pc: m->ilockpc,
1149ef1f84bSDavid du Colombier 			getcallerpc(&p+2));
1159ef1f84bSDavid du Colombier 
1169ef1f84bSDavid du Colombier 	if(up){
1179ef1f84bSDavid du Colombier 		/*
1189ef1f84bSDavid du Colombier 		 * Delay the sched until the process gives up the locks
1199ef1f84bSDavid du Colombier 		 * it is holding.  This avoids dumb lock loops.
1209ef1f84bSDavid du Colombier 		 * Don't delay if the process is Moribund.
1219ef1f84bSDavid du Colombier 		 * It called sched to die.
1229ef1f84bSDavid du Colombier 		 * But do sched eventually.  This avoids a missing unlock
1239ef1f84bSDavid du Colombier 		 * from hanging the entire kernel.
1249ef1f84bSDavid du Colombier 		 * But don't reschedule procs holding palloc or procalloc.
1259ef1f84bSDavid du Colombier 		 * Those are far too important to be holding while asleep.
1269ef1f84bSDavid du Colombier 		 *
1279ef1f84bSDavid du Colombier 		 * This test is not exact.  There can still be a few
1289ef1f84bSDavid du Colombier 		 * instructions in the middle of taslock when a process
1299ef1f84bSDavid du Colombier 		 * holds a lock but Lock.p has not yet been initialized.
1309ef1f84bSDavid du Colombier 		 */
1319ef1f84bSDavid du Colombier 		if(up->nlocks)
1329ef1f84bSDavid du Colombier 		if(up->state != Moribund)
1339ef1f84bSDavid du Colombier 		if(up->delaysched < 20
1349ef1f84bSDavid du Colombier 		|| palloc.Lock.p == up
1359ef1f84bSDavid du Colombier 		|| procalloc.Lock.p == up){
1369ef1f84bSDavid du Colombier 			up->delaysched++;
1379ef1f84bSDavid du Colombier 			delayedscheds++;
1389ef1f84bSDavid du Colombier 			return;
1399ef1f84bSDavid du Colombier 		}
1409ef1f84bSDavid du Colombier 		up->delaysched = 0;
1419ef1f84bSDavid du Colombier 
1429ef1f84bSDavid du Colombier 		splhi();
1439ef1f84bSDavid du Colombier 
1449ef1f84bSDavid du Colombier 		/* statistics */
1459ef1f84bSDavid du Colombier 		m->cs++;
1469ef1f84bSDavid du Colombier 
1479ef1f84bSDavid du Colombier 		procsave(up);
1489ef1f84bSDavid du Colombier 		if(setlabel(&up->sched)){
1499ef1f84bSDavid du Colombier 			procrestore(up);
1509ef1f84bSDavid du Colombier 			spllo();
1519ef1f84bSDavid du Colombier 			return;
1529ef1f84bSDavid du Colombier 		}
1539ef1f84bSDavid du Colombier 		gotolabel(&m->sched);
1549ef1f84bSDavid du Colombier 	}
1559ef1f84bSDavid du Colombier 	p = runproc();
1569ef1f84bSDavid du Colombier 	if(!p->edf){
1579ef1f84bSDavid du Colombier 		updatecpu(p);
1589ef1f84bSDavid du Colombier 		p->priority = reprioritize(p);
1599ef1f84bSDavid du Colombier 	}
1609ef1f84bSDavid du Colombier 	if(p != m->readied)
1619ef1f84bSDavid du Colombier 		m->schedticks = m->ticks + HZ/10;
162*4498a243SDavid du Colombier 	m->readied = nil;
1639ef1f84bSDavid du Colombier 	up = p;
1649ef1f84bSDavid du Colombier 	up->state = Running;
1659ef1f84bSDavid du Colombier 	up->mach = m;
1669ef1f84bSDavid du Colombier 	m->proc = up;
1679ef1f84bSDavid du Colombier 	mmuswitch(up);
1689ef1f84bSDavid du Colombier 	gotolabel(&up->sched);
1699ef1f84bSDavid du Colombier }
1709ef1f84bSDavid du Colombier 
1719ef1f84bSDavid du Colombier int
anyready(void)1729ef1f84bSDavid du Colombier anyready(void)
1739ef1f84bSDavid du Colombier {
1749ef1f84bSDavid du Colombier 	return runvec;
1759ef1f84bSDavid du Colombier }
1769ef1f84bSDavid du Colombier 
1779ef1f84bSDavid du Colombier int
anyhigher(void)1789ef1f84bSDavid du Colombier anyhigher(void)
1799ef1f84bSDavid du Colombier {
1809ef1f84bSDavid du Colombier 	return runvec & ~((1<<(up->priority+1))-1);
1819ef1f84bSDavid du Colombier }
1829ef1f84bSDavid du Colombier 
1839ef1f84bSDavid du Colombier /*
1849ef1f84bSDavid du Colombier  *  here once per clock tick to see if we should resched
1859ef1f84bSDavid du Colombier  */
1869ef1f84bSDavid du Colombier void
hzsched(void)1879ef1f84bSDavid du Colombier hzsched(void)
1889ef1f84bSDavid du Colombier {
1899ef1f84bSDavid du Colombier 	/* once a second, rebalance will reprioritize ready procs */
1909ef1f84bSDavid du Colombier 	if(m->machno == 0)
1919ef1f84bSDavid du Colombier 		rebalance();
1929ef1f84bSDavid du Colombier 
1939ef1f84bSDavid du Colombier 	/* unless preempted, get to run for at least 100ms */
1949ef1f84bSDavid du Colombier 	if(anyhigher()
1959ef1f84bSDavid du Colombier 	|| (!up->fixedpri && m->ticks > m->schedticks && anyready())){
1969ef1f84bSDavid du Colombier 		m->readied = nil;	/* avoid cooperative scheduling */
1979ef1f84bSDavid du Colombier 		up->delaysched++;
1989ef1f84bSDavid du Colombier 	}
1999ef1f84bSDavid du Colombier }
2009ef1f84bSDavid du Colombier 
2019ef1f84bSDavid du Colombier /*
2029ef1f84bSDavid du Colombier  *  here at the end of non-clock interrupts to see if we should preempt the
2039ef1f84bSDavid du Colombier  *  current process.  Returns 1 if preempted, 0 otherwise.
2049ef1f84bSDavid du Colombier  */
2059ef1f84bSDavid du Colombier int
preempted(void)2069ef1f84bSDavid du Colombier preempted(void)
2079ef1f84bSDavid du Colombier {
2089ef1f84bSDavid du Colombier 	if(up && up->state == Running)
2099ef1f84bSDavid du Colombier 	if(up->preempted == 0)
2109ef1f84bSDavid du Colombier 	if(anyhigher())
2119ef1f84bSDavid du Colombier 	if(!active.exiting){
2129ef1f84bSDavid du Colombier 		m->readied = nil;	/* avoid cooperative scheduling */
2139ef1f84bSDavid du Colombier 		up->preempted = 1;
2149ef1f84bSDavid du Colombier 		sched();
2159ef1f84bSDavid du Colombier 		splhi();
2169ef1f84bSDavid du Colombier 		up->preempted = 0;
2179ef1f84bSDavid du Colombier 		return 1;
2189ef1f84bSDavid du Colombier 	}
2199ef1f84bSDavid du Colombier 	return 0;
2209ef1f84bSDavid du Colombier }
2219ef1f84bSDavid du Colombier 
2229ef1f84bSDavid du Colombier /*
2239ef1f84bSDavid du Colombier  * Update the cpu time average for this particular process,
2249ef1f84bSDavid du Colombier  * which is about to change from up -> not up or vice versa.
2259ef1f84bSDavid du Colombier  * p->lastupdate is the last time an updatecpu happened.
2269ef1f84bSDavid du Colombier  *
2279ef1f84bSDavid du Colombier  * The cpu time average is a decaying average that lasts
2289ef1f84bSDavid du Colombier  * about D clock ticks.  D is chosen to be approximately
2299ef1f84bSDavid du Colombier  * the cpu time of a cpu-intensive "quick job".  A job has to run
2309ef1f84bSDavid du Colombier  * for approximately D clock ticks before we home in on its
2319ef1f84bSDavid du Colombier  * actual cpu usage.  Thus if you manage to get in and get out
2329ef1f84bSDavid du Colombier  * quickly, you won't be penalized during your burst.  Once you
2339ef1f84bSDavid du Colombier  * start using your share of the cpu for more than about D
2349ef1f84bSDavid du Colombier  * clock ticks though, your p->cpu hits 1000 (1.0) and you end up
2359ef1f84bSDavid du Colombier  * below all the other quick jobs.  Interactive tasks, because
2369ef1f84bSDavid du Colombier  * they basically always use less than their fair share of cpu,
2379ef1f84bSDavid du Colombier  * will be rewarded.
2389ef1f84bSDavid du Colombier  *
2399ef1f84bSDavid du Colombier  * If the process has not been running, then we want to
2409ef1f84bSDavid du Colombier  * apply the filter
2419ef1f84bSDavid du Colombier  *
2429ef1f84bSDavid du Colombier  *	cpu = cpu * (D-1)/D
2439ef1f84bSDavid du Colombier  *
2449ef1f84bSDavid du Colombier  * n times, yielding
2459ef1f84bSDavid du Colombier  *
2469ef1f84bSDavid du Colombier  *	cpu = cpu * ((D-1)/D)^n
2479ef1f84bSDavid du Colombier  *
2489ef1f84bSDavid du Colombier  * but D is big enough that this is approximately
2499ef1f84bSDavid du Colombier  *
2509ef1f84bSDavid du Colombier  * 	cpu = cpu * (D-n)/D
2519ef1f84bSDavid du Colombier  *
2529ef1f84bSDavid du Colombier  * so we use that instead.
2539ef1f84bSDavid du Colombier  *
2549ef1f84bSDavid du Colombier  * If the process has been running, we apply the filter to
2559ef1f84bSDavid du Colombier  * 1 - cpu, yielding a similar equation.  Note that cpu is
2569ef1f84bSDavid du Colombier  * stored in fixed point (* 1000).
2579ef1f84bSDavid du Colombier  *
2589ef1f84bSDavid du Colombier  * Updatecpu must be called before changing up, in order
2599ef1f84bSDavid du Colombier  * to maintain accurate cpu usage statistics.  It can be called
2609ef1f84bSDavid du Colombier  * at any time to bring the stats for a given proc up-to-date.
2619ef1f84bSDavid du Colombier  */
2629ef1f84bSDavid du Colombier static void
updatecpu(Proc * p)2639ef1f84bSDavid du Colombier updatecpu(Proc *p)
2649ef1f84bSDavid du Colombier {
2659ef1f84bSDavid du Colombier 	int D, n, t, ocpu;
2669ef1f84bSDavid du Colombier 
2679ef1f84bSDavid du Colombier 	if(p->edf)
2689ef1f84bSDavid du Colombier 		return;
2699ef1f84bSDavid du Colombier 
2709ef1f84bSDavid du Colombier 	t = sys->ticks*Scaling + Scaling/2;
2719ef1f84bSDavid du Colombier 	n = t - p->lastupdate;
2729ef1f84bSDavid du Colombier 	p->lastupdate = t;
2739ef1f84bSDavid du Colombier 
2749ef1f84bSDavid du Colombier 	if(n == 0)
2759ef1f84bSDavid du Colombier 		return;
2769ef1f84bSDavid du Colombier 	D = schedgain*HZ*Scaling;
2779ef1f84bSDavid du Colombier 	if(n > D)
2789ef1f84bSDavid du Colombier 		n = D;
2799ef1f84bSDavid du Colombier 
2809ef1f84bSDavid du Colombier 	ocpu = p->cpu;
2819ef1f84bSDavid du Colombier 	if(p != up)
2829ef1f84bSDavid du Colombier 		p->cpu = (ocpu*(D-n))/D;
2839ef1f84bSDavid du Colombier 	else{
2849ef1f84bSDavid du Colombier 		t = 1000 - ocpu;
2859ef1f84bSDavid du Colombier 		t = (t*(D-n))/D;
2869ef1f84bSDavid du Colombier 		p->cpu = 1000 - t;
2879ef1f84bSDavid du Colombier 	}
2889ef1f84bSDavid du Colombier 
2899ef1f84bSDavid du Colombier //iprint("pid %d %s for %d cpu %d -> %d\n", p->pid,p==up?"active":"inactive",n, ocpu,p->cpu);
2909ef1f84bSDavid du Colombier }
2919ef1f84bSDavid du Colombier 
2929ef1f84bSDavid du Colombier /*
2939ef1f84bSDavid du Colombier  * On average, p has used p->cpu of a cpu recently.
2949ef1f84bSDavid du Colombier  * Its fair share is sys.nonline/m->load of a cpu.  If it has been getting
2959ef1f84bSDavid du Colombier  * too much, penalize it.  If it has been getting not enough, reward it.
2969ef1f84bSDavid du Colombier  * I don't think you can get much more than your fair share that
2979ef1f84bSDavid du Colombier  * often, so most of the queues are for using less.  Having a priority
2989ef1f84bSDavid du Colombier  * of 3 means you're just right.  Having a higher priority (up to p->basepri)
2999ef1f84bSDavid du Colombier  * means you're not using as much as you could.
3009ef1f84bSDavid du Colombier  */
3019ef1f84bSDavid du Colombier static int
reprioritize(Proc * p)3029ef1f84bSDavid du Colombier reprioritize(Proc *p)
3039ef1f84bSDavid du Colombier {
3049ef1f84bSDavid du Colombier 	int fairshare, n, load, ratio;
3059ef1f84bSDavid du Colombier 
3069ef1f84bSDavid du Colombier 	load = sys->machptr[0]->load;
3079ef1f84bSDavid du Colombier 	if(load == 0)
3089ef1f84bSDavid du Colombier 		return p->basepri;
3099ef1f84bSDavid du Colombier 
3109ef1f84bSDavid du Colombier 	/*
3119ef1f84bSDavid du Colombier 	 *  fairshare = 1.000 * PROCMAX * 1.000/load,
3129ef1f84bSDavid du Colombier 	 * except the decimal point is moved three places
3139ef1f84bSDavid du Colombier 	 * on both load and fairshare.
3149ef1f84bSDavid du Colombier 	 */
3159ef1f84bSDavid du Colombier 	fairshare = (sys->nonline*1000*1000)/load;
3169ef1f84bSDavid du Colombier 	n = p->cpu;
3179ef1f84bSDavid du Colombier 	if(n == 0)
3189ef1f84bSDavid du Colombier 		n = 1;
3199ef1f84bSDavid du Colombier 	ratio = (fairshare+n/2) / n;
3209ef1f84bSDavid du Colombier 	if(ratio > p->basepri)
3219ef1f84bSDavid du Colombier 		ratio = p->basepri;
3229ef1f84bSDavid du Colombier 	if(ratio < 0)
3239ef1f84bSDavid du Colombier 		panic("reprioritize");
3249ef1f84bSDavid du Colombier //iprint("pid %d cpu %d load %d fair %d pri %d\n", p->pid, p->cpu, load, fairshare, ratio);
3259ef1f84bSDavid du Colombier 	return ratio;
3269ef1f84bSDavid du Colombier }
3279ef1f84bSDavid du Colombier 
3289ef1f84bSDavid du Colombier /*
3299ef1f84bSDavid du Colombier  * add a process to a scheduling queue
3309ef1f84bSDavid du Colombier  */
3319ef1f84bSDavid du Colombier void
queueproc(Schedq * rq,Proc * p)3329ef1f84bSDavid du Colombier queueproc(Schedq *rq, Proc *p)
3339ef1f84bSDavid du Colombier {
3349ef1f84bSDavid du Colombier 	int pri;
3359ef1f84bSDavid du Colombier 
3369ef1f84bSDavid du Colombier 	pri = rq - runq;
3379ef1f84bSDavid du Colombier 	lock(runq);
3389ef1f84bSDavid du Colombier 	p->priority = pri;
3399ef1f84bSDavid du Colombier 	p->rnext = 0;
3409ef1f84bSDavid du Colombier 	if(rq->tail)
3419ef1f84bSDavid du Colombier 		rq->tail->rnext = p;
3429ef1f84bSDavid du Colombier 	else
3439ef1f84bSDavid du Colombier 		rq->head = p;
3449ef1f84bSDavid du Colombier 	rq->tail = p;
3459ef1f84bSDavid du Colombier 	rq->n++;
3469ef1f84bSDavid du Colombier 	nrdy++;
3479ef1f84bSDavid du Colombier 	runvec |= 1<<pri;
3489ef1f84bSDavid du Colombier 	unlock(runq);
3499ef1f84bSDavid du Colombier }
3509ef1f84bSDavid du Colombier 
3519ef1f84bSDavid du Colombier /*
3529ef1f84bSDavid du Colombier  *  try to remove a process from a scheduling queue (called splhi)
3539ef1f84bSDavid du Colombier  */
3549ef1f84bSDavid du Colombier Proc*
dequeueproc(Schedq * rq,Proc * tp)3559ef1f84bSDavid du Colombier dequeueproc(Schedq *rq, Proc *tp)
3569ef1f84bSDavid du Colombier {
3579ef1f84bSDavid du Colombier 	Proc *l, *p;
3589ef1f84bSDavid du Colombier 
3599ef1f84bSDavid du Colombier 	if(!canlock(runq))
3609ef1f84bSDavid du Colombier 		return nil;
3619ef1f84bSDavid du Colombier 
3629ef1f84bSDavid du Colombier 	/*
3639ef1f84bSDavid du Colombier 	 *  the queue may have changed before we locked runq,
3649ef1f84bSDavid du Colombier 	 *  refind the target process.
3659ef1f84bSDavid du Colombier 	 */
3669ef1f84bSDavid du Colombier 	l = 0;
3679ef1f84bSDavid du Colombier 	for(p = rq->head; p; p = p->rnext){
3689ef1f84bSDavid du Colombier 		if(p == tp)
3699ef1f84bSDavid du Colombier 			break;
3709ef1f84bSDavid du Colombier 		l = p;
3719ef1f84bSDavid du Colombier 	}
3729ef1f84bSDavid du Colombier 
3739ef1f84bSDavid du Colombier 	/*
3749ef1f84bSDavid du Colombier 	 *  p->mach==0 only when process state is saved
3759ef1f84bSDavid du Colombier 	 */
376*4498a243SDavid du Colombier 	if(p == nil || p->mach){
3779ef1f84bSDavid du Colombier 		unlock(runq);
3789ef1f84bSDavid du Colombier 		return nil;
3799ef1f84bSDavid du Colombier 	}
380*4498a243SDavid du Colombier 	if(p->rnext == nil)
3819ef1f84bSDavid du Colombier 		rq->tail = l;
3829ef1f84bSDavid du Colombier 	if(l)
3839ef1f84bSDavid du Colombier 		l->rnext = p->rnext;
3849ef1f84bSDavid du Colombier 	else
3859ef1f84bSDavid du Colombier 		rq->head = p->rnext;
3869ef1f84bSDavid du Colombier 	if(rq->head == nil)
3879ef1f84bSDavid du Colombier 		runvec &= ~(1<<(rq-runq));
3889ef1f84bSDavid du Colombier 	rq->n--;
3899ef1f84bSDavid du Colombier 	nrdy--;
3909ef1f84bSDavid du Colombier 	if(p->state != Ready)
3919ef1f84bSDavid du Colombier 		print("dequeueproc %s %d %s\n", p->text, p->pid, statename[p->state]);
3929ef1f84bSDavid du Colombier 
3939ef1f84bSDavid du Colombier 	unlock(runq);
3949ef1f84bSDavid du Colombier 	return p;
3959ef1f84bSDavid du Colombier }
3969ef1f84bSDavid du Colombier 
3979ef1f84bSDavid du Colombier /*
3989ef1f84bSDavid du Colombier  *  ready(p) picks a new priority for a process and sticks it in the
3999ef1f84bSDavid du Colombier  *  runq for that priority.
4009ef1f84bSDavid du Colombier  */
4019ef1f84bSDavid du Colombier void
ready(Proc * p)4029ef1f84bSDavid du Colombier ready(Proc *p)
4039ef1f84bSDavid du Colombier {
4049ef1f84bSDavid du Colombier 	Mreg s;
4059ef1f84bSDavid du Colombier 	int pri;
4069ef1f84bSDavid du Colombier 	Schedq *rq;
407d46407a3SDavid du Colombier 	void (*pt)(Proc*, int, vlong, vlong);
4089ef1f84bSDavid du Colombier 
4099ef1f84bSDavid du Colombier 	s = splhi();
4109ef1f84bSDavid du Colombier 	if(edfready(p)){
4119ef1f84bSDavid du Colombier 		splx(s);
4129ef1f84bSDavid du Colombier 		return;
4139ef1f84bSDavid du Colombier 	}
4149ef1f84bSDavid du Colombier 
4159ef1f84bSDavid du Colombier 	if(up != p && (p->wired == nil || p->wired == m))
4169ef1f84bSDavid du Colombier 		m->readied = p;	/* group scheduling */
4179ef1f84bSDavid du Colombier 
4189ef1f84bSDavid du Colombier 	updatecpu(p);
4199ef1f84bSDavid du Colombier 	pri = reprioritize(p);
4209ef1f84bSDavid du Colombier 	p->priority = pri;
4219ef1f84bSDavid du Colombier 	rq = &runq[pri];
4229ef1f84bSDavid du Colombier 	p->state = Ready;
4239ef1f84bSDavid du Colombier 	queueproc(rq, p);
4249ef1f84bSDavid du Colombier 	pt = proctrace;
4259ef1f84bSDavid du Colombier 	if(pt)
426d46407a3SDavid du Colombier 		pt(p, SReady, 0, 0);
4279ef1f84bSDavid du Colombier 	splx(s);
4289ef1f84bSDavid du Colombier }
4299ef1f84bSDavid du Colombier 
4309ef1f84bSDavid du Colombier /*
4319ef1f84bSDavid du Colombier  *  yield the processor and drop our priority
4329ef1f84bSDavid du Colombier  */
4339ef1f84bSDavid du Colombier void
yield(void)4349ef1f84bSDavid du Colombier yield(void)
4359ef1f84bSDavid du Colombier {
4369ef1f84bSDavid du Colombier 	if(anyready()){
4379ef1f84bSDavid du Colombier 		/* pretend we just used 1/2 tick */
4389ef1f84bSDavid du Colombier 		up->lastupdate -= Scaling/2;
4399ef1f84bSDavid du Colombier 		sched();
4409ef1f84bSDavid du Colombier 	}
4419ef1f84bSDavid du Colombier }
4429ef1f84bSDavid du Colombier 
4439ef1f84bSDavid du Colombier /*
4449ef1f84bSDavid du Colombier  *  recalculate priorities once a second.  We need to do this
4459ef1f84bSDavid du Colombier  *  since priorities will otherwise only be recalculated when
4469ef1f84bSDavid du Colombier  *  the running process blocks.
4479ef1f84bSDavid du Colombier  */
4489ef1f84bSDavid du Colombier static void
rebalance(void)4499ef1f84bSDavid du Colombier rebalance(void)
4509ef1f84bSDavid du Colombier {
4519ef1f84bSDavid du Colombier 	Mreg s;
4529ef1f84bSDavid du Colombier 	int pri, npri, t;
4539ef1f84bSDavid du Colombier 	Schedq *rq;
4549ef1f84bSDavid du Colombier 	Proc *p;
4559ef1f84bSDavid du Colombier 
4569ef1f84bSDavid du Colombier 	t = m->ticks;
4579ef1f84bSDavid du Colombier 	if(t - balancetime < HZ)
4589ef1f84bSDavid du Colombier 		return;
4599ef1f84bSDavid du Colombier 	balancetime = t;
4609ef1f84bSDavid du Colombier 
4619ef1f84bSDavid du Colombier 	for(pri=0, rq=runq; pri<Npriq; pri++, rq++){
4629ef1f84bSDavid du Colombier another:
4639ef1f84bSDavid du Colombier 		p = rq->head;
4649ef1f84bSDavid du Colombier 		if(p == nil)
4659ef1f84bSDavid du Colombier 			continue;
4669ef1f84bSDavid du Colombier 		if(p->mp != m)
4679ef1f84bSDavid du Colombier 			continue;
4689ef1f84bSDavid du Colombier 		if(pri == p->basepri)
4699ef1f84bSDavid du Colombier 			continue;
4709ef1f84bSDavid du Colombier 		updatecpu(p);
4719ef1f84bSDavid du Colombier 		npri = reprioritize(p);
4729ef1f84bSDavid du Colombier 		if(npri != pri){
4739ef1f84bSDavid du Colombier 			s = splhi();
4749ef1f84bSDavid du Colombier 			p = dequeueproc(rq, p);
4759ef1f84bSDavid du Colombier 			if(p)
4769ef1f84bSDavid du Colombier 				queueproc(&runq[npri], p);
4779ef1f84bSDavid du Colombier 			splx(s);
4789ef1f84bSDavid du Colombier 			goto another;
4799ef1f84bSDavid du Colombier 		}
4809ef1f84bSDavid du Colombier 	}
4819ef1f84bSDavid du Colombier }
4829ef1f84bSDavid du Colombier 
4839ef1f84bSDavid du Colombier 
4849ef1f84bSDavid du Colombier /*
4859ef1f84bSDavid du Colombier  *  pick a process to run
4869ef1f84bSDavid du Colombier  */
4879ef1f84bSDavid du Colombier Proc*
runproc(void)4889ef1f84bSDavid du Colombier runproc(void)
4899ef1f84bSDavid du Colombier {
4909ef1f84bSDavid du Colombier 	Schedq *rq;
4919ef1f84bSDavid du Colombier 	Proc *p;
4929ef1f84bSDavid du Colombier 	ulong start, now;
4939ef1f84bSDavid du Colombier 	int i;
494d46407a3SDavid du Colombier 	void (*pt)(Proc*, int, vlong, vlong);
4959ef1f84bSDavid du Colombier 
4969ef1f84bSDavid du Colombier 	start = perfticks();
4979ef1f84bSDavid du Colombier 
4989ef1f84bSDavid du Colombier 	/* cooperative scheduling until the clock ticks */
4999ef1f84bSDavid du Colombier 	if((p=m->readied) && p->mach==0 && p->state==Ready
5009ef1f84bSDavid du Colombier 	&& (p->wired == nil || p->wired == m)
5019ef1f84bSDavid du Colombier 	&& runq[Nrq-1].head == nil && runq[Nrq-2].head == nil){
5029ef1f84bSDavid du Colombier 		skipscheds++;
5039ef1f84bSDavid du Colombier 		rq = &runq[p->priority];
5049ef1f84bSDavid du Colombier 		goto found;
5059ef1f84bSDavid du Colombier 	}
5069ef1f84bSDavid du Colombier 
5079ef1f84bSDavid du Colombier 	preempts++;
5089ef1f84bSDavid du Colombier 
5099ef1f84bSDavid du Colombier loop:
5109ef1f84bSDavid du Colombier 	/*
5119ef1f84bSDavid du Colombier 	 *  find a process that last ran on this processor (affinity),
5129ef1f84bSDavid du Colombier 	 *  or one that hasn't moved in a while (load balancing).  Every
5139ef1f84bSDavid du Colombier 	 *  time around the loop affinity goes down.
5149ef1f84bSDavid du Colombier 	 */
5159ef1f84bSDavid du Colombier 	spllo();
5169ef1f84bSDavid du Colombier 	for(i = 0;; i++){
5179ef1f84bSDavid du Colombier 		/*
5189ef1f84bSDavid du Colombier 		 *  find the highest priority target process that this
5199ef1f84bSDavid du Colombier 		 *  processor can run given affinity constraints.
5209ef1f84bSDavid du Colombier 		 *
5219ef1f84bSDavid du Colombier 		 */
5229ef1f84bSDavid du Colombier 		for(rq = &runq[Nrq-1]; rq >= runq; rq--){
5239ef1f84bSDavid du Colombier 			for(p = rq->head; p; p = p->rnext){
5249ef1f84bSDavid du Colombier 				if(p->mp == nil || p->mp == m
5259ef1f84bSDavid du Colombier 				|| (!p->wired && i > 0))
5269ef1f84bSDavid du Colombier 					goto found;
5279ef1f84bSDavid du Colombier 			}
5289ef1f84bSDavid du Colombier 		}
5299ef1f84bSDavid du Colombier 
5309ef1f84bSDavid du Colombier 		/* waste time or halt the CPU */
5319ef1f84bSDavid du Colombier 		idlehands();
5329ef1f84bSDavid du Colombier 
5339ef1f84bSDavid du Colombier 		/* remember how much time we're here */
5349ef1f84bSDavid du Colombier 		now = perfticks();
5359ef1f84bSDavid du Colombier 		m->perf.inidle += now-start;
5369ef1f84bSDavid du Colombier 		start = now;
5379ef1f84bSDavid du Colombier 	}
5389ef1f84bSDavid du Colombier 
5399ef1f84bSDavid du Colombier found:
5409ef1f84bSDavid du Colombier 	splhi();
5419ef1f84bSDavid du Colombier 	p = dequeueproc(rq, p);
5429ef1f84bSDavid du Colombier 	if(p == nil)
5439ef1f84bSDavid du Colombier 		goto loop;
5449ef1f84bSDavid du Colombier 
5459ef1f84bSDavid du Colombier 	p->state = Scheding;
5469ef1f84bSDavid du Colombier 	p->mp = m;
5479ef1f84bSDavid du Colombier 
5489ef1f84bSDavid du Colombier 	if(edflock(p)){
5499ef1f84bSDavid du Colombier 		edfrun(p, rq == &runq[PriEdf]);	/* start deadline timer and do admin */
5509ef1f84bSDavid du Colombier 		edfunlock();
5519ef1f84bSDavid du Colombier 	}
5529ef1f84bSDavid du Colombier 	pt = proctrace;
5539ef1f84bSDavid du Colombier 	if(pt)
554d46407a3SDavid du Colombier 		pt(p, SRun, 0, 0);
5559ef1f84bSDavid du Colombier 	return p;
5569ef1f84bSDavid du Colombier }
5579ef1f84bSDavid du Colombier 
5589ef1f84bSDavid du Colombier int
canpage(Proc * p)5599ef1f84bSDavid du Colombier canpage(Proc *p)
5609ef1f84bSDavid du Colombier {
5619ef1f84bSDavid du Colombier 	int ok;
5629ef1f84bSDavid du Colombier 
5639ef1f84bSDavid du Colombier 	splhi();
5649ef1f84bSDavid du Colombier 	lock(runq);
5659ef1f84bSDavid du Colombier 	/* Only reliable way to see if we are Running */
5669ef1f84bSDavid du Colombier 	if(p->mach == 0) {
5679ef1f84bSDavid du Colombier 		p->newtlb = 1;
5689ef1f84bSDavid du Colombier 		ok = 1;
5699ef1f84bSDavid du Colombier 	}
5709ef1f84bSDavid du Colombier 	else
5719ef1f84bSDavid du Colombier 		ok = 0;
5729ef1f84bSDavid du Colombier 	unlock(runq);
5739ef1f84bSDavid du Colombier 	spllo();
5749ef1f84bSDavid du Colombier 
5759ef1f84bSDavid du Colombier 	return ok;
5769ef1f84bSDavid du Colombier }
5779ef1f84bSDavid du Colombier 
5789ef1f84bSDavid du Colombier Proc*
newproc(void)5799ef1f84bSDavid du Colombier newproc(void)
5809ef1f84bSDavid du Colombier {
5819ef1f84bSDavid du Colombier 	Proc *p;
5829ef1f84bSDavid du Colombier 
5839ef1f84bSDavid du Colombier 	p = psalloc();
5849ef1f84bSDavid du Colombier 
5859ef1f84bSDavid du Colombier 	p->state = Scheding;
5869ef1f84bSDavid du Colombier 	p->psstate = "New";
587*4498a243SDavid du Colombier 	p->mach = nil;
588*4498a243SDavid du Colombier 	p->qnext = nil;
5899ef1f84bSDavid du Colombier 	p->nchild = 0;
5909ef1f84bSDavid du Colombier 	p->nwait = 0;
591*4498a243SDavid du Colombier 	p->waitq = nil;
592*4498a243SDavid du Colombier 	p->parent = nil;
593*4498a243SDavid du Colombier 	p->pgrp = nil;
594*4498a243SDavid du Colombier 	p->egrp = nil;
595*4498a243SDavid du Colombier 	p->fgrp = nil;
596*4498a243SDavid du Colombier 	p->rgrp = nil;
5979ef1f84bSDavid du Colombier 	p->pdbg = 0;
5989ef1f84bSDavid du Colombier 	p->kp = 0;
5999ef1f84bSDavid du Colombier 	if(up != nil && up->procctl == Proc_tracesyscall)
6009ef1f84bSDavid du Colombier 		p->procctl = Proc_tracesyscall;
6019ef1f84bSDavid du Colombier 	else
6029ef1f84bSDavid du Colombier 		p->procctl = 0;
6039ef1f84bSDavid du Colombier 	p->syscalltrace = nil;
6049ef1f84bSDavid du Colombier 	p->notepending = 0;
605*4498a243SDavid du Colombier 	p->ureg = nil;
6069ef1f84bSDavid du Colombier 	p->privatemem = 0;
6079ef1f84bSDavid du Colombier 	p->errstr = p->errbuf0;
6089ef1f84bSDavid du Colombier 	p->syserrstr = p->errbuf1;
6099ef1f84bSDavid du Colombier 	p->errbuf0[0] = '\0';
6109ef1f84bSDavid du Colombier 	p->errbuf1[0] = '\0';
6119ef1f84bSDavid du Colombier 	p->nlocks = 0;
6129ef1f84bSDavid du Colombier 	p->delaysched = 0;
6139ef1f84bSDavid du Colombier 	p->trace = 0;
6149ef1f84bSDavid du Colombier 	kstrdup(&p->user, "*nouser");
6159ef1f84bSDavid du Colombier 	kstrdup(&p->text, "*notext");
6169ef1f84bSDavid du Colombier 	kstrdup(&p->args, "");
6179ef1f84bSDavid du Colombier 	p->nargs = 0;
6189ef1f84bSDavid du Colombier 	p->setargs = 0;
6199ef1f84bSDavid du Colombier 	memset(p->seg, 0, sizeof p->seg);
6209ef1f84bSDavid du Colombier 	p->pid = incref(&pidalloc);
6219ef1f84bSDavid du Colombier 	pshash(p);
6229ef1f84bSDavid du Colombier 	p->noteid = incref(&noteidalloc);
6239ef1f84bSDavid du Colombier 	if(p->pid <= 0 || p->noteid <= 0)
6249ef1f84bSDavid du Colombier 		panic("pidalloc");
625*4498a243SDavid du Colombier 	if(p->kstack == nil)
6269ef1f84bSDavid du Colombier 		p->kstack = smalloc(KSTACK);
6279ef1f84bSDavid du Colombier 
6289ef1f84bSDavid du Colombier 	/* sched params */
629*4498a243SDavid du Colombier 	p->mp = nil;
630*4498a243SDavid du Colombier 	p->wired = nil;
6319ef1f84bSDavid du Colombier 	procpriority(p, PriNormal, 0);
6329ef1f84bSDavid du Colombier 	p->cpu = 0;
6339ef1f84bSDavid du Colombier 	p->lastupdate = sys->ticks*Scaling;
6349ef1f84bSDavid du Colombier 	p->edf = nil;
6359ef1f84bSDavid du Colombier 
6369ef1f84bSDavid du Colombier 	return p;
6379ef1f84bSDavid du Colombier }
6389ef1f84bSDavid du Colombier 
6399ef1f84bSDavid du Colombier /*
6409ef1f84bSDavid du Colombier  * wire this proc to a machine
6419ef1f84bSDavid du Colombier  */
6429ef1f84bSDavid du Colombier void
procwired(Proc * p,int bm)6439ef1f84bSDavid du Colombier procwired(Proc *p, int bm)
6449ef1f84bSDavid du Colombier {
6459ef1f84bSDavid du Colombier 	Proc *pp;
6469ef1f84bSDavid du Colombier 	int i;
6479ef1f84bSDavid du Colombier 	char nwired[MACHMAX];
6489ef1f84bSDavid du Colombier 	Mach *wm, *mp;
6499ef1f84bSDavid du Colombier 
6509ef1f84bSDavid du Colombier 	if(bm < 0){
6519ef1f84bSDavid du Colombier 		/* pick a machine to wire to */
6529ef1f84bSDavid du Colombier 		memset(nwired, 0, sizeof(nwired));
653*4498a243SDavid du Colombier 		p->wired = nil;
6549ef1f84bSDavid du Colombier 		for(i=0; (pp = psincref(i)) != nil; i++){
6559ef1f84bSDavid du Colombier 			wm = pp->wired;
6569ef1f84bSDavid du Colombier 			if(wm && pp->pid)
6579ef1f84bSDavid du Colombier 				nwired[wm->machno]++;
6589ef1f84bSDavid du Colombier 			psdecref(pp);
6599ef1f84bSDavid du Colombier 		}
6609ef1f84bSDavid du Colombier 		bm = 0;
6619ef1f84bSDavid du Colombier 		for(i=0; i<MACHMAX; i++){
6629ef1f84bSDavid du Colombier 			if((mp = sys->machptr[i]) == nil || !mp->online)
6639ef1f84bSDavid du Colombier 				continue;
6649ef1f84bSDavid du Colombier 			if(nwired[i] < nwired[bm])
6659ef1f84bSDavid du Colombier 				bm = i;
6669ef1f84bSDavid du Colombier 		}
6679ef1f84bSDavid du Colombier 	} else {
6689ef1f84bSDavid du Colombier 		/* use the virtual machine requested */
6699ef1f84bSDavid du Colombier 		bm = bm % MACHMAX;
6709ef1f84bSDavid du Colombier 	}
6719ef1f84bSDavid du Colombier 
6729ef1f84bSDavid du Colombier 	p->wired = sys->machptr[bm];
6739ef1f84bSDavid du Colombier 	p->mp = p->wired;
6749ef1f84bSDavid du Colombier }
6759ef1f84bSDavid du Colombier 
6769ef1f84bSDavid du Colombier void
procpriority(Proc * p,int pri,int fixed)6779ef1f84bSDavid du Colombier procpriority(Proc *p, int pri, int fixed)
6789ef1f84bSDavid du Colombier {
6799ef1f84bSDavid du Colombier 	if(pri >= Npriq)
6809ef1f84bSDavid du Colombier 		pri = Npriq - 1;
6819ef1f84bSDavid du Colombier 	else if(pri < 0)
6829ef1f84bSDavid du Colombier 		pri = 0;
6839ef1f84bSDavid du Colombier 	p->basepri = pri;
6849ef1f84bSDavid du Colombier 	p->priority = pri;
6859ef1f84bSDavid du Colombier 	if(fixed){
6869ef1f84bSDavid du Colombier 		p->fixedpri = 1;
6879ef1f84bSDavid du Colombier 	} else {
6889ef1f84bSDavid du Colombier 		p->fixedpri = 0;
6899ef1f84bSDavid du Colombier 	}
6909ef1f84bSDavid du Colombier }
6919ef1f84bSDavid du Colombier 
6929ef1f84bSDavid du Colombier /*
6939ef1f84bSDavid du Colombier  *  sleep if a condition is not true.  Another process will
6949ef1f84bSDavid du Colombier  *  awaken us after it sets the condition.  When we awaken
6959ef1f84bSDavid du Colombier  *  the condition may no longer be true.
6969ef1f84bSDavid du Colombier  *
6979ef1f84bSDavid du Colombier  *  we lock both the process and the rendezvous to keep r->p
6989ef1f84bSDavid du Colombier  *  and p->r synchronized.
6999ef1f84bSDavid du Colombier  */
7009ef1f84bSDavid du Colombier void
sleep(Rendez * r,int (* f)(void *),void * arg)7019ef1f84bSDavid du Colombier sleep(Rendez *r, int (*f)(void*), void *arg)
7029ef1f84bSDavid du Colombier {
7039ef1f84bSDavid du Colombier 	Mreg s;
704d46407a3SDavid du Colombier 	void (*pt)(Proc*, int, vlong, vlong);
7059ef1f84bSDavid du Colombier 
7069ef1f84bSDavid du Colombier 	s = splhi();
7079ef1f84bSDavid du Colombier 
7089ef1f84bSDavid du Colombier 	if(up->nlocks)
7099ef1f84bSDavid du Colombier 		print("process %d sleeps with %d locks held, last lock %#p locked at pc %#p, sleep called from %#p\n",
7109ef1f84bSDavid du Colombier 			up->pid, up->nlocks, up->lastlock, up->lastlock->pc, getcallerpc(&r));
7119ef1f84bSDavid du Colombier 	lock(r);
7129ef1f84bSDavid du Colombier 	lock(&up->rlock);
7139ef1f84bSDavid du Colombier 	if(r->p){
7149ef1f84bSDavid du Colombier 		print("double sleep called from %#p, %d %d\n",
7159ef1f84bSDavid du Colombier 			getcallerpc(&r), r->p->pid, up->pid);
7169ef1f84bSDavid du Colombier 		dumpstack();
7179ef1f84bSDavid du Colombier 	}
7189ef1f84bSDavid du Colombier 
7199ef1f84bSDavid du Colombier 	/*
7209ef1f84bSDavid du Colombier 	 *  Wakeup only knows there may be something to do by testing
7219ef1f84bSDavid du Colombier 	 *  r->p in order to get something to lock on.
7229ef1f84bSDavid du Colombier 	 *  Flush that information out to memory in case the sleep is
7239ef1f84bSDavid du Colombier 	 *  committed.
7249ef1f84bSDavid du Colombier 	 */
7259ef1f84bSDavid du Colombier 	r->p = up;
7269ef1f84bSDavid du Colombier 
7279ef1f84bSDavid du Colombier 	if((*f)(arg) || up->notepending){
7289ef1f84bSDavid du Colombier 		/*
7299ef1f84bSDavid du Colombier 		 *  if condition happened or a note is pending
7309ef1f84bSDavid du Colombier 		 *  never mind
7319ef1f84bSDavid du Colombier 		 */
7329ef1f84bSDavid du Colombier 		r->p = nil;
7339ef1f84bSDavid du Colombier 		unlock(&up->rlock);
7349ef1f84bSDavid du Colombier 		unlock(r);
7359ef1f84bSDavid du Colombier 	} else {
7369ef1f84bSDavid du Colombier 		/*
7379ef1f84bSDavid du Colombier 		 *  now we are committed to
7389ef1f84bSDavid du Colombier 		 *  change state and call scheduler
7399ef1f84bSDavid du Colombier 		 */
7409ef1f84bSDavid du Colombier 		pt = proctrace;
7419ef1f84bSDavid du Colombier 		if(pt)
742d46407a3SDavid du Colombier 			pt(up, SSleep, 0, 0);
7439ef1f84bSDavid du Colombier 		up->state = Wakeme;
7449ef1f84bSDavid du Colombier 		up->r = r;
7459ef1f84bSDavid du Colombier 
7469ef1f84bSDavid du Colombier 		/* statistics */
7479ef1f84bSDavid du Colombier 		m->cs++;
7489ef1f84bSDavid du Colombier 
7499ef1f84bSDavid du Colombier 		procsave(up);
7509ef1f84bSDavid du Colombier 		if(setlabel(&up->sched)) {
7519ef1f84bSDavid du Colombier 			/*
7529ef1f84bSDavid du Colombier 			 *  here when the process is awakened
7539ef1f84bSDavid du Colombier 			 */
7549ef1f84bSDavid du Colombier 			procrestore(up);
7559ef1f84bSDavid du Colombier 			spllo();
7569ef1f84bSDavid du Colombier 		} else {
7579ef1f84bSDavid du Colombier 			/*
7589ef1f84bSDavid du Colombier 			 *  here to go to sleep (i.e. stop Running)
7599ef1f84bSDavid du Colombier 			 */
7609ef1f84bSDavid du Colombier 			unlock(&up->rlock);
7619ef1f84bSDavid du Colombier 			unlock(r);
7629ef1f84bSDavid du Colombier 			gotolabel(&m->sched);
7639ef1f84bSDavid du Colombier 		}
7649ef1f84bSDavid du Colombier 	}
7659ef1f84bSDavid du Colombier 
7669ef1f84bSDavid du Colombier 	if(up->notepending) {
7679ef1f84bSDavid du Colombier 		up->notepending = 0;
7689ef1f84bSDavid du Colombier 		splx(s);
7699ef1f84bSDavid du Colombier 		if(up->procctl == Proc_exitme && up->closingfgrp)
7709ef1f84bSDavid du Colombier 			forceclosefgrp();
7719ef1f84bSDavid du Colombier 		error(Eintr);
7729ef1f84bSDavid du Colombier 	}
7739ef1f84bSDavid du Colombier 
7749ef1f84bSDavid du Colombier 	splx(s);
7759ef1f84bSDavid du Colombier }
7769ef1f84bSDavid du Colombier 
7779ef1f84bSDavid du Colombier static int
tfn(void * arg)7789ef1f84bSDavid du Colombier tfn(void *arg)
7799ef1f84bSDavid du Colombier {
7809ef1f84bSDavid du Colombier 	return up->trend == nil || up->tfn(arg);
7819ef1f84bSDavid du Colombier }
7829ef1f84bSDavid du Colombier 
7839ef1f84bSDavid du Colombier void
twakeup(Ureg *,Timer * t)7849ef1f84bSDavid du Colombier twakeup(Ureg*, Timer *t)
7859ef1f84bSDavid du Colombier {
7869ef1f84bSDavid du Colombier 	Proc *p;
7879ef1f84bSDavid du Colombier 	Rendez *trend;
7889ef1f84bSDavid du Colombier 
7899ef1f84bSDavid du Colombier 	p = t->ta;
7909ef1f84bSDavid du Colombier 	trend = p->trend;
7919ef1f84bSDavid du Colombier 	p->trend = 0;
7929ef1f84bSDavid du Colombier 	if(trend)
7939ef1f84bSDavid du Colombier 		wakeup(trend);
7949ef1f84bSDavid du Colombier }
7959ef1f84bSDavid du Colombier 
7969ef1f84bSDavid du Colombier void
tsleep(Rendez * r,int (* fn)(void *),void * arg,long ms)7979ef1f84bSDavid du Colombier tsleep(Rendez *r, int (*fn)(void*), void *arg, long ms)
7989ef1f84bSDavid du Colombier {
7999ef1f84bSDavid du Colombier 	if (up->tt){
8009ef1f84bSDavid du Colombier 		print("tsleep: timer active: mode %d, tf %#p\n",
8019ef1f84bSDavid du Colombier 			up->tmode, up->tf);
8029ef1f84bSDavid du Colombier 		timerdel(up);
8039ef1f84bSDavid du Colombier 	}
8049ef1f84bSDavid du Colombier 	up->tns = MS2NS(ms);
8059ef1f84bSDavid du Colombier 	up->tf = twakeup;
8069ef1f84bSDavid du Colombier 	up->tmode = Trelative;
8079ef1f84bSDavid du Colombier 	up->ta = up;
8089ef1f84bSDavid du Colombier 	up->trend = r;
8099ef1f84bSDavid du Colombier 	up->tfn = fn;
8109ef1f84bSDavid du Colombier 	timeradd(up);
8119ef1f84bSDavid du Colombier 
8129ef1f84bSDavid du Colombier 	if(waserror()){
8139ef1f84bSDavid du Colombier 		timerdel(up);
8149ef1f84bSDavid du Colombier 		nexterror();
8159ef1f84bSDavid du Colombier 	}
8169ef1f84bSDavid du Colombier 	sleep(r, tfn, arg);
8179ef1f84bSDavid du Colombier 	if (up->tt)
8189ef1f84bSDavid du Colombier 		timerdel(up);
8199ef1f84bSDavid du Colombier 	up->twhen = 0;
8209ef1f84bSDavid du Colombier 	poperror();
8219ef1f84bSDavid du Colombier }
8229ef1f84bSDavid du Colombier 
8239ef1f84bSDavid du Colombier /*
8249ef1f84bSDavid du Colombier  *  Expects that only one process can call wakeup for any given Rendez.
8259ef1f84bSDavid du Colombier  *  We hold both locks to ensure that r->p and p->r remain consistent.
8269ef1f84bSDavid du Colombier  *  Richard Miller has a better solution that doesn't require both to
8279ef1f84bSDavid du Colombier  *  be held simultaneously, but I'm a paranoid - presotto.
8289ef1f84bSDavid du Colombier  */
8299ef1f84bSDavid du Colombier Proc*
wakeup(Rendez * r)8309ef1f84bSDavid du Colombier wakeup(Rendez *r)
8319ef1f84bSDavid du Colombier {
8329ef1f84bSDavid du Colombier 	Mreg s;
8339ef1f84bSDavid du Colombier 	Proc *p;
8349ef1f84bSDavid du Colombier 
8359ef1f84bSDavid du Colombier 	s = splhi();
8369ef1f84bSDavid du Colombier 
8379ef1f84bSDavid du Colombier 	lock(r);
8389ef1f84bSDavid du Colombier 	p = r->p;
8399ef1f84bSDavid du Colombier 
8409ef1f84bSDavid du Colombier 	if(p != nil){
8419ef1f84bSDavid du Colombier 		lock(&p->rlock);
8429ef1f84bSDavid du Colombier 		if(p->state != Wakeme || p->r != r)
8439ef1f84bSDavid du Colombier 			panic("wakeup: state");
8449ef1f84bSDavid du Colombier 		r->p = nil;
8459ef1f84bSDavid du Colombier 		p->r = nil;
8469ef1f84bSDavid du Colombier 		ready(p);
8479ef1f84bSDavid du Colombier 		unlock(&p->rlock);
8489ef1f84bSDavid du Colombier 	}
8499ef1f84bSDavid du Colombier 	unlock(r);
8509ef1f84bSDavid du Colombier 
8519ef1f84bSDavid du Colombier 	splx(s);
8529ef1f84bSDavid du Colombier 
8539ef1f84bSDavid du Colombier 	return p;
8549ef1f84bSDavid du Colombier }
8559ef1f84bSDavid du Colombier 
8569ef1f84bSDavid du Colombier /*
8579ef1f84bSDavid du Colombier  *  if waking a sleeping process, this routine must hold both
8589ef1f84bSDavid du Colombier  *  p->rlock and r->lock.  However, it can't know them in
8599ef1f84bSDavid du Colombier  *  the same order as wakeup causing a possible lock ordering
8609ef1f84bSDavid du Colombier  *  deadlock.  We break the deadlock by giving up the p->rlock
8619ef1f84bSDavid du Colombier  *  lock if we can't get the r->lock and retrying.
8629ef1f84bSDavid du Colombier  */
8639ef1f84bSDavid du Colombier int
postnote(Proc * p,int dolock,char * n,int flag)8649ef1f84bSDavid du Colombier postnote(Proc *p, int dolock, char *n, int flag)
8659ef1f84bSDavid du Colombier {
8669ef1f84bSDavid du Colombier 	Mreg s;
8679ef1f84bSDavid du Colombier 	int ret;
8689ef1f84bSDavid du Colombier 	Rendez *r;
8699ef1f84bSDavid du Colombier 	Proc *d, **l;
8709ef1f84bSDavid du Colombier 
8719ef1f84bSDavid du Colombier 	if(dolock && m->ilockdepth != 0)
8729ef1f84bSDavid du Colombier 		panic("postnote: caller %#p: ilockdepth %d note %s",
8739ef1f84bSDavid du Colombier 			getcallerpc(&p), m->ilockdepth, n);
8749ef1f84bSDavid du Colombier 	if(dolock)
8759ef1f84bSDavid du Colombier 		qlock(&p->debug);
8769ef1f84bSDavid du Colombier 
877*4498a243SDavid du Colombier 	if(flag != NUser && (p->notify == nil || p->notified))
8789ef1f84bSDavid du Colombier 		p->nnote = 0;
8799ef1f84bSDavid du Colombier 
8809ef1f84bSDavid du Colombier 	ret = 0;
8819ef1f84bSDavid du Colombier 	if(p->nnote < NNOTE) {
8829ef1f84bSDavid du Colombier 		strcpy(p->note[p->nnote].msg, n);
8839ef1f84bSDavid du Colombier 		p->note[p->nnote++].flag = flag;
8849ef1f84bSDavid du Colombier 		ret = 1;
8859ef1f84bSDavid du Colombier 	}
8869ef1f84bSDavid du Colombier 	p->notepending = 1;
8879ef1f84bSDavid du Colombier 	if(dolock)
8889ef1f84bSDavid du Colombier 		qunlock(&p->debug);
8899ef1f84bSDavid du Colombier 
8909ef1f84bSDavid du Colombier 	/* this loop is to avoid lock ordering problems. */
8919ef1f84bSDavid du Colombier 	for(;;){
8929ef1f84bSDavid du Colombier 		s = splhi();
8939ef1f84bSDavid du Colombier 		lock(&p->rlock);
8949ef1f84bSDavid du Colombier 		r = p->r;
8959ef1f84bSDavid du Colombier 
8969ef1f84bSDavid du Colombier 		/* waiting for a wakeup? */
8979ef1f84bSDavid du Colombier 		if(r == nil)
8989ef1f84bSDavid du Colombier 			break;	/* no */
8999ef1f84bSDavid du Colombier 
9009ef1f84bSDavid du Colombier 		/* try for the second lock */
9019ef1f84bSDavid du Colombier 		if(canlock(r)){
9029ef1f84bSDavid du Colombier 			if(p->state != Wakeme || r->p != p)
9039ef1f84bSDavid du Colombier 				panic("postnote: state %d %d %d", r->p != p, p->r != r, p->state);
9049ef1f84bSDavid du Colombier 			p->r = nil;
9059ef1f84bSDavid du Colombier 			r->p = nil;
9069ef1f84bSDavid du Colombier 			ready(p);
9079ef1f84bSDavid du Colombier 			unlock(r);
9089ef1f84bSDavid du Colombier 			break;
9099ef1f84bSDavid du Colombier 		}
9109ef1f84bSDavid du Colombier 
9119ef1f84bSDavid du Colombier 		/* give other process time to get out of critical section and try again */
9129ef1f84bSDavid du Colombier 		unlock(&p->rlock);
9139ef1f84bSDavid du Colombier 		splx(s);
9149ef1f84bSDavid du Colombier 		sched();
9159ef1f84bSDavid du Colombier 	}
9169ef1f84bSDavid du Colombier 	unlock(&p->rlock);
9179ef1f84bSDavid du Colombier 	splx(s);
9189ef1f84bSDavid du Colombier 
9199ef1f84bSDavid du Colombier 	if(p->state != Rendezvous)
9209ef1f84bSDavid du Colombier 		return ret;
9219ef1f84bSDavid du Colombier 
9229ef1f84bSDavid du Colombier 	/* Try and pull out of a rendezvous */
9239ef1f84bSDavid du Colombier 	lock(p->rgrp);
9249ef1f84bSDavid du Colombier 	if(p->state == Rendezvous) {
9259ef1f84bSDavid du Colombier 		p->rendval = ~0;
9269ef1f84bSDavid du Colombier 		l = &REND(p->rgrp, p->rendtag);
9279ef1f84bSDavid du Colombier 		for(d = *l; d; d = d->rendhash) {
9289ef1f84bSDavid du Colombier 			if(d == p) {
9299ef1f84bSDavid du Colombier 				*l = p->rendhash;
9309ef1f84bSDavid du Colombier 				break;
9319ef1f84bSDavid du Colombier 			}
9329ef1f84bSDavid du Colombier 			l = &d->rendhash;
9339ef1f84bSDavid du Colombier 		}
9349ef1f84bSDavid du Colombier 		ready(p);
9359ef1f84bSDavid du Colombier 	}
9369ef1f84bSDavid du Colombier 	unlock(p->rgrp);
9379ef1f84bSDavid du Colombier 	return ret;
9389ef1f84bSDavid du Colombier }
9399ef1f84bSDavid du Colombier 
9409ef1f84bSDavid du Colombier /*
9419ef1f84bSDavid du Colombier  * weird thing: keep at most NBROKEN around
9429ef1f84bSDavid du Colombier  */
9439ef1f84bSDavid du Colombier #define	NBROKEN 4
9449ef1f84bSDavid du Colombier struct
9459ef1f84bSDavid du Colombier {
9469ef1f84bSDavid du Colombier 	QLock;
9479ef1f84bSDavid du Colombier 	int	n;
9489ef1f84bSDavid du Colombier 	Proc	*p[NBROKEN];
9499ef1f84bSDavid du Colombier }broken;
9509ef1f84bSDavid du Colombier 
9519ef1f84bSDavid du Colombier void
addbroken(Proc * p)9529ef1f84bSDavid du Colombier addbroken(Proc *p)
9539ef1f84bSDavid du Colombier {
9549ef1f84bSDavid du Colombier 	qlock(&broken);
9559ef1f84bSDavid du Colombier 	if(broken.n == NBROKEN) {
9569ef1f84bSDavid du Colombier 		ready(broken.p[0]);
9579ef1f84bSDavid du Colombier 		memmove(&broken.p[0], &broken.p[1], sizeof(Proc*)*(NBROKEN-1));
9589ef1f84bSDavid du Colombier 		--broken.n;
9599ef1f84bSDavid du Colombier 	}
9609ef1f84bSDavid du Colombier 	broken.p[broken.n++] = p;
9619ef1f84bSDavid du Colombier 	qunlock(&broken);
9629ef1f84bSDavid du Colombier 
9639ef1f84bSDavid du Colombier 	edfstop(up);
9649ef1f84bSDavid du Colombier 	p->state = Broken;
9659ef1f84bSDavid du Colombier 	p->psstate = 0;
9669ef1f84bSDavid du Colombier 	sched();
9679ef1f84bSDavid du Colombier }
9689ef1f84bSDavid du Colombier 
9699ef1f84bSDavid du Colombier void
unbreak(Proc * p)9709ef1f84bSDavid du Colombier unbreak(Proc *p)
9719ef1f84bSDavid du Colombier {
9729ef1f84bSDavid du Colombier 	int b;
9739ef1f84bSDavid du Colombier 
9749ef1f84bSDavid du Colombier 	qlock(&broken);
9759ef1f84bSDavid du Colombier 	for(b=0; b < broken.n; b++)
9769ef1f84bSDavid du Colombier 		if(broken.p[b] == p) {
9779ef1f84bSDavid du Colombier 			broken.n--;
9789ef1f84bSDavid du Colombier 			memmove(&broken.p[b], &broken.p[b+1],
9799ef1f84bSDavid du Colombier 					sizeof(Proc*)*(NBROKEN-(b+1)));
9809ef1f84bSDavid du Colombier 			ready(p);
9819ef1f84bSDavid du Colombier 			break;
9829ef1f84bSDavid du Colombier 		}
9839ef1f84bSDavid du Colombier 	qunlock(&broken);
9849ef1f84bSDavid du Colombier }
9859ef1f84bSDavid du Colombier 
9869ef1f84bSDavid du Colombier int
freebroken(void)9879ef1f84bSDavid du Colombier freebroken(void)
9889ef1f84bSDavid du Colombier {
9899ef1f84bSDavid du Colombier 	int i, n;
9909ef1f84bSDavid du Colombier 
9919ef1f84bSDavid du Colombier 	qlock(&broken);
9929ef1f84bSDavid du Colombier 	n = broken.n;
9939ef1f84bSDavid du Colombier 	for(i=0; i<n; i++) {
9949ef1f84bSDavid du Colombier 		ready(broken.p[i]);
9959ef1f84bSDavid du Colombier 		broken.p[i] = 0;
9969ef1f84bSDavid du Colombier 	}
9979ef1f84bSDavid du Colombier 	broken.n = 0;
9989ef1f84bSDavid du Colombier 	qunlock(&broken);
9999ef1f84bSDavid du Colombier 	return n;
10009ef1f84bSDavid du Colombier }
10019ef1f84bSDavid du Colombier 
10029ef1f84bSDavid du Colombier void
pexit(char * exitstr,int freemem)10039ef1f84bSDavid du Colombier pexit(char *exitstr, int freemem)
10049ef1f84bSDavid du Colombier {
10059ef1f84bSDavid du Colombier 	Proc *p;
10069ef1f84bSDavid du Colombier 	Segment **s, **es;
10079ef1f84bSDavid du Colombier 	long utime, stime;
10089ef1f84bSDavid du Colombier 	Waitq *wq, *f, *next;
10099ef1f84bSDavid du Colombier 	Fgrp *fgrp;
10109ef1f84bSDavid du Colombier 	Egrp *egrp;
10119ef1f84bSDavid du Colombier 	Rgrp *rgrp;
10129ef1f84bSDavid du Colombier 	Pgrp *pgrp;
10139ef1f84bSDavid du Colombier 	Chan *dot;
1014d46407a3SDavid du Colombier 	void (*pt)(Proc*, int, vlong, vlong);
10159ef1f84bSDavid du Colombier 
10169ef1f84bSDavid du Colombier 	if(up->syscalltrace != nil)
10179ef1f84bSDavid du Colombier 		free(up->syscalltrace);
10189ef1f84bSDavid du Colombier 	up->syscalltrace = nil;
10199ef1f84bSDavid du Colombier 	up->alarm = 0;
10209ef1f84bSDavid du Colombier 	if (up->tt)
10219ef1f84bSDavid du Colombier 		timerdel(up);
10229ef1f84bSDavid du Colombier 	pt = proctrace;
10239ef1f84bSDavid du Colombier 	if(pt)
1024d46407a3SDavid du Colombier 		pt(up, SDead, 0, 0);
10259ef1f84bSDavid du Colombier 
10269ef1f84bSDavid du Colombier 	/* nil out all the resources under lock (free later) */
10279ef1f84bSDavid du Colombier 	qlock(&up->debug);
10289ef1f84bSDavid du Colombier 	fgrp = up->fgrp;
10299ef1f84bSDavid du Colombier 	up->fgrp = nil;
10309ef1f84bSDavid du Colombier 	egrp = up->egrp;
10319ef1f84bSDavid du Colombier 	up->egrp = nil;
10329ef1f84bSDavid du Colombier 	rgrp = up->rgrp;
10339ef1f84bSDavid du Colombier 	up->rgrp = nil;
10349ef1f84bSDavid du Colombier 	pgrp = up->pgrp;
10359ef1f84bSDavid du Colombier 	up->pgrp = nil;
10369ef1f84bSDavid du Colombier 	dot = up->dot;
10379ef1f84bSDavid du Colombier 	up->dot = nil;
10389ef1f84bSDavid du Colombier 	qunlock(&up->debug);
10399ef1f84bSDavid du Colombier 
10409ef1f84bSDavid du Colombier 	if(fgrp)
10419ef1f84bSDavid du Colombier 		closefgrp(fgrp);
10429ef1f84bSDavid du Colombier 	if(egrp)
10439ef1f84bSDavid du Colombier 		closeegrp(egrp);
10449ef1f84bSDavid du Colombier 	if(rgrp)
10459ef1f84bSDavid du Colombier 		closergrp(rgrp);
10469ef1f84bSDavid du Colombier 	if(dot)
10479ef1f84bSDavid du Colombier 		cclose(dot);
10489ef1f84bSDavid du Colombier 	if(pgrp)
10499ef1f84bSDavid du Colombier 		closepgrp(pgrp);
10509ef1f84bSDavid du Colombier 
10519ef1f84bSDavid du Colombier 	/*
10529ef1f84bSDavid du Colombier 	 * if not a kernel process and have a parent,
10539ef1f84bSDavid du Colombier 	 * do some housekeeping.
10549ef1f84bSDavid du Colombier 	 */
10559ef1f84bSDavid du Colombier 	if(up->kp == 0) {
10569ef1f84bSDavid du Colombier 		p = up->parent;
1057*4498a243SDavid du Colombier 		if(p == nil) {
1058*4498a243SDavid du Colombier 			if(exitstr == nil)
10599ef1f84bSDavid du Colombier 				exitstr = "unknown";
10609ef1f84bSDavid du Colombier 			panic("boot process died: %s", exitstr);
10619ef1f84bSDavid du Colombier 		}
10629ef1f84bSDavid du Colombier 
10639ef1f84bSDavid du Colombier 		while(waserror())
10649ef1f84bSDavid du Colombier 			;
10659ef1f84bSDavid du Colombier 
10669ef1f84bSDavid du Colombier 		wq = smalloc(sizeof(Waitq));
10679ef1f84bSDavid du Colombier 		poperror();
10689ef1f84bSDavid du Colombier 
10699ef1f84bSDavid du Colombier 		wq->w.pid = up->pid;
10709ef1f84bSDavid du Colombier 		utime = up->time[TUser] + up->time[TCUser];
10719ef1f84bSDavid du Colombier 		stime = up->time[TSys] + up->time[TCSys];
10729ef1f84bSDavid du Colombier 		wq->w.time[TUser] = tk2ms(utime);
10739ef1f84bSDavid du Colombier 		wq->w.time[TSys] = tk2ms(stime);
10749ef1f84bSDavid du Colombier 		wq->w.time[TReal] = tk2ms(sys->ticks - up->time[TReal]);
10759ef1f84bSDavid du Colombier 		if(exitstr && exitstr[0])
10769ef1f84bSDavid du Colombier 			snprint(wq->w.msg, sizeof(wq->w.msg), "%s %d: %s",
10779ef1f84bSDavid du Colombier 				up->text, up->pid, exitstr);
10789ef1f84bSDavid du Colombier 		else
10799ef1f84bSDavid du Colombier 			wq->w.msg[0] = '\0';
10809ef1f84bSDavid du Colombier 
10819ef1f84bSDavid du Colombier 		lock(&p->exl);
10829ef1f84bSDavid du Colombier 		/*
10839ef1f84bSDavid du Colombier 		 * Check that parent is still alive.
10849ef1f84bSDavid du Colombier 		 */
10859ef1f84bSDavid du Colombier 		if(p->pid == up->parentpid && p->state != Broken) {
10869ef1f84bSDavid du Colombier 			p->nchild--;
10879ef1f84bSDavid du Colombier 			p->time[TCUser] += utime;
10889ef1f84bSDavid du Colombier 			p->time[TCSys] += stime;
10899ef1f84bSDavid du Colombier 			/*
10909ef1f84bSDavid du Colombier 			 * If there would be more than 128 wait records
10919ef1f84bSDavid du Colombier 			 * processes for my parent, then don't leave a wait
10929ef1f84bSDavid du Colombier 			 * record behind.  This helps prevent badly written
10939ef1f84bSDavid du Colombier 			 * daemon processes from accumulating lots of wait
10949ef1f84bSDavid du Colombier 			 * records.
10959ef1f84bSDavid du Colombier 		 	 */
10969ef1f84bSDavid du Colombier 			if(p->nwait < 128) {
10979ef1f84bSDavid du Colombier 				wq->next = p->waitq;
10989ef1f84bSDavid du Colombier 				p->waitq = wq;
10999ef1f84bSDavid du Colombier 				p->nwait++;
11009ef1f84bSDavid du Colombier 				wq = nil;
11019ef1f84bSDavid du Colombier 				wakeup(&p->waitr);
11029ef1f84bSDavid du Colombier 			}
11039ef1f84bSDavid du Colombier 		}
11049ef1f84bSDavid du Colombier 		unlock(&p->exl);
11059ef1f84bSDavid du Colombier 		if(wq)
11069ef1f84bSDavid du Colombier 			free(wq);
11079ef1f84bSDavid du Colombier 	}
11089ef1f84bSDavid du Colombier 
11099ef1f84bSDavid du Colombier 	if(!freemem)
11109ef1f84bSDavid du Colombier 		addbroken(up);
11119ef1f84bSDavid du Colombier 
11129ef1f84bSDavid du Colombier 	qlock(&up->seglock);
11139ef1f84bSDavid du Colombier 	es = &up->seg[NSEG];
11149ef1f84bSDavid du Colombier 	for(s = up->seg; s < es; s++) {
11159ef1f84bSDavid du Colombier 		if(*s) {
11169ef1f84bSDavid du Colombier 			putseg(*s);
11179ef1f84bSDavid du Colombier 			*s = 0;
11189ef1f84bSDavid du Colombier 		}
11199ef1f84bSDavid du Colombier 	}
11209ef1f84bSDavid du Colombier 	qunlock(&up->seglock);
11219ef1f84bSDavid du Colombier 
11229ef1f84bSDavid du Colombier 	lock(&up->exl);		/* Prevent my children from leaving waits */
11239ef1f84bSDavid du Colombier 	psunhash(up);
11249ef1f84bSDavid du Colombier 	up->pid = 0;
11259ef1f84bSDavid du Colombier 	wakeup(&up->waitr);
11269ef1f84bSDavid du Colombier 	unlock(&up->exl);
11279ef1f84bSDavid du Colombier 
11289ef1f84bSDavid du Colombier 	for(f = up->waitq; f; f = next) {
11299ef1f84bSDavid du Colombier 		next = f->next;
11309ef1f84bSDavid du Colombier 		free(f);
11319ef1f84bSDavid du Colombier 	}
11329ef1f84bSDavid du Colombier 
11339ef1f84bSDavid du Colombier 	/* release debuggers */
11349ef1f84bSDavid du Colombier 	qlock(&up->debug);
11359ef1f84bSDavid du Colombier 	if(up->pdbg) {
11369ef1f84bSDavid du Colombier 		wakeup(&up->pdbg->sleep);
11379ef1f84bSDavid du Colombier 		up->pdbg = 0;
11389ef1f84bSDavid du Colombier 	}
11399ef1f84bSDavid du Colombier 	qunlock(&up->debug);
11409ef1f84bSDavid du Colombier 
11419ef1f84bSDavid du Colombier 	edfstop(up);
1142*4498a243SDavid du Colombier 	if(up->edf != nil){
11439ef1f84bSDavid du Colombier 		free(up->edf);
11449ef1f84bSDavid du Colombier 		up->edf = nil;
11459ef1f84bSDavid du Colombier 	}
11469ef1f84bSDavid du Colombier 
11479ef1f84bSDavid du Colombier 	/* Sched must not loop for these locks */
11489ef1f84bSDavid du Colombier 	lock(&procalloc);
11499ef1f84bSDavid du Colombier 	lock(&palloc);
11509ef1f84bSDavid du Colombier 
11519ef1f84bSDavid du Colombier 	up->state = Moribund;
11529ef1f84bSDavid du Colombier 	sched();
11539ef1f84bSDavid du Colombier 	panic("pexit");
11549ef1f84bSDavid du Colombier }
11559ef1f84bSDavid du Colombier 
11569ef1f84bSDavid du Colombier int
haswaitq(void * x)11579ef1f84bSDavid du Colombier haswaitq(void *x)
11589ef1f84bSDavid du Colombier {
11599ef1f84bSDavid du Colombier 	Proc *p;
11609ef1f84bSDavid du Colombier 
11619ef1f84bSDavid du Colombier 	p = (Proc *)x;
11629ef1f84bSDavid du Colombier 	return p->waitq != 0;
11639ef1f84bSDavid du Colombier }
11649ef1f84bSDavid du Colombier 
11659ef1f84bSDavid du Colombier int
pwait(Waitmsg * w)11669ef1f84bSDavid du Colombier pwait(Waitmsg *w)
11679ef1f84bSDavid du Colombier {
11689ef1f84bSDavid du Colombier 	int cpid;
11699ef1f84bSDavid du Colombier 	Waitq *wq;
11709ef1f84bSDavid du Colombier 
11719ef1f84bSDavid du Colombier 	if(!canqlock(&up->qwaitr))
11729ef1f84bSDavid du Colombier 		error(Einuse);
11739ef1f84bSDavid du Colombier 
11749ef1f84bSDavid du Colombier 	if(waserror()) {
11759ef1f84bSDavid du Colombier 		qunlock(&up->qwaitr);
11769ef1f84bSDavid du Colombier 		nexterror();
11779ef1f84bSDavid du Colombier 	}
11789ef1f84bSDavid du Colombier 
11799ef1f84bSDavid du Colombier 	lock(&up->exl);
1180*4498a243SDavid du Colombier 	if(up->nchild == 0 && up->waitq == nil) {
11819ef1f84bSDavid du Colombier 		unlock(&up->exl);
11829ef1f84bSDavid du Colombier 		error(Enochild);
11839ef1f84bSDavid du Colombier 	}
11849ef1f84bSDavid du Colombier 	unlock(&up->exl);
11859ef1f84bSDavid du Colombier 
11869ef1f84bSDavid du Colombier 	sleep(&up->waitr, haswaitq, up);
11879ef1f84bSDavid du Colombier 
11889ef1f84bSDavid du Colombier 	lock(&up->exl);
11899ef1f84bSDavid du Colombier 	wq = up->waitq;
11909ef1f84bSDavid du Colombier 	up->waitq = wq->next;
11919ef1f84bSDavid du Colombier 	up->nwait--;
11929ef1f84bSDavid du Colombier 	unlock(&up->exl);
11939ef1f84bSDavid du Colombier 
11949ef1f84bSDavid du Colombier 	qunlock(&up->qwaitr);
11959ef1f84bSDavid du Colombier 	poperror();
11969ef1f84bSDavid du Colombier 
11979ef1f84bSDavid du Colombier 	if(w)
11989ef1f84bSDavid du Colombier 		memmove(w, &wq->w, sizeof(Waitmsg));
11999ef1f84bSDavid du Colombier 	cpid = wq->w.pid;
12009ef1f84bSDavid du Colombier 	free(wq);
12019ef1f84bSDavid du Colombier 
12029ef1f84bSDavid du Colombier 	return cpid;
12039ef1f84bSDavid du Colombier }
12049ef1f84bSDavid du Colombier 
12059ef1f84bSDavid du Colombier void
dumpaproc(Proc * p)12069ef1f84bSDavid du Colombier dumpaproc(Proc *p)
12079ef1f84bSDavid du Colombier {
12089ef1f84bSDavid du Colombier 	uintptr bss;
12099ef1f84bSDavid du Colombier 	char *s;
12109ef1f84bSDavid du Colombier 
1211*4498a243SDavid du Colombier 	if(p == nil)
12129ef1f84bSDavid du Colombier 		return;
12139ef1f84bSDavid du Colombier 
12149ef1f84bSDavid du Colombier 	bss = 0;
12159ef1f84bSDavid du Colombier 	if(p->seg[BSEG])
12169ef1f84bSDavid du Colombier 		bss = p->seg[BSEG]->top;
12179ef1f84bSDavid du Colombier 
12189ef1f84bSDavid du Colombier 	s = p->psstate;
1219*4498a243SDavid du Colombier 	if(s == nil)
12209ef1f84bSDavid du Colombier 		s = statename[p->state];
12219ef1f84bSDavid du Colombier 	print("%3d:%10s pc %#p dbgpc %#p  %8s (%s) ut %ld st %ld bss %#p qpc %#p nl %d nd %lud lpc %#p pri %lud\n",
12229ef1f84bSDavid du Colombier 		p->pid, p->text, p->pc, dbgpc(p), s, statename[p->state],
12239ef1f84bSDavid du Colombier 		p->time[0], p->time[1], bss, p->qpc, p->nlocks,
12249ef1f84bSDavid du Colombier 		p->delaysched, p->lastlock ? p->lastlock->pc : 0, p->priority);
12259ef1f84bSDavid du Colombier }
12269ef1f84bSDavid du Colombier 
12279ef1f84bSDavid du Colombier void
procdump(void)12289ef1f84bSDavid du Colombier procdump(void)
12299ef1f84bSDavid du Colombier {
12309ef1f84bSDavid du Colombier 	int i;
12319ef1f84bSDavid du Colombier 	Proc *p;
12329ef1f84bSDavid du Colombier 
1233*4498a243SDavid du Colombier 	if(up != nil)
12349ef1f84bSDavid du Colombier 		print("up %d\n", up->pid);
12359ef1f84bSDavid du Colombier 	else
12369ef1f84bSDavid du Colombier 		print("no current process\n");
12379ef1f84bSDavid du Colombier 	for(i=0; (p = psincref(i)) != nil; i++) {
12389ef1f84bSDavid du Colombier 		if(p->state != Dead)
12399ef1f84bSDavid du Colombier 			dumpaproc(p);
12409ef1f84bSDavid du Colombier 		psdecref(p);
12419ef1f84bSDavid du Colombier 	}
12429ef1f84bSDavid du Colombier }
12439ef1f84bSDavid du Colombier 
12449ef1f84bSDavid du Colombier /*
12459ef1f84bSDavid du Colombier  *  wait till all processes have flushed their mmu
12466cbc2fb8SDavid du Colombier  *  state about segment s
12479ef1f84bSDavid du Colombier  */
12489ef1f84bSDavid du Colombier void
procflushseg(Segment * s)12499ef1f84bSDavid du Colombier procflushseg(Segment *s)
12509ef1f84bSDavid du Colombier {
12519ef1f84bSDavid du Colombier 	int i, ns, nm, nwait;
12529ef1f84bSDavid du Colombier 	Proc *p;
12539ef1f84bSDavid du Colombier 	Mach *mp;
12549ef1f84bSDavid du Colombier 
12559ef1f84bSDavid du Colombier 	/*
12569ef1f84bSDavid du Colombier 	 *  tell all processes with this
12579ef1f84bSDavid du Colombier 	 *  segment to flush their mmu's
12589ef1f84bSDavid du Colombier 	 */
12599ef1f84bSDavid du Colombier 	nwait = 0;
12609ef1f84bSDavid du Colombier 	for(i=0; (p = psincref(i)) != nil; i++) {
12619ef1f84bSDavid du Colombier 		if(p->state == Dead){
12629ef1f84bSDavid du Colombier 			psdecref(p);
12639ef1f84bSDavid du Colombier 			continue;
12649ef1f84bSDavid du Colombier 		}
12659ef1f84bSDavid du Colombier 		for(ns = 0; ns < NSEG; ns++){
12669ef1f84bSDavid du Colombier 			if(p->seg[ns] == s){
12679ef1f84bSDavid du Colombier 				p->newtlb = 1;
12689ef1f84bSDavid du Colombier 				for(nm = 0; nm < MACHMAX; nm++){
12699ef1f84bSDavid du Colombier 					if((mp = sys->machptr[nm]) == nil || !mp->online)
12709ef1f84bSDavid du Colombier 						continue;
12719ef1f84bSDavid du Colombier 					if(mp->proc == p){
12729ef1f84bSDavid du Colombier 						mp->mmuflush = 1;
12739ef1f84bSDavid du Colombier 						nwait++;
12749ef1f84bSDavid du Colombier 					}
12759ef1f84bSDavid du Colombier 				}
12769ef1f84bSDavid du Colombier 				break;
12779ef1f84bSDavid du Colombier 			}
12789ef1f84bSDavid du Colombier 		}
12799ef1f84bSDavid du Colombier 		psdecref(p);
12809ef1f84bSDavid du Colombier 	}
12819ef1f84bSDavid du Colombier 
12829ef1f84bSDavid du Colombier 	if(nwait == 0)
12839ef1f84bSDavid du Colombier 		return;
12849ef1f84bSDavid du Colombier 
12859ef1f84bSDavid du Colombier 	/*
12869ef1f84bSDavid du Colombier 	 *  wait for all processors to take a clock interrupt
12879ef1f84bSDavid du Colombier 	 *  and flush their mmu's
12889ef1f84bSDavid du Colombier 	 */
12899ef1f84bSDavid du Colombier 	for(i = 0; i < MACHMAX; i++){
12909ef1f84bSDavid du Colombier 		if((mp = sys->machptr[i]) == nil || !mp->online || mp == m)
12919ef1f84bSDavid du Colombier 			continue;
12929ef1f84bSDavid du Colombier 		while(mp->mmuflush)
12939ef1f84bSDavid du Colombier 			sched();
12949ef1f84bSDavid du Colombier 	}
12959ef1f84bSDavid du Colombier }
12969ef1f84bSDavid du Colombier 
12979ef1f84bSDavid du Colombier void
scheddump(void)12989ef1f84bSDavid du Colombier scheddump(void)
12999ef1f84bSDavid du Colombier {
13009ef1f84bSDavid du Colombier 	Proc *p;
13019ef1f84bSDavid du Colombier 	Schedq *rq;
13029ef1f84bSDavid du Colombier 
13039ef1f84bSDavid du Colombier 	for(rq = &runq[Nrq-1]; rq >= runq; rq--){
13049ef1f84bSDavid du Colombier 		if(rq->head == 0)
13059ef1f84bSDavid du Colombier 			continue;
13069ef1f84bSDavid du Colombier 		print("rq%ld:", rq-runq);
13079ef1f84bSDavid du Colombier 		for(p = rq->head; p; p = p->rnext)
13089ef1f84bSDavid du Colombier 			print(" %d(%lud)", p->pid, m->ticks - p->readytime);
13099ef1f84bSDavid du Colombier 		print("\n");
13109ef1f84bSDavid du Colombier 		delay(150);
13119ef1f84bSDavid du Colombier 	}
13129ef1f84bSDavid du Colombier 	print("nrdy %d\n", nrdy);
13139ef1f84bSDavid du Colombier }
13149ef1f84bSDavid du Colombier 
13159ef1f84bSDavid du Colombier void
kproc(char * name,void (* func)(void *),void * arg)13169ef1f84bSDavid du Colombier kproc(char *name, void (*func)(void *), void *arg)
13179ef1f84bSDavid du Colombier {
13189ef1f84bSDavid du Colombier 	Proc *p;
13199ef1f84bSDavid du Colombier 	static Pgrp *kpgrp;
13209ef1f84bSDavid du Colombier 
13219ef1f84bSDavid du Colombier 	p = newproc();
13229ef1f84bSDavid du Colombier 	p->psstate = 0;
13239ef1f84bSDavid du Colombier 	p->procmode = 0640;
13249ef1f84bSDavid du Colombier 	p->kp = 1;
13259ef1f84bSDavid du Colombier 
13269ef1f84bSDavid du Colombier 	p->scallnr = up->scallnr;
13279ef1f84bSDavid du Colombier 	memmove(p->arg, up->arg, sizeof(up->arg));
13289ef1f84bSDavid du Colombier 	p->nerrlab = 0;
13299ef1f84bSDavid du Colombier 	p->slash = up->slash;
13309ef1f84bSDavid du Colombier 	p->dot = up->dot;
13319ef1f84bSDavid du Colombier 	if(p->dot)
13329ef1f84bSDavid du Colombier 		incref(p->dot);
13339ef1f84bSDavid du Colombier 
13349ef1f84bSDavid du Colombier 	memmove(p->note, up->note, sizeof(p->note));
13359ef1f84bSDavid du Colombier 	p->nnote = up->nnote;
13369ef1f84bSDavid du Colombier 	p->notified = 0;
13379ef1f84bSDavid du Colombier 	p->lastnote = up->lastnote;
13389ef1f84bSDavid du Colombier 	p->notify = up->notify;
1339*4498a243SDavid du Colombier 	p->ureg = nil;
1340*4498a243SDavid du Colombier 	p->dbgreg = nil;
13419ef1f84bSDavid du Colombier 
13429ef1f84bSDavid du Colombier 	procpriority(p, PriKproc, 0);
13439ef1f84bSDavid du Colombier 
13449ef1f84bSDavid du Colombier 	kprocchild(p, func, arg);
13459ef1f84bSDavid du Colombier 
13469ef1f84bSDavid du Colombier 	kstrdup(&p->user, eve);
13479ef1f84bSDavid du Colombier 	kstrdup(&p->text, name);
1348*4498a243SDavid du Colombier 	if(kpgrp == nil)
13499ef1f84bSDavid du Colombier 		kpgrp = newpgrp();
13509ef1f84bSDavid du Colombier 	p->pgrp = kpgrp;
13519ef1f84bSDavid du Colombier 	incref(kpgrp);
13529ef1f84bSDavid du Colombier 
13539ef1f84bSDavid du Colombier 	memset(p->time, 0, sizeof(p->time));
13549ef1f84bSDavid du Colombier 	p->time[TReal] = sys->ticks;
13559ef1f84bSDavid du Colombier 	ready(p);
13569ef1f84bSDavid du Colombier }
13579ef1f84bSDavid du Colombier 
13589ef1f84bSDavid du Colombier /*
13599ef1f84bSDavid du Colombier  *  called splhi() by notify().  See comment in notify for the
13609ef1f84bSDavid du Colombier  *  reasoning.
13619ef1f84bSDavid du Colombier  */
13629ef1f84bSDavid du Colombier void
procctl(Proc * p)13639ef1f84bSDavid du Colombier procctl(Proc *p)
13649ef1f84bSDavid du Colombier {
13659ef1f84bSDavid du Colombier 	Mreg s;
13669ef1f84bSDavid du Colombier 	char *state;
13679ef1f84bSDavid du Colombier 
13689ef1f84bSDavid du Colombier 	switch(p->procctl) {
13699ef1f84bSDavid du Colombier 	case Proc_exitbig:
13709ef1f84bSDavid du Colombier 		spllo();
13719ef1f84bSDavid du Colombier 		pexit("Killed: Insufficient physical memory", 1);
13729ef1f84bSDavid du Colombier 
13739ef1f84bSDavid du Colombier 	case Proc_exitme:
13749ef1f84bSDavid du Colombier 		spllo();		/* pexit has locks in it */
13759ef1f84bSDavid du Colombier 		pexit("Killed", 1);
13769ef1f84bSDavid du Colombier 
13779ef1f84bSDavid du Colombier 	case Proc_traceme:
13789ef1f84bSDavid du Colombier 		if(p->nnote == 0)
13799ef1f84bSDavid du Colombier 			return;
13809ef1f84bSDavid du Colombier 		/* No break */
13819ef1f84bSDavid du Colombier 
13829ef1f84bSDavid du Colombier 	case Proc_stopme:
13839ef1f84bSDavid du Colombier 		p->procctl = 0;
13849ef1f84bSDavid du Colombier 		state = p->psstate;
13859ef1f84bSDavid du Colombier 		p->psstate = "Stopped";
13869ef1f84bSDavid du Colombier 		/* free a waiting debugger */
13879ef1f84bSDavid du Colombier 		s = spllo();
13889ef1f84bSDavid du Colombier 		qlock(&p->debug);
13899ef1f84bSDavid du Colombier 		if(p->pdbg) {
13909ef1f84bSDavid du Colombier 			wakeup(&p->pdbg->sleep);
13919ef1f84bSDavid du Colombier 			p->pdbg = 0;
13929ef1f84bSDavid du Colombier 		}
13939ef1f84bSDavid du Colombier 		qunlock(&p->debug);
13949ef1f84bSDavid du Colombier 		splhi();
13959ef1f84bSDavid du Colombier 		p->state = Stopped;
13969ef1f84bSDavid du Colombier 		sched();
13979ef1f84bSDavid du Colombier 		p->psstate = state;
13989ef1f84bSDavid du Colombier 		splx(s);
13999ef1f84bSDavid du Colombier 		return;
14009ef1f84bSDavid du Colombier 	}
14019ef1f84bSDavid du Colombier }
14029ef1f84bSDavid du Colombier 
14039ef1f84bSDavid du Colombier void
error(char * err)14049ef1f84bSDavid du Colombier error(char *err)
14059ef1f84bSDavid du Colombier {
14069ef1f84bSDavid du Colombier 	spllo();
14079ef1f84bSDavid du Colombier 
14089ef1f84bSDavid du Colombier 	assert(up->nerrlab < NERR);
14099ef1f84bSDavid du Colombier 	kstrcpy(up->errstr, err, ERRMAX);
14109ef1f84bSDavid du Colombier 	setlabel(&up->errlab[NERR-1]);
14119ef1f84bSDavid du Colombier 	nexterror();
14129ef1f84bSDavid du Colombier }
14139ef1f84bSDavid du Colombier 
14149ef1f84bSDavid du Colombier void
nexterror(void)14159ef1f84bSDavid du Colombier nexterror(void)
14169ef1f84bSDavid du Colombier {
14179ef1f84bSDavid du Colombier 	gotolabel(&up->errlab[--up->nerrlab]);
14189ef1f84bSDavid du Colombier }
14199ef1f84bSDavid du Colombier 
14209ef1f84bSDavid du Colombier void
exhausted(char * resource)14219ef1f84bSDavid du Colombier exhausted(char *resource)
14229ef1f84bSDavid du Colombier {
14239ef1f84bSDavid du Colombier 	char buf[ERRMAX];
14249ef1f84bSDavid du Colombier 
1425406c76faSDavid du Colombier 	snprint(buf, sizeof buf, "no free %s", resource);
14269ef1f84bSDavid du Colombier 	iprint("%s\n", buf);
14279ef1f84bSDavid du Colombier 	error(buf);
14289ef1f84bSDavid du Colombier }
14299ef1f84bSDavid du Colombier 
14309ef1f84bSDavid du Colombier void
killbig(char * why)14319ef1f84bSDavid du Colombier killbig(char *why)
14329ef1f84bSDavid du Colombier {
14339ef1f84bSDavid du Colombier 	int i, x;
14349ef1f84bSDavid du Colombier 	Segment *s;
14359ef1f84bSDavid du Colombier 	ulong l, max;
14369ef1f84bSDavid du Colombier 	Proc *p, *kp;
14379ef1f84bSDavid du Colombier 
14389ef1f84bSDavid du Colombier 	max = 0;
14399ef1f84bSDavid du Colombier 	kp = nil;
14409ef1f84bSDavid du Colombier 	for(x = 0; (p = psincref(x)) != nil; x++) {
14419ef1f84bSDavid du Colombier 		if(p->state == Dead || p->kp){
14429ef1f84bSDavid du Colombier 			psdecref(p);
14439ef1f84bSDavid du Colombier 			continue;
14449ef1f84bSDavid du Colombier 		}
14459ef1f84bSDavid du Colombier 		l = 0;
14469ef1f84bSDavid du Colombier 		for(i=1; i<NSEG; i++) {
14479ef1f84bSDavid du Colombier 			s = p->seg[i];
1448*4498a243SDavid du Colombier 			if(s != 0)
14499ef1f84bSDavid du Colombier 				l += s->top - s->base;
14509ef1f84bSDavid du Colombier 		}
14519ef1f84bSDavid du Colombier 		if(l > max && ((p->procmode&0222) || strcmp(eve, p->user)!=0)) {
14529ef1f84bSDavid du Colombier 			if(kp != nil)
14539ef1f84bSDavid du Colombier 				psdecref(kp);
14549ef1f84bSDavid du Colombier 			kp = p;
14559ef1f84bSDavid du Colombier 			max = l;
14569ef1f84bSDavid du Colombier 		}
14579ef1f84bSDavid du Colombier 		else
14589ef1f84bSDavid du Colombier 			psdecref(p);
14599ef1f84bSDavid du Colombier 	}
14609ef1f84bSDavid du Colombier 	if(kp == nil)
14619ef1f84bSDavid du Colombier 		return;
14629ef1f84bSDavid du Colombier 
14639ef1f84bSDavid du Colombier 	print("%d: %s killed: %s\n", kp->pid, kp->text, why);
14649ef1f84bSDavid du Colombier 	for(x = 0; (p = psincref(x)) != nil; x++) {
14659ef1f84bSDavid du Colombier 		if(p->state == Dead || p->kp){
14669ef1f84bSDavid du Colombier 			psdecref(p);
14679ef1f84bSDavid du Colombier 			continue;
14689ef1f84bSDavid du Colombier 		}
14699ef1f84bSDavid du Colombier 		if(p != kp && p->seg[BSEG] && p->seg[BSEG] == kp->seg[BSEG])
14709ef1f84bSDavid du Colombier 			p->procctl = Proc_exitbig;
14719ef1f84bSDavid du Colombier 		psdecref(p);
14729ef1f84bSDavid du Colombier 	}
14739ef1f84bSDavid du Colombier 
14749ef1f84bSDavid du Colombier 	kp->procctl = Proc_exitbig;
14759ef1f84bSDavid du Colombier 	for(i = 0; i < NSEG; i++) {
14769ef1f84bSDavid du Colombier 		s = kp->seg[i];
14779ef1f84bSDavid du Colombier 		if(s != nil && canqlock(&s->lk)) {
14789ef1f84bSDavid du Colombier 			mfreeseg(s, s->base, s->top);
14799ef1f84bSDavid du Colombier 			qunlock(&s->lk);
14809ef1f84bSDavid du Colombier 		}
14819ef1f84bSDavid du Colombier 	}
14829ef1f84bSDavid du Colombier 	psdecref(kp);
14839ef1f84bSDavid du Colombier }
14849ef1f84bSDavid du Colombier 
14859ef1f84bSDavid du Colombier /*
14869ef1f84bSDavid du Colombier  *  change ownership to 'new' of all processes owned by 'old'.  Used when
14879ef1f84bSDavid du Colombier  *  eve changes.
14889ef1f84bSDavid du Colombier  */
14899ef1f84bSDavid du Colombier void
renameuser(char * old,char * new)14909ef1f84bSDavid du Colombier renameuser(char *old, char *new)
14919ef1f84bSDavid du Colombier {
14929ef1f84bSDavid du Colombier 	int i;
14939ef1f84bSDavid du Colombier 	Proc *p;
14949ef1f84bSDavid du Colombier 
14959ef1f84bSDavid du Colombier 	for(i = 0; (p = psincref(i)) != nil; i++){
14969ef1f84bSDavid du Colombier 		if(p->user!=nil && strcmp(old, p->user)==0)
14979ef1f84bSDavid du Colombier 			kstrdup(&p->user, new);
14989ef1f84bSDavid du Colombier 		psdecref(p);
14999ef1f84bSDavid du Colombier 	}
15009ef1f84bSDavid du Colombier }
15019ef1f84bSDavid du Colombier 
15029ef1f84bSDavid du Colombier /*
15039ef1f84bSDavid du Colombier  *  time accounting called by clock() splhi'd
15049ef1f84bSDavid du Colombier  */
15059ef1f84bSDavid du Colombier void
accounttime(void)15069ef1f84bSDavid du Colombier accounttime(void)
15079ef1f84bSDavid du Colombier {
15089ef1f84bSDavid du Colombier 	Proc *p;
15099ef1f84bSDavid du Colombier 	ulong n, per;
15109ef1f84bSDavid du Colombier 	static ulong nrun;
15119ef1f84bSDavid du Colombier 
15129ef1f84bSDavid du Colombier 	p = m->proc;
1513*4498a243SDavid du Colombier 	if(p != nil) {
15149ef1f84bSDavid du Colombier 		nrun++;
15159ef1f84bSDavid du Colombier 		p->time[p->insyscall]++;
15169ef1f84bSDavid du Colombier 	}
15179ef1f84bSDavid du Colombier 
15189ef1f84bSDavid du Colombier 	/* calculate decaying duty cycles */
15199ef1f84bSDavid du Colombier 	n = perfticks();
15209ef1f84bSDavid du Colombier 	per = n - m->perf.last;
15219ef1f84bSDavid du Colombier 	m->perf.last = n;
15229ef1f84bSDavid du Colombier 	per = (m->perf.period*(HZ-1) + per)/HZ;
15239ef1f84bSDavid du Colombier 	if(per != 0)
15249ef1f84bSDavid du Colombier 		m->perf.period = per;
15259ef1f84bSDavid du Colombier 
15269ef1f84bSDavid du Colombier 	m->perf.avg_inidle = (m->perf.avg_inidle*(HZ-1)+m->perf.inidle)/HZ;
15279ef1f84bSDavid du Colombier 	m->perf.inidle = 0;
15289ef1f84bSDavid du Colombier 
15299ef1f84bSDavid du Colombier 	m->perf.avg_inintr = (m->perf.avg_inintr*(HZ-1)+m->perf.inintr)/HZ;
15309ef1f84bSDavid du Colombier 	m->perf.inintr = 0;
15319ef1f84bSDavid du Colombier 
15329ef1f84bSDavid du Colombier 	/* only one processor gets to compute system load averages */
15339ef1f84bSDavid du Colombier 	if(m->machno != 0)
15349ef1f84bSDavid du Colombier 		return;
15359ef1f84bSDavid du Colombier 
15369ef1f84bSDavid du Colombier 	/*
15379ef1f84bSDavid du Colombier 	 * calculate decaying load average.
15389ef1f84bSDavid du Colombier 	 * if we decay by (n-1)/n then it takes
15399ef1f84bSDavid du Colombier 	 * n clock ticks to go from load L to .36 L once
15409ef1f84bSDavid du Colombier 	 * things quiet down.  it takes about 5 n clock
15419ef1f84bSDavid du Colombier 	 * ticks to go to zero.  so using HZ means this is
15429ef1f84bSDavid du Colombier 	 * approximately the load over the last second,
15439ef1f84bSDavid du Colombier 	 * with a tail lasting about 5 seconds.
15449ef1f84bSDavid du Colombier 	 */
15459ef1f84bSDavid du Colombier 	n = nrun;
15469ef1f84bSDavid du Colombier 	nrun = 0;
15479ef1f84bSDavid du Colombier 	n = (nrdy+n)*1000;
15489ef1f84bSDavid du Colombier 	m->load = (m->load*(HZ-1)+n)/HZ;
15499ef1f84bSDavid du Colombier }
15509ef1f84bSDavid du Colombier 
1551