1e288d156SDavid 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"
7696c1e60SDavid du Colombier #include "../port/edf.h"
8e288d156SDavid du Colombier #include <trace.h>
93e12c5d1SDavid du Colombier
1095a264b3SDavid du Colombier int schedgain = 30; /* units in seconds */
119a747e4fSDavid du Colombier int nrdy;
123e12c5d1SDavid du Colombier Ref noteidalloc;
133e12c5d1SDavid du Colombier
1459c21d95SDavid du Colombier void updatecpu(Proc*);
1559c21d95SDavid du Colombier int reprioritize(Proc*);
1659c21d95SDavid du Colombier
17061a3f44SDavid du Colombier ulong delayedscheds; /* statistics */
1859c21d95SDavid du Colombier long skipscheds;
1959c21d95SDavid du Colombier long preempts;
2059c21d95SDavid du Colombier ulong load;
219a747e4fSDavid du Colombier
229a747e4fSDavid du Colombier static Ref pidalloc;
239a747e4fSDavid du Colombier
249a747e4fSDavid du Colombier static struct Procalloc
253e12c5d1SDavid du Colombier {
263e12c5d1SDavid du Colombier Lock;
279a747e4fSDavid du Colombier Proc* ht[128];
283e12c5d1SDavid du Colombier Proc* arena;
293e12c5d1SDavid du Colombier Proc* free;
303e12c5d1SDavid du Colombier } procalloc;
313e12c5d1SDavid du Colombier
32a6a9e072SDavid du Colombier enum
33a6a9e072SDavid du Colombier {
3459c21d95SDavid du Colombier Q=10,
3559c21d95SDavid du Colombier DQ=4,
3695a264b3SDavid du Colombier Scaling=2,
37a6a9e072SDavid du Colombier };
38a6a9e072SDavid du Colombier
39e288d156SDavid du Colombier Schedq runq[Nrq];
40e288d156SDavid du Colombier ulong runvec;
413e12c5d1SDavid du Colombier
423e12c5d1SDavid du Colombier char *statename[] =
433e12c5d1SDavid du Colombier { /* BUG: generate automatically */
443e12c5d1SDavid du Colombier "Dead",
453e12c5d1SDavid du Colombier "Moribund",
463e12c5d1SDavid du Colombier "Ready",
473e12c5d1SDavid du Colombier "Scheding",
483e12c5d1SDavid du Colombier "Running",
493e12c5d1SDavid du Colombier "Queueing",
507dd7cddfSDavid du Colombier "QueueingR",
517dd7cddfSDavid du Colombier "QueueingW",
523e12c5d1SDavid du Colombier "Wakeme",
533e12c5d1SDavid du Colombier "Broken",
543e12c5d1SDavid du Colombier "Stopped",
553e12c5d1SDavid du Colombier "Rendez",
56e288d156SDavid du Colombier "Waitrelease",
573e12c5d1SDavid du Colombier };
583e12c5d1SDavid du Colombier
599a747e4fSDavid du Colombier static void pidhash(Proc*);
609a747e4fSDavid du Colombier static void pidunhash(Proc*);
6159c21d95SDavid du Colombier static void rebalance(void);
629a747e4fSDavid du Colombier
633e12c5d1SDavid du Colombier /*
643e12c5d1SDavid du Colombier * Always splhi()'ed.
653e12c5d1SDavid du Colombier */
663e12c5d1SDavid du Colombier void
schedinit(void)673e12c5d1SDavid du Colombier schedinit(void) /* never returns */
683e12c5d1SDavid du Colombier {
69e288d156SDavid du Colombier Edf *e;
70e288d156SDavid du Colombier
713e12c5d1SDavid du Colombier setlabel(&m->sched);
727dd7cddfSDavid du Colombier if(up) {
73e288d156SDavid du Colombier if((e = up->edf) && (e->flags & Admitted))
74e288d156SDavid du Colombier edfrecord(up);
753e12c5d1SDavid du Colombier m->proc = 0;
767dd7cddfSDavid du Colombier switch(up->state) {
777dd7cddfSDavid du Colombier case Running:
787dd7cddfSDavid du Colombier ready(up);
797dd7cddfSDavid du Colombier break;
807dd7cddfSDavid du Colombier case Moribund:
817dd7cddfSDavid du Colombier up->state = Dead;
82e288d156SDavid du Colombier edfstop(up);
83e288d156SDavid du Colombier if (up->edf)
84e288d156SDavid du Colombier free(up->edf);
85e288d156SDavid du Colombier up->edf = nil;
869a747e4fSDavid du Colombier
873e12c5d1SDavid du Colombier /*
883e12c5d1SDavid du Colombier * Holding locks from pexit:
897dd7cddfSDavid du Colombier * procalloc
907dd7cddfSDavid du Colombier * palloc
913e12c5d1SDavid du Colombier */
927dd7cddfSDavid du Colombier mmurelease(up);
933e12c5d1SDavid du Colombier
947dd7cddfSDavid du Colombier up->qnext = procalloc.free;
957dd7cddfSDavid du Colombier procalloc.free = up;
963e12c5d1SDavid du Colombier
973e12c5d1SDavid du Colombier unlock(&palloc);
983e12c5d1SDavid du Colombier unlock(&procalloc);
997dd7cddfSDavid du Colombier break;
1003e12c5d1SDavid du Colombier }
10159c21d95SDavid du Colombier up->mach = nil;
10259c21d95SDavid du Colombier updatecpu(up);
1039a747e4fSDavid du Colombier up = nil;
1043e12c5d1SDavid du Colombier }
1053e12c5d1SDavid du Colombier sched();
1063e12c5d1SDavid du Colombier }
1073e12c5d1SDavid du Colombier
1087dd7cddfSDavid du Colombier /*
1097dd7cddfSDavid du Colombier * If changing this routine, look also at sleep(). It
1107dd7cddfSDavid du Colombier * contains a copy of the guts of sched().
1117dd7cddfSDavid du Colombier */
1123e12c5d1SDavid du Colombier void
sched(void)1133e12c5d1SDavid du Colombier sched(void)
1143e12c5d1SDavid du Colombier {
11559c21d95SDavid du Colombier Proc *p;
116d9306527SDavid du Colombier
1179a747e4fSDavid du Colombier if(m->ilockdepth)
1185f7495c3SDavid du Colombier panic("cpu%d: ilockdepth %d, last lock %#p at %#p, sched called from %#p",
1195f7495c3SDavid du Colombier m->machno,
1205f7495c3SDavid du Colombier m->ilockdepth,
1215f7495c3SDavid du Colombier up? up->lastilock: nil,
1224de34a7eSDavid du Colombier (up && up->lastilock)? up->lastilock->pc: 0,
1234de34a7eSDavid du Colombier getcallerpc(&p+2));
1247dd7cddfSDavid du Colombier if(up){
1255437ee90SDavid du Colombier /*
1265437ee90SDavid du Colombier * Delay the sched until the process gives up the locks
1275437ee90SDavid du Colombier * it is holding. This avoids dumb lock loops.
1285437ee90SDavid du Colombier * Don't delay if the process is Moribund.
1295437ee90SDavid du Colombier * It called sched to die.
1305437ee90SDavid du Colombier * But do sched eventually. This avoids a missing unlock
1315437ee90SDavid du Colombier * from hanging the entire kernel.
1325437ee90SDavid du Colombier * But don't reschedule procs holding palloc or procalloc.
1335437ee90SDavid du Colombier * Those are far too important to be holding while asleep.
1345437ee90SDavid du Colombier *
1355437ee90SDavid du Colombier * This test is not exact. There can still be a few instructions
1365437ee90SDavid du Colombier * in the middle of taslock when a process holds a lock
1375437ee90SDavid du Colombier * but Lock.p has not yet been initialized.
1385437ee90SDavid du Colombier */
1395437ee90SDavid du Colombier if(up->nlocks.ref)
1405437ee90SDavid du Colombier if(up->state != Moribund)
1415437ee90SDavid du Colombier if(up->delaysched < 20
1425437ee90SDavid du Colombier || palloc.Lock.p == up
1435437ee90SDavid du Colombier || procalloc.Lock.p == up){
144e288d156SDavid du Colombier up->delaysched++;
1459a747e4fSDavid du Colombier delayedscheds++;
1469a747e4fSDavid du Colombier return;
1479a747e4fSDavid du Colombier }
148e288d156SDavid du Colombier up->delaysched = 0;
1499a747e4fSDavid du Colombier
1503e12c5d1SDavid du Colombier splhi();
1517dd7cddfSDavid du Colombier
1527dd7cddfSDavid du Colombier /* statistics */
1533e12c5d1SDavid du Colombier m->cs++;
1547dd7cddfSDavid du Colombier
1557dd7cddfSDavid du Colombier procsave(up);
1567dd7cddfSDavid du Colombier if(setlabel(&up->sched)){
1577dd7cddfSDavid du Colombier procrestore(up);
1583e12c5d1SDavid du Colombier spllo();
1593e12c5d1SDavid du Colombier return;
1603e12c5d1SDavid du Colombier }
1613e12c5d1SDavid du Colombier gotolabel(&m->sched);
1623e12c5d1SDavid du Colombier }
16359c21d95SDavid du Colombier p = runproc();
16459c21d95SDavid du Colombier if(!p->edf){
16559c21d95SDavid du Colombier updatecpu(p);
16659c21d95SDavid du Colombier p->priority = reprioritize(p);
16759c21d95SDavid du Colombier }
16859c21d95SDavid du Colombier if(p != m->readied)
16959c21d95SDavid du Colombier m->schedticks = m->ticks + HZ/10;
17095a264b3SDavid du Colombier m->readied = 0;
17159c21d95SDavid du Colombier up = p;
1727dd7cddfSDavid du Colombier up->state = Running;
1737dd7cddfSDavid du Colombier up->mach = MACHP(m->machno);
1747dd7cddfSDavid du Colombier m->proc = up;
1757dd7cddfSDavid du Colombier mmuswitch(up);
1767dd7cddfSDavid du Colombier gotolabel(&up->sched);
1773e12c5d1SDavid du Colombier }
1783e12c5d1SDavid du Colombier
1793e12c5d1SDavid du Colombier int
anyready(void)1803e12c5d1SDavid du Colombier anyready(void)
1813e12c5d1SDavid du Colombier {
182e288d156SDavid du Colombier return runvec;
1833e12c5d1SDavid du Colombier }
1843e12c5d1SDavid du Colombier
185219b2ee8SDavid du Colombier int
anyhigher(void)186219b2ee8SDavid du Colombier anyhigher(void)
187219b2ee8SDavid du Colombier {
188a6a9e072SDavid du Colombier return runvec & ~((1<<(up->priority+1))-1);
189a6a9e072SDavid du Colombier }
190219b2ee8SDavid du Colombier
191a6a9e072SDavid du Colombier /*
192a6a9e072SDavid du Colombier * here once per clock tick to see if we should resched
193a6a9e072SDavid du Colombier */
194a6a9e072SDavid du Colombier void
hzsched(void)195a6a9e072SDavid du Colombier hzsched(void)
196a6a9e072SDavid du Colombier {
19759c21d95SDavid du Colombier /* once a second, rebalance will reprioritize ready procs */
19859c21d95SDavid du Colombier if(m->machno == 0)
19959c21d95SDavid du Colombier rebalance();
2007dd7cddfSDavid du Colombier
20159c21d95SDavid du Colombier /* unless preempted, get to run for at least 100ms */
20259c21d95SDavid du Colombier if(anyhigher()
20359c21d95SDavid du Colombier || (!up->fixedpri && m->ticks > m->schedticks && anyready())){
20459c21d95SDavid du Colombier m->readied = nil; /* avoid cooperative scheduling */
205da51d93aSDavid du Colombier up->delaysched++;
206a6a9e072SDavid du Colombier }
207a6a9e072SDavid du Colombier }
208a6a9e072SDavid du Colombier
209a6a9e072SDavid du Colombier /*
210a6a9e072SDavid du Colombier * here at the end of non-clock interrupts to see if we should preempt the
211a6a9e072SDavid du Colombier * current process. Returns 1 if preempted, 0 otherwise.
212a6a9e072SDavid du Colombier */
213a6a9e072SDavid du Colombier int
preempted(void)214a6a9e072SDavid du Colombier preempted(void)
215a6a9e072SDavid du Colombier {
216a6a9e072SDavid du Colombier if(up && up->state == Running)
217a6a9e072SDavid du Colombier if(up->preempted == 0)
218a6a9e072SDavid du Colombier if(anyhigher())
219a6a9e072SDavid du Colombier if(!active.exiting){
22059c21d95SDavid du Colombier m->readied = nil; /* avoid cooperative scheduling */
221a6a9e072SDavid du Colombier up->preempted = 1;
222a6a9e072SDavid du Colombier sched();
223a6a9e072SDavid du Colombier splhi();
224a6a9e072SDavid du Colombier up->preempted = 0;
2257dd7cddfSDavid du Colombier return 1;
226a6a9e072SDavid du Colombier }
2277dd7cddfSDavid du Colombier return 0;
228219b2ee8SDavid du Colombier }
229219b2ee8SDavid du Colombier
230a6a9e072SDavid du Colombier /*
23159c21d95SDavid du Colombier * Update the cpu time average for this particular process,
23259c21d95SDavid du Colombier * which is about to change from up -> not up or vice versa.
23359c21d95SDavid du Colombier * p->lastupdate is the last time an updatecpu happened.
234a6a9e072SDavid du Colombier *
23559c21d95SDavid du Colombier * The cpu time average is a decaying average that lasts
23659c21d95SDavid du Colombier * about D clock ticks. D is chosen to be approximately
23759c21d95SDavid du Colombier * the cpu time of a cpu-intensive "quick job". A job has to run
23859c21d95SDavid du Colombier * for approximately D clock ticks before we home in on its
23959c21d95SDavid du Colombier * actual cpu usage. Thus if you manage to get in and get out
24059c21d95SDavid du Colombier * quickly, you won't be penalized during your burst. Once you
24159c21d95SDavid du Colombier * start using your share of the cpu for more than about D
24259c21d95SDavid du Colombier * clock ticks though, your p->cpu hits 1000 (1.0) and you end up
24359c21d95SDavid du Colombier * below all the other quick jobs. Interactive tasks, because
24459c21d95SDavid du Colombier * they basically always use less than their fair share of cpu,
24559c21d95SDavid du Colombier * will be rewarded.
246a6a9e072SDavid du Colombier *
24759c21d95SDavid du Colombier * If the process has not been running, then we want to
24859c21d95SDavid du Colombier * apply the filter
24959c21d95SDavid du Colombier *
25059c21d95SDavid du Colombier * cpu = cpu * (D-1)/D
25159c21d95SDavid du Colombier *
25259c21d95SDavid du Colombier * n times, yielding
25359c21d95SDavid du Colombier *
25459c21d95SDavid du Colombier * cpu = cpu * ((D-1)/D)^n
25559c21d95SDavid du Colombier *
25659c21d95SDavid du Colombier * but D is big enough that this is approximately
25759c21d95SDavid du Colombier *
25859c21d95SDavid du Colombier * cpu = cpu * (D-n)/D
25959c21d95SDavid du Colombier *
26059c21d95SDavid du Colombier * so we use that instead.
26159c21d95SDavid du Colombier *
26259c21d95SDavid du Colombier * If the process has been running, we apply the filter to
26359c21d95SDavid du Colombier * 1 - cpu, yielding a similar equation. Note that cpu is
26459c21d95SDavid du Colombier * stored in fixed point (* 1000).
26559c21d95SDavid du Colombier *
26659c21d95SDavid du Colombier * Updatecpu must be called before changing up, in order
26759c21d95SDavid du Colombier * to maintain accurate cpu usage statistics. It can be called
26859c21d95SDavid du Colombier * at any time to bring the stats for a given proc up-to-date.
269a6a9e072SDavid du Colombier */
2703e12c5d1SDavid du Colombier void
updatecpu(Proc * p)27159c21d95SDavid du Colombier updatecpu(Proc *p)
2723e12c5d1SDavid du Colombier {
27359c21d95SDavid du Colombier int n, t, ocpu;
27495a264b3SDavid du Colombier int D = schedgain*HZ*Scaling;
2753e12c5d1SDavid du Colombier
27659c21d95SDavid du Colombier if(p->edf)
2779a747e4fSDavid du Colombier return;
27859c21d95SDavid du Colombier
27995a264b3SDavid du Colombier t = MACHP(0)->ticks*Scaling + Scaling/2;
28059c21d95SDavid du Colombier n = t - p->lastupdate;
28159c21d95SDavid du Colombier p->lastupdate = t;
28259c21d95SDavid du Colombier
28359c21d95SDavid du Colombier if(n == 0)
28459c21d95SDavid du Colombier return;
28559c21d95SDavid du Colombier if(n > D)
28659c21d95SDavid du Colombier n = D;
28759c21d95SDavid du Colombier
28859c21d95SDavid du Colombier ocpu = p->cpu;
28959c21d95SDavid du Colombier if(p != up)
29059c21d95SDavid du Colombier p->cpu = (ocpu*(D-n))/D;
29159c21d95SDavid du Colombier else{
29259c21d95SDavid du Colombier t = 1000 - ocpu;
29359c21d95SDavid du Colombier t = (t*(D-n))/D;
29459c21d95SDavid du Colombier p->cpu = 1000 - t;
2959a747e4fSDavid du Colombier }
296a6a9e072SDavid du Colombier
29759c21d95SDavid du Colombier //iprint("pid %d %s for %d cpu %d -> %d\n", p->pid,p==up?"active":"inactive",n, ocpu,p->cpu);
29880ee5cbfSDavid du Colombier }
2997dd7cddfSDavid du Colombier
30059c21d95SDavid du Colombier /*
30159c21d95SDavid du Colombier * On average, p has used p->cpu of a cpu recently.
30259c21d95SDavid du Colombier * Its fair share is conf.nmach/m->load of a cpu. If it has been getting
30359c21d95SDavid du Colombier * too much, penalize it. If it has been getting not enough, reward it.
30459c21d95SDavid du Colombier * I don't think you can get much more than your fair share that
30559c21d95SDavid du Colombier * often, so most of the queues are for using less. Having a priority
30659c21d95SDavid du Colombier * of 3 means you're just right. Having a higher priority (up to p->basepri)
30759c21d95SDavid du Colombier * means you're not using as much as you could.
30859c21d95SDavid du Colombier */
30959c21d95SDavid du Colombier int
reprioritize(Proc * p)31059c21d95SDavid du Colombier reprioritize(Proc *p)
31159c21d95SDavid du Colombier {
31259c21d95SDavid du Colombier int fairshare, n, load, ratio;
31359c21d95SDavid du Colombier
31459c21d95SDavid du Colombier load = MACHP(0)->load;
31559c21d95SDavid du Colombier if(load == 0)
31659c21d95SDavid du Colombier return p->basepri;
31759c21d95SDavid du Colombier
31859c21d95SDavid du Colombier /*
31959c21d95SDavid du Colombier * fairshare = 1.000 * conf.nproc * 1.000/load,
32059c21d95SDavid du Colombier * except the decimal point is moved three places
32159c21d95SDavid du Colombier * on both load and fairshare.
32259c21d95SDavid du Colombier */
32359c21d95SDavid du Colombier fairshare = (conf.nmach*1000*1000)/load;
32459c21d95SDavid du Colombier n = p->cpu;
32559c21d95SDavid du Colombier if(n == 0)
32659c21d95SDavid du Colombier n = 1;
32759c21d95SDavid du Colombier ratio = (fairshare+n/2) / n;
32859c21d95SDavid du Colombier if(ratio > p->basepri)
32959c21d95SDavid du Colombier ratio = p->basepri;
33059c21d95SDavid du Colombier if(ratio < 0)
33159c21d95SDavid du Colombier panic("reprioritize");
33259c21d95SDavid du Colombier //iprint("pid %d cpu %d load %d fair %d pri %d\n", p->pid, p->cpu, load, fairshare, ratio);
33359c21d95SDavid du Colombier return ratio;
33459c21d95SDavid du Colombier }
33559c21d95SDavid du Colombier
33659c21d95SDavid du Colombier /*
33759c21d95SDavid du Colombier * add a process to a scheduling queue
33859c21d95SDavid du Colombier */
33959c21d95SDavid du Colombier void
queueproc(Schedq * rq,Proc * p)34059c21d95SDavid du Colombier queueproc(Schedq *rq, Proc *p)
34159c21d95SDavid du Colombier {
34259c21d95SDavid du Colombier int pri;
34359c21d95SDavid du Colombier
34459c21d95SDavid du Colombier pri = rq - runq;
345219b2ee8SDavid du Colombier lock(runq);
34659c21d95SDavid du Colombier p->priority = pri;
3473e12c5d1SDavid du Colombier p->rnext = 0;
3483e12c5d1SDavid du Colombier if(rq->tail)
3493e12c5d1SDavid du Colombier rq->tail->rnext = p;
3503e12c5d1SDavid du Colombier else
3513e12c5d1SDavid du Colombier rq->head = p;
3523e12c5d1SDavid du Colombier rq->tail = p;
353219b2ee8SDavid du Colombier rq->n++;
3543e12c5d1SDavid du Colombier nrdy++;
355a6a9e072SDavid du Colombier runvec |= 1<<pri;
356219b2ee8SDavid du Colombier unlock(runq);
3573e12c5d1SDavid du Colombier }
3583e12c5d1SDavid du Colombier
35904b73bddSDavid du Colombier /*
36059c21d95SDavid du Colombier * try to remove a process from a scheduling queue (called splhi)
36104b73bddSDavid du Colombier */
362e288d156SDavid du Colombier Proc*
dequeueproc(Schedq * rq,Proc * tp)36304b73bddSDavid du Colombier dequeueproc(Schedq *rq, Proc *tp)
3643e12c5d1SDavid du Colombier {
36504b73bddSDavid du Colombier Proc *l, *p;
3663e12c5d1SDavid du Colombier
3677dd7cddfSDavid du Colombier if(!canlock(runq))
36804b73bddSDavid du Colombier return nil;
369219b2ee8SDavid du Colombier
370a6a9e072SDavid du Colombier /*
371a6a9e072SDavid du Colombier * the queue may have changed before we locked runq,
372a6a9e072SDavid du Colombier * refind the target process.
373a6a9e072SDavid du Colombier */
374219b2ee8SDavid du Colombier l = 0;
375219b2ee8SDavid du Colombier for(p = rq->head; p; p = p->rnext){
376a6a9e072SDavid du Colombier if(p == tp)
377219b2ee8SDavid du Colombier break;
378219b2ee8SDavid du Colombier l = p;
379219b2ee8SDavid du Colombier }
380219b2ee8SDavid du Colombier
381219b2ee8SDavid du Colombier /*
382219b2ee8SDavid du Colombier * p->mach==0 only when process state is saved
383219b2ee8SDavid du Colombier */
384219b2ee8SDavid du Colombier if(p == 0 || p->mach){
385219b2ee8SDavid du Colombier unlock(runq);
38604b73bddSDavid du Colombier return nil;
3873e12c5d1SDavid du Colombier }
3883e12c5d1SDavid du Colombier if(p->rnext == 0)
389219b2ee8SDavid du Colombier rq->tail = l;
390219b2ee8SDavid du Colombier if(l)
391219b2ee8SDavid du Colombier l->rnext = p->rnext;
392219b2ee8SDavid du Colombier else
3933e12c5d1SDavid du Colombier rq->head = p->rnext;
394a6a9e072SDavid du Colombier if(rq->head == nil)
395a6a9e072SDavid du Colombier runvec &= ~(1<<(rq-runq));
396219b2ee8SDavid du Colombier rq->n--;
3973e12c5d1SDavid du Colombier nrdy--;
3983e12c5d1SDavid du Colombier if(p->state != Ready)
39904b73bddSDavid du Colombier print("dequeueproc %s %lud %s\n", p->text, p->pid, statename[p->state]);
40004b73bddSDavid du Colombier
401219b2ee8SDavid du Colombier unlock(runq);
40204b73bddSDavid du Colombier return p;
40304b73bddSDavid du Colombier }
40404b73bddSDavid du Colombier
40504b73bddSDavid du Colombier /*
40659c21d95SDavid du Colombier * ready(p) picks a new priority for a process and sticks it in the
40759c21d95SDavid du Colombier * runq for that priority.
40859c21d95SDavid du Colombier */
40959c21d95SDavid du Colombier void
ready(Proc * p)41059c21d95SDavid du Colombier ready(Proc *p)
41159c21d95SDavid du Colombier {
41259c21d95SDavid du Colombier int s, pri;
41359c21d95SDavid du Colombier Schedq *rq;
41459c21d95SDavid du Colombier void (*pt)(Proc*, int, vlong);
41559c21d95SDavid du Colombier
41659c21d95SDavid du Colombier s = splhi();
41759c21d95SDavid du Colombier if(edfready(p)){
41859c21d95SDavid du Colombier splx(s);
41959c21d95SDavid du Colombier return;
42059c21d95SDavid du Colombier }
42159c21d95SDavid du Colombier
4226fb99756SDavid du Colombier if(up != p && (p->wired == nil || p->wired == m))
42359c21d95SDavid du Colombier m->readied = p; /* group scheduling */
42459c21d95SDavid du Colombier
42559c21d95SDavid du Colombier updatecpu(p);
42659c21d95SDavid du Colombier pri = reprioritize(p);
42759c21d95SDavid du Colombier p->priority = pri;
42859c21d95SDavid du Colombier rq = &runq[pri];
42959c21d95SDavid du Colombier p->state = Ready;
43059c21d95SDavid du Colombier queueproc(rq, p);
43159c21d95SDavid du Colombier pt = proctrace;
43259c21d95SDavid du Colombier if(pt)
43359c21d95SDavid du Colombier pt(p, SReady, 0);
43459c21d95SDavid du Colombier splx(s);
43559c21d95SDavid du Colombier }
43659c21d95SDavid du Colombier
43759c21d95SDavid du Colombier /*
43804b73bddSDavid du Colombier * yield the processor and drop our priority
43904b73bddSDavid du Colombier */
44004b73bddSDavid du Colombier void
yield(void)44104b73bddSDavid du Colombier yield(void)
44204b73bddSDavid du Colombier {
44304b73bddSDavid du Colombier if(anyready()){
44495a264b3SDavid du Colombier /* pretend we just used 1/2 tick */
44595a264b3SDavid du Colombier up->lastupdate -= Scaling/2;
44604b73bddSDavid du Colombier sched();
44704b73bddSDavid du Colombier }
44804b73bddSDavid du Colombier }
44904b73bddSDavid du Colombier
45004b73bddSDavid du Colombier /*
45195a264b3SDavid du Colombier * recalculate priorities once a second. We need to do this
45295a264b3SDavid du Colombier * since priorities will otherwise only be recalculated when
45395a264b3SDavid du Colombier * the running process blocks.
45404b73bddSDavid du Colombier */
45559c21d95SDavid du Colombier ulong balancetime;
45659c21d95SDavid du Colombier
45704b73bddSDavid du Colombier static void
rebalance(void)45804b73bddSDavid du Colombier rebalance(void)
45904b73bddSDavid du Colombier {
460da51d93aSDavid du Colombier int pri, npri, t, x;
46104b73bddSDavid du Colombier Schedq *rq;
46204b73bddSDavid du Colombier Proc *p;
46304b73bddSDavid du Colombier
46459c21d95SDavid du Colombier t = m->ticks;
46559c21d95SDavid du Colombier if(t - balancetime < HZ)
46659c21d95SDavid du Colombier return;
46759c21d95SDavid du Colombier balancetime = t;
46859c21d95SDavid du Colombier
46959c21d95SDavid du Colombier for(pri=0, rq=runq; pri<Npriq; pri++, rq++){
47059c21d95SDavid du Colombier another:
47104b73bddSDavid du Colombier p = rq->head;
47204b73bddSDavid du Colombier if(p == nil)
47304b73bddSDavid du Colombier continue;
47404b73bddSDavid du Colombier if(p->mp != MACHP(m->machno))
47504b73bddSDavid du Colombier continue;
47659c21d95SDavid du Colombier if(pri == p->basepri)
47704b73bddSDavid du Colombier continue;
47859c21d95SDavid du Colombier updatecpu(p);
47959c21d95SDavid du Colombier npri = reprioritize(p);
48059c21d95SDavid du Colombier if(npri != pri){
481da51d93aSDavid du Colombier x = splhi();
48204b73bddSDavid du Colombier p = dequeueproc(rq, p);
48359c21d95SDavid du Colombier if(p)
48459c21d95SDavid du Colombier queueproc(&runq[npri], p);
485da51d93aSDavid du Colombier splx(x);
48659c21d95SDavid du Colombier goto another;
48704b73bddSDavid du Colombier }
48804b73bddSDavid du Colombier }
48959c21d95SDavid du Colombier }
49059c21d95SDavid du Colombier
49104b73bddSDavid du Colombier
49204b73bddSDavid du Colombier /*
49304b73bddSDavid du Colombier * pick a process to run
49404b73bddSDavid du Colombier */
49504b73bddSDavid du Colombier Proc*
runproc(void)49604b73bddSDavid du Colombier runproc(void)
49704b73bddSDavid du Colombier {
49804b73bddSDavid du Colombier Schedq *rq;
49904b73bddSDavid du Colombier Proc *p;
50004b73bddSDavid du Colombier ulong start, now;
50104b73bddSDavid du Colombier int i;
5020701b922SDavid du Colombier void (*pt)(Proc*, int, vlong);
50304b73bddSDavid du Colombier
50404b73bddSDavid du Colombier start = perfticks();
50504b73bddSDavid du Colombier
50659c21d95SDavid du Colombier /* cooperative scheduling until the clock ticks */
507adc470c1SDavid du Colombier if((p=m->readied) && p->mach==0 && p->state==Ready
5086fb99756SDavid du Colombier && (p->wired == nil || p->wired == m)
50959c21d95SDavid du Colombier && runq[Nrq-1].head == nil && runq[Nrq-2].head == nil){
51059c21d95SDavid du Colombier skipscheds++;
51159c21d95SDavid du Colombier rq = &runq[p->priority];
51259c21d95SDavid du Colombier goto found;
51304b73bddSDavid du Colombier }
51404b73bddSDavid du Colombier
51559c21d95SDavid du Colombier preempts++;
51659c21d95SDavid du Colombier
51704b73bddSDavid du Colombier loop:
51804b73bddSDavid du Colombier /*
51904b73bddSDavid du Colombier * find a process that last ran on this processor (affinity),
52004b73bddSDavid du Colombier * or one that hasn't moved in a while (load balancing). Every
52104b73bddSDavid du Colombier * time around the loop affinity goes down.
52204b73bddSDavid du Colombier */
52304b73bddSDavid du Colombier spllo();
52404b73bddSDavid du Colombier for(i = 0;; i++){
52504b73bddSDavid du Colombier /*
52604b73bddSDavid du Colombier * find the highest priority target process that this
52704b73bddSDavid du Colombier * processor can run given affinity constraints.
52804b73bddSDavid du Colombier *
52904b73bddSDavid du Colombier */
53004b73bddSDavid du Colombier for(rq = &runq[Nrq-1]; rq >= runq; rq--){
53104b73bddSDavid du Colombier for(p = rq->head; p; p = p->rnext){
53204b73bddSDavid du Colombier if(p->mp == nil || p->mp == MACHP(m->machno)
53304b73bddSDavid du Colombier || (!p->wired && i > 0))
53404b73bddSDavid du Colombier goto found;
53504b73bddSDavid du Colombier }
53604b73bddSDavid du Colombier }
53704b73bddSDavid du Colombier
53804b73bddSDavid du Colombier /* waste time or halt the CPU */
53904b73bddSDavid du Colombier idlehands();
54004b73bddSDavid du Colombier
54104b73bddSDavid du Colombier /* remember how much time we're here */
54204b73bddSDavid du Colombier now = perfticks();
54304b73bddSDavid du Colombier m->perf.inidle += now-start;
54404b73bddSDavid du Colombier start = now;
54504b73bddSDavid du Colombier }
54604b73bddSDavid du Colombier
54704b73bddSDavid du Colombier found:
54804b73bddSDavid du Colombier splhi();
54904b73bddSDavid du Colombier p = dequeueproc(rq, p);
55004b73bddSDavid du Colombier if(p == nil)
55104b73bddSDavid du Colombier goto loop;
552219b2ee8SDavid du Colombier
5533e12c5d1SDavid du Colombier p->state = Scheding;
5547dd7cddfSDavid du Colombier p->mp = MACHP(m->machno);
5559a747e4fSDavid du Colombier
556da51d93aSDavid du Colombier if(edflock(p)){
557e288d156SDavid du Colombier edfrun(p, rq == &runq[PriEdf]); /* start deadline timer and do admin */
558e288d156SDavid du Colombier edfunlock();
559e288d156SDavid du Colombier }
560e288d156SDavid du Colombier pt = proctrace;
5610701b922SDavid du Colombier if(pt)
5620701b922SDavid du Colombier pt(p, SRun, 0);
5633e12c5d1SDavid du Colombier return p;
5643e12c5d1SDavid du Colombier }
5653e12c5d1SDavid du Colombier
5663e12c5d1SDavid du Colombier int
canpage(Proc * p)5673e12c5d1SDavid du Colombier canpage(Proc *p)
5683e12c5d1SDavid du Colombier {
5693e12c5d1SDavid du Colombier int ok = 0;
5703e12c5d1SDavid du Colombier
5713e12c5d1SDavid du Colombier splhi();
5727dd7cddfSDavid du Colombier lock(runq);
5733e12c5d1SDavid du Colombier /* Only reliable way to see if we are Running */
5743e12c5d1SDavid du Colombier if(p->mach == 0) {
5753e12c5d1SDavid du Colombier p->newtlb = 1;
5763e12c5d1SDavid du Colombier ok = 1;
5773e12c5d1SDavid du Colombier }
5787dd7cddfSDavid du Colombier unlock(runq);
5793e12c5d1SDavid du Colombier spllo();
5803e12c5d1SDavid du Colombier
5813e12c5d1SDavid du Colombier return ok;
5823e12c5d1SDavid du Colombier }
5833e12c5d1SDavid du Colombier
584*8ccc32efSDavid du Colombier void
noprocpanic(char * msg)585*8ccc32efSDavid du Colombier noprocpanic(char *msg)
586*8ccc32efSDavid du Colombier {
587*8ccc32efSDavid du Colombier /*
588*8ccc32efSDavid du Colombier * setting exiting will make hzclock() on each processor call exit(0).
589*8ccc32efSDavid du Colombier * clearing our bit in machs avoids calling exit(0) from hzclock()
590*8ccc32efSDavid du Colombier * on this processor.
591*8ccc32efSDavid du Colombier */
592*8ccc32efSDavid du Colombier lock(&active);
593*8ccc32efSDavid du Colombier active.machs &= ~(1<<m->machno);
594*8ccc32efSDavid du Colombier active.exiting = 1;
595*8ccc32efSDavid du Colombier unlock(&active);
596*8ccc32efSDavid du Colombier
597*8ccc32efSDavid du Colombier procdump();
598*8ccc32efSDavid du Colombier delay(1000);
599*8ccc32efSDavid du Colombier panic(msg);
600*8ccc32efSDavid du Colombier }
601*8ccc32efSDavid du Colombier
6023e12c5d1SDavid du Colombier Proc*
newproc(void)6033e12c5d1SDavid du Colombier newproc(void)
6043e12c5d1SDavid du Colombier {
60514cc0f53SDavid du Colombier char msg[64];
6063e12c5d1SDavid du Colombier Proc *p;
6073e12c5d1SDavid du Colombier
6083e12c5d1SDavid du Colombier lock(&procalloc);
609*8ccc32efSDavid du Colombier while((p = procalloc.free) == nil) {
610*8ccc32efSDavid du Colombier unlock(&procalloc);
6117dd7cddfSDavid du Colombier
61214cc0f53SDavid du Colombier snprint(msg, sizeof msg, "no procs; %s forking",
61314cc0f53SDavid du Colombier up? up->text: "kernel");
614*8ccc32efSDavid du Colombier /*
615*8ccc32efSDavid du Colombier * the situation is unlikely to heal itself.
616*8ccc32efSDavid du Colombier * dump the proc table and restart by default.
617*8ccc32efSDavid du Colombier * *noprocspersist in plan9.ini will yield the old
618*8ccc32efSDavid du Colombier * behaviour of trying forever.
619*8ccc32efSDavid du Colombier */
620*8ccc32efSDavid du Colombier if(getconf("*noprocspersist") == nil)
621*8ccc32efSDavid du Colombier noprocpanic(msg);
62214cc0f53SDavid du Colombier resrcwait(msg);
6237dd7cddfSDavid du Colombier lock(&procalloc);
6247dd7cddfSDavid du Colombier }
6253e12c5d1SDavid du Colombier procalloc.free = p->qnext;
6267dd7cddfSDavid du Colombier unlock(&procalloc);
6277dd7cddfSDavid du Colombier
6283e12c5d1SDavid du Colombier p->state = Scheding;
6293e12c5d1SDavid du Colombier p->psstate = "New";
6303e12c5d1SDavid du Colombier p->mach = 0;
6313e12c5d1SDavid du Colombier p->qnext = 0;
6323e12c5d1SDavid du Colombier p->nchild = 0;
6333e12c5d1SDavid du Colombier p->nwait = 0;
6343e12c5d1SDavid du Colombier p->waitq = 0;
6359a747e4fSDavid du Colombier p->parent = 0;
6363e12c5d1SDavid du Colombier p->pgrp = 0;
6373e12c5d1SDavid du Colombier p->egrp = 0;
6383e12c5d1SDavid du Colombier p->fgrp = 0;
6397dd7cddfSDavid du Colombier p->rgrp = 0;
6403e12c5d1SDavid du Colombier p->pdbg = 0;
6413e12c5d1SDavid du Colombier p->fpstate = FPinit;
6423e12c5d1SDavid du Colombier p->kp = 0;
643d1be6b08SDavid du Colombier if(up && up->procctl == Proc_tracesyscall)
644d1be6b08SDavid du Colombier p->procctl = Proc_tracesyscall;
645d1be6b08SDavid du Colombier else
6463e12c5d1SDavid du Colombier p->procctl = 0;
647d1be6b08SDavid du Colombier p->syscalltrace = 0;
6483e12c5d1SDavid du Colombier p->notepending = 0;
6497dd7cddfSDavid du Colombier p->ureg = 0;
6509a747e4fSDavid du Colombier p->privatemem = 0;
651b7b24591SDavid du Colombier p->noswap = 0;
6529a747e4fSDavid du Colombier p->errstr = p->errbuf0;
6539a747e4fSDavid du Colombier p->syserrstr = p->errbuf1;
6549a747e4fSDavid du Colombier p->errbuf0[0] = '\0';
6559a747e4fSDavid du Colombier p->errbuf1[0] = '\0';
656e288d156SDavid du Colombier p->nlocks.ref = 0;
6579a747e4fSDavid du Colombier p->delaysched = 0;
658220e960cSDavid du Colombier p->trace = 0;
6599a747e4fSDavid du Colombier kstrdup(&p->user, "*nouser");
6609a747e4fSDavid du Colombier kstrdup(&p->text, "*notext");
6619a747e4fSDavid du Colombier kstrdup(&p->args, "");
6629a747e4fSDavid du Colombier p->nargs = 0;
663d9306527SDavid du Colombier p->setargs = 0;
6643e12c5d1SDavid du Colombier memset(p->seg, 0, sizeof p->seg);
6653e12c5d1SDavid du Colombier p->pid = incref(&pidalloc);
6669a747e4fSDavid du Colombier pidhash(p);
6673e12c5d1SDavid du Colombier p->noteid = incref(¬eidalloc);
6683e12c5d1SDavid du Colombier if(p->pid==0 || p->noteid==0)
6693e12c5d1SDavid du Colombier panic("pidalloc");
6707dd7cddfSDavid du Colombier if(p->kstack == 0)
6717dd7cddfSDavid du Colombier p->kstack = smalloc(KSTACK);
6727dd7cddfSDavid du Colombier
673a6a9e072SDavid du Colombier /* sched params */
674a6a9e072SDavid du Colombier p->mp = 0;
675a6a9e072SDavid du Colombier p->wired = 0;
676a6a9e072SDavid du Colombier procpriority(p, PriNormal, 0);
67795a264b3SDavid du Colombier p->cpu = 0;
67895a264b3SDavid du Colombier p->lastupdate = MACHP(0)->ticks*Scaling;
679e288d156SDavid du Colombier p->edf = nil;
6809a747e4fSDavid du Colombier
6813e12c5d1SDavid du Colombier return p;
6823e12c5d1SDavid du Colombier }
6837dd7cddfSDavid du Colombier
6847dd7cddfSDavid du Colombier /*
6857dd7cddfSDavid du Colombier * wire this proc to a machine
6867dd7cddfSDavid du Colombier */
6877dd7cddfSDavid du Colombier void
procwired(Proc * p,int bm)6887dd7cddfSDavid du Colombier procwired(Proc *p, int bm)
6897dd7cddfSDavid du Colombier {
6907dd7cddfSDavid du Colombier Proc *pp;
6917dd7cddfSDavid du Colombier int i;
6927dd7cddfSDavid du Colombier char nwired[MAXMACH];
6937dd7cddfSDavid du Colombier Mach *wm;
6947dd7cddfSDavid du Colombier
6957dd7cddfSDavid du Colombier if(bm < 0){
6967dd7cddfSDavid du Colombier /* pick a machine to wire to */
6977dd7cddfSDavid du Colombier memset(nwired, 0, sizeof(nwired));
6987dd7cddfSDavid du Colombier p->wired = 0;
6997dd7cddfSDavid du Colombier pp = proctab(0);
7007dd7cddfSDavid du Colombier for(i=0; i<conf.nproc; i++, pp++){
7017dd7cddfSDavid du Colombier wm = pp->wired;
7027dd7cddfSDavid du Colombier if(wm && pp->pid)
7037dd7cddfSDavid du Colombier nwired[wm->machno]++;
7043e12c5d1SDavid du Colombier }
7057dd7cddfSDavid du Colombier bm = 0;
7067dd7cddfSDavid du Colombier for(i=0; i<conf.nmach; i++)
7077dd7cddfSDavid du Colombier if(nwired[i] < nwired[bm])
7087dd7cddfSDavid du Colombier bm = i;
7097dd7cddfSDavid du Colombier } else {
7107dd7cddfSDavid du Colombier /* use the virtual machine requested */
7117dd7cddfSDavid du Colombier bm = bm % conf.nmach;
7127dd7cddfSDavid du Colombier }
7137dd7cddfSDavid du Colombier
7147dd7cddfSDavid du Colombier p->wired = MACHP(bm);
7157dd7cddfSDavid du Colombier p->mp = p->wired;
7163e12c5d1SDavid du Colombier }
7173e12c5d1SDavid du Colombier
7183e12c5d1SDavid du Colombier void
procpriority(Proc * p,int pri,int fixed)719a6a9e072SDavid du Colombier procpriority(Proc *p, int pri, int fixed)
720a6a9e072SDavid du Colombier {
721e288d156SDavid du Colombier if(pri >= Npriq)
722e288d156SDavid du Colombier pri = Npriq - 1;
723a6a9e072SDavid du Colombier else if(pri < 0)
724a6a9e072SDavid du Colombier pri = 0;
725a6a9e072SDavid du Colombier p->basepri = pri;
726a6a9e072SDavid du Colombier p->priority = pri;
727a6a9e072SDavid du Colombier if(fixed){
728a6a9e072SDavid du Colombier p->fixedpri = 1;
729a6a9e072SDavid du Colombier } else {
730a6a9e072SDavid du Colombier p->fixedpri = 0;
731a6a9e072SDavid du Colombier }
732a6a9e072SDavid du Colombier }
733a6a9e072SDavid du Colombier
734a6a9e072SDavid du Colombier void
procinit0(void)7353e12c5d1SDavid du Colombier procinit0(void) /* bad planning - clashes with devproc.c */
7363e12c5d1SDavid du Colombier {
7373e12c5d1SDavid du Colombier Proc *p;
7383e12c5d1SDavid du Colombier int i;
7393e12c5d1SDavid du Colombier
7403e12c5d1SDavid du Colombier procalloc.free = xalloc(conf.nproc*sizeof(Proc));
7414de34a7eSDavid du Colombier if(procalloc.free == nil){
7424de34a7eSDavid du Colombier xsummary();
7434de34a7eSDavid du Colombier panic("cannot allocate %lud procs (%ludMB)\n", conf.nproc, conf.nproc*sizeof(Proc)/(1024*1024));
7444de34a7eSDavid du Colombier }
7453e12c5d1SDavid du Colombier procalloc.arena = procalloc.free;
7463e12c5d1SDavid du Colombier
7473e12c5d1SDavid du Colombier p = procalloc.free;
7483e12c5d1SDavid du Colombier for(i=0; i<conf.nproc-1; i++,p++)
7493e12c5d1SDavid du Colombier p->qnext = p+1;
7503e12c5d1SDavid du Colombier p->qnext = 0;
7513e12c5d1SDavid du Colombier }
7523e12c5d1SDavid du Colombier
7537dd7cddfSDavid du Colombier /*
75459cc4ca5SDavid du Colombier * sleep if a condition is not true. Another process will
75559cc4ca5SDavid du Colombier * awaken us after it sets the condition. When we awaken
75659cc4ca5SDavid du Colombier * the condition may no longer be true.
7577dd7cddfSDavid du Colombier *
75859cc4ca5SDavid du Colombier * we lock both the process and the rendezvous to keep r->p
75959cc4ca5SDavid du Colombier * and p->r synchronized.
7607dd7cddfSDavid du Colombier */
7613e12c5d1SDavid du Colombier void
sleep(Rendez * r,int (* f)(void *),void * arg)7627dd7cddfSDavid du Colombier sleep(Rendez *r, int (*f)(void*), void *arg)
7633e12c5d1SDavid du Colombier {
7643e12c5d1SDavid du Colombier int s;
7650701b922SDavid du Colombier void (*pt)(Proc*, int, vlong);
7663e12c5d1SDavid du Colombier
7673e12c5d1SDavid du Colombier s = splhi();
7683e12c5d1SDavid du Colombier
769e288d156SDavid du Colombier if(up->nlocks.ref)
770567483c8SDavid du Colombier print("process %lud sleeps with %lud locks held, last lock %#p locked at pc %#lux, sleep called from %#p\n",
771da51d93aSDavid du Colombier up->pid, up->nlocks.ref, up->lastlock, up->lastlock->pc, getcallerpc(&r));
77259cc4ca5SDavid du Colombier lock(r);
7737dd7cddfSDavid du Colombier lock(&up->rlock);
7747dd7cddfSDavid du Colombier if(r->p){
775567483c8SDavid du Colombier print("double sleep called from %#p, %lud %lud\n", getcallerpc(&r), r->p->pid, up->pid);
7767dd7cddfSDavid du Colombier dumpstack();
7773e12c5d1SDavid du Colombier }
7783e12c5d1SDavid du Colombier
7793e12c5d1SDavid du Colombier /*
7807dd7cddfSDavid du Colombier * Wakeup only knows there may be something to do by testing
7817dd7cddfSDavid du Colombier * r->p in order to get something to lock on.
7827dd7cddfSDavid du Colombier * Flush that information out to memory in case the sleep is
7837dd7cddfSDavid du Colombier * committed.
7847dd7cddfSDavid du Colombier */
7857dd7cddfSDavid du Colombier r->p = up;
7867dd7cddfSDavid du Colombier
7877dd7cddfSDavid du Colombier if((*f)(arg) || up->notepending){
7887dd7cddfSDavid du Colombier /*
7897dd7cddfSDavid du Colombier * if condition happened or a note is pending
7907dd7cddfSDavid du Colombier * never mind
7917dd7cddfSDavid du Colombier */
7927dd7cddfSDavid du Colombier r->p = nil;
7937dd7cddfSDavid du Colombier unlock(&up->rlock);
79459cc4ca5SDavid du Colombier unlock(r);
7957dd7cddfSDavid du Colombier } else {
7967dd7cddfSDavid du Colombier /*
7973e12c5d1SDavid du Colombier * now we are committed to
7983e12c5d1SDavid du Colombier * change state and call scheduler
7993e12c5d1SDavid du Colombier */
800e288d156SDavid du Colombier pt = proctrace;
8010701b922SDavid du Colombier if(pt)
8020701b922SDavid du Colombier pt(up, SSleep, 0);
8037dd7cddfSDavid du Colombier up->state = Wakeme;
8047dd7cddfSDavid du Colombier up->r = r;
8057dd7cddfSDavid du Colombier
8067dd7cddfSDavid du Colombier /* statistics */
8077dd7cddfSDavid du Colombier m->cs++;
8087dd7cddfSDavid du Colombier
8097dd7cddfSDavid du Colombier procsave(up);
8107dd7cddfSDavid du Colombier if(setlabel(&up->sched)) {
8117dd7cddfSDavid du Colombier /*
8127dd7cddfSDavid du Colombier * here when the process is awakened
8137dd7cddfSDavid du Colombier */
8147dd7cddfSDavid du Colombier procrestore(up);
8157dd7cddfSDavid du Colombier spllo();
8167dd7cddfSDavid du Colombier } else {
8177dd7cddfSDavid du Colombier /*
8187dd7cddfSDavid du Colombier * here to go to sleep (i.e. stop Running)
8197dd7cddfSDavid du Colombier */
8207dd7cddfSDavid du Colombier unlock(&up->rlock);
82159cc4ca5SDavid du Colombier unlock(r);
8227dd7cddfSDavid du Colombier gotolabel(&m->sched);
8233e12c5d1SDavid du Colombier }
8243e12c5d1SDavid du Colombier }
8253e12c5d1SDavid du Colombier
8267dd7cddfSDavid du Colombier if(up->notepending) {
8277dd7cddfSDavid du Colombier up->notepending = 0;
8283e12c5d1SDavid du Colombier splx(s);
8292cca75a1SDavid du Colombier if(up->procctl == Proc_exitme && up->closingfgrp)
8302cca75a1SDavid du Colombier forceclosefgrp();
8313e12c5d1SDavid du Colombier error(Eintr);
8323e12c5d1SDavid du Colombier }
8337dd7cddfSDavid du Colombier
8347dd7cddfSDavid du Colombier splx(s);
8353e12c5d1SDavid du Colombier }
8363e12c5d1SDavid du Colombier
83715174232SDavid du Colombier static int
tfn(void * arg)8383e12c5d1SDavid du Colombier tfn(void *arg)
8393e12c5d1SDavid du Colombier {
840da51d93aSDavid du Colombier return up->trend == nil || up->tfn(arg);
8413e12c5d1SDavid du Colombier }
8423e12c5d1SDavid du Colombier
8433e12c5d1SDavid du Colombier void
twakeup(Ureg *,Timer * t)844e288d156SDavid du Colombier twakeup(Ureg*, Timer *t)
8453e12c5d1SDavid du Colombier {
846e288d156SDavid du Colombier Proc *p;
8478280c5dcSDavid du Colombier Rendez *trend;
8483e12c5d1SDavid du Colombier
849e288d156SDavid du Colombier p = t->ta;
8508280c5dcSDavid du Colombier trend = p->trend;
851e288d156SDavid du Colombier p->trend = 0;
8528280c5dcSDavid du Colombier if(trend)
8538280c5dcSDavid du Colombier wakeup(trend);
854e288d156SDavid du Colombier }
8553e12c5d1SDavid du Colombier
856e288d156SDavid du Colombier void
tsleep(Rendez * r,int (* fn)(void *),void * arg,ulong ms)857e288d156SDavid du Colombier tsleep(Rendez *r, int (*fn)(void*), void *arg, ulong ms)
858e288d156SDavid du Colombier {
859da51d93aSDavid du Colombier if (up->tt){
860567483c8SDavid du Colombier print("tsleep: timer active: mode %d, tf %#p\n", up->tmode, up->tf);
861e288d156SDavid du Colombier timerdel(up);
862da51d93aSDavid du Colombier }
863e288d156SDavid du Colombier up->tns = MS2NS(ms);
864e288d156SDavid du Colombier up->tf = twakeup;
865e288d156SDavid du Colombier up->tmode = Trelative;
866e288d156SDavid du Colombier up->ta = up;
867e288d156SDavid du Colombier up->trend = r;
868e288d156SDavid du Colombier up->tfn = fn;
869e288d156SDavid du Colombier timeradd(up);
870e288d156SDavid du Colombier
871e288d156SDavid du Colombier if(waserror()){
872e288d156SDavid du Colombier timerdel(up);
873e288d156SDavid du Colombier nexterror();
874e288d156SDavid du Colombier }
875e288d156SDavid du Colombier sleep(r, tfn, arg);
876e288d156SDavid du Colombier if(up->tt)
877e288d156SDavid du Colombier timerdel(up);
8787dd7cddfSDavid du Colombier up->twhen = 0;
8797dd7cddfSDavid du Colombier poperror();
8803e12c5d1SDavid du Colombier }
8813e12c5d1SDavid du Colombier
8823e12c5d1SDavid du Colombier /*
88359cc4ca5SDavid du Colombier * Expects that only one process can call wakeup for any given Rendez.
88459cc4ca5SDavid du Colombier * We hold both locks to ensure that r->p and p->r remain consistent.
88559cc4ca5SDavid du Colombier * Richard Miller has a better solution that doesn't require both to
88659cc4ca5SDavid du Colombier * be held simultaneously, but I'm a paranoid - presotto.
8873e12c5d1SDavid du Colombier */
88880ee5cbfSDavid du Colombier Proc*
wakeup(Rendez * r)8893e12c5d1SDavid du Colombier wakeup(Rendez *r)
8903e12c5d1SDavid du Colombier {
8919a747e4fSDavid du Colombier Proc *p;
89280ee5cbfSDavid du Colombier int s;
8937dd7cddfSDavid du Colombier
8943e12c5d1SDavid du Colombier s = splhi();
8957dd7cddfSDavid du Colombier
89659cc4ca5SDavid du Colombier lock(r);
89759cc4ca5SDavid du Colombier p = r->p;
89859cc4ca5SDavid du Colombier
89959cc4ca5SDavid du Colombier if(p != nil){
90059cc4ca5SDavid du Colombier lock(&p->rlock);
901017579bfSDavid du Colombier if(p->state != Wakeme || p->r != r){
902017579bfSDavid du Colombier iprint("%p %p %d\n", p->r, r, p->state);
9033e12c5d1SDavid du Colombier panic("wakeup: state");
904017579bfSDavid du Colombier }
90559cc4ca5SDavid du Colombier r->p = nil;
90659cc4ca5SDavid du Colombier p->r = nil;
9073e12c5d1SDavid du Colombier ready(p);
90859cc4ca5SDavid du Colombier unlock(&p->rlock);
9093e12c5d1SDavid du Colombier }
91059cc4ca5SDavid du Colombier unlock(r);
91159cc4ca5SDavid du Colombier
9123e12c5d1SDavid du Colombier splx(s);
9137dd7cddfSDavid du Colombier
9149a747e4fSDavid du Colombier return p;
9153e12c5d1SDavid du Colombier }
9163e12c5d1SDavid du Colombier
91759cc4ca5SDavid du Colombier /*
91859cc4ca5SDavid du Colombier * if waking a sleeping process, this routine must hold both
91959cc4ca5SDavid du Colombier * p->rlock and r->lock. However, it can't know them in
92059cc4ca5SDavid du Colombier * the same order as wakeup causing a possible lock ordering
92159cc4ca5SDavid du Colombier * deadlock. We break the deadlock by giving up the p->rlock
92259cc4ca5SDavid du Colombier * lock if we can't get the r->lock and retrying.
92359cc4ca5SDavid du Colombier */
9243e12c5d1SDavid du Colombier int
postnote(Proc * p,int dolock,char * n,int flag)9253e12c5d1SDavid du Colombier postnote(Proc *p, int dolock, char *n, int flag)
9263e12c5d1SDavid du Colombier {
9273e12c5d1SDavid du Colombier int s, ret;
9283e12c5d1SDavid du Colombier Rendez *r;
9293e12c5d1SDavid du Colombier Proc *d, **l;
9303e12c5d1SDavid du Colombier
9313e12c5d1SDavid du Colombier if(dolock)
9323e12c5d1SDavid du Colombier qlock(&p->debug);
9333e12c5d1SDavid du Colombier
9347dd7cddfSDavid du Colombier if(flag != NUser && (p->notify == 0 || p->notified))
9357dd7cddfSDavid du Colombier p->nnote = 0;
9363e12c5d1SDavid du Colombier
9373e12c5d1SDavid du Colombier ret = 0;
9387dd7cddfSDavid du Colombier if(p->nnote < NNOTE) {
9397dd7cddfSDavid du Colombier strcpy(p->note[p->nnote].msg, n);
9407dd7cddfSDavid du Colombier p->note[p->nnote++].flag = flag;
9413e12c5d1SDavid du Colombier ret = 1;
9423e12c5d1SDavid du Colombier }
9433e12c5d1SDavid du Colombier p->notepending = 1;
9443e12c5d1SDavid du Colombier if(dolock)
9453e12c5d1SDavid du Colombier qunlock(&p->debug);
9463e12c5d1SDavid du Colombier
94759cc4ca5SDavid du Colombier /* this loop is to avoid lock ordering problems. */
94859cc4ca5SDavid du Colombier for(;;){
9493e12c5d1SDavid du Colombier s = splhi();
9507dd7cddfSDavid du Colombier lock(&p->rlock);
9517dd7cddfSDavid du Colombier r = p->r;
95259cc4ca5SDavid du Colombier
95359cc4ca5SDavid du Colombier /* waiting for a wakeup? */
95459cc4ca5SDavid du Colombier if(r == nil)
95559cc4ca5SDavid du Colombier break; /* no */
95659cc4ca5SDavid du Colombier
95759cc4ca5SDavid du Colombier /* try for the second lock */
95859cc4ca5SDavid du Colombier if(canlock(r)){
95959cc4ca5SDavid du Colombier if(p->state != Wakeme || r->p != p)
9607dd7cddfSDavid du Colombier panic("postnote: state %d %d %d", r->p != p, p->r != r, p->state);
96159cc4ca5SDavid du Colombier p->r = nil;
96259cc4ca5SDavid du Colombier r->p = nil;
9633e12c5d1SDavid du Colombier ready(p);
96459cc4ca5SDavid du Colombier unlock(r);
96559cc4ca5SDavid du Colombier break;
96659cc4ca5SDavid du Colombier }
96759cc4ca5SDavid du Colombier
96859cc4ca5SDavid du Colombier /* give other process time to get out of critical section and try again */
96959cc4ca5SDavid du Colombier unlock(&p->rlock);
97059cc4ca5SDavid du Colombier splx(s);
97159cc4ca5SDavid du Colombier sched();
9723e12c5d1SDavid du Colombier }
9737dd7cddfSDavid du Colombier unlock(&p->rlock);
9743e12c5d1SDavid du Colombier splx(s);
9753e12c5d1SDavid du Colombier
976bd389b36SDavid du Colombier if(p->state != Rendezvous)
977bd389b36SDavid du Colombier return ret;
978bd389b36SDavid du Colombier
979bd389b36SDavid du Colombier /* Try and pull out of a rendezvous */
9807dd7cddfSDavid du Colombier lock(p->rgrp);
9813e12c5d1SDavid du Colombier if(p->state == Rendezvous) {
9823e12c5d1SDavid du Colombier p->rendval = ~0;
9837dd7cddfSDavid du Colombier l = &REND(p->rgrp, p->rendtag);
9843e12c5d1SDavid du Colombier for(d = *l; d; d = d->rendhash) {
9853e12c5d1SDavid du Colombier if(d == p) {
9863e12c5d1SDavid du Colombier *l = p->rendhash;
9873e12c5d1SDavid du Colombier break;
9883e12c5d1SDavid du Colombier }
9893e12c5d1SDavid du Colombier l = &d->rendhash;
9903e12c5d1SDavid du Colombier }
9917dd7cddfSDavid du Colombier ready(p);
9923e12c5d1SDavid du Colombier }
9937dd7cddfSDavid du Colombier unlock(p->rgrp);
9943e12c5d1SDavid du Colombier return ret;
9953e12c5d1SDavid du Colombier }
9963e12c5d1SDavid du Colombier
9973e12c5d1SDavid du Colombier /*
9983e12c5d1SDavid du Colombier * weird thing: keep at most NBROKEN around
9993e12c5d1SDavid du Colombier */
10003e12c5d1SDavid du Colombier #define NBROKEN 4
1001bd389b36SDavid du Colombier struct
1002bd389b36SDavid du Colombier {
1003bd389b36SDavid du Colombier QLock;
10043e12c5d1SDavid du Colombier int n;
10053e12c5d1SDavid du Colombier Proc *p[NBROKEN];
10063e12c5d1SDavid du Colombier }broken;
10073e12c5d1SDavid du Colombier
10083e12c5d1SDavid du Colombier void
addbroken(Proc * p)1009bd389b36SDavid du Colombier addbroken(Proc *p)
10103e12c5d1SDavid du Colombier {
1011bd389b36SDavid du Colombier qlock(&broken);
10123e12c5d1SDavid du Colombier if(broken.n == NBROKEN) {
10133e12c5d1SDavid du Colombier ready(broken.p[0]);
10143e12c5d1SDavid du Colombier memmove(&broken.p[0], &broken.p[1], sizeof(Proc*)*(NBROKEN-1));
10153e12c5d1SDavid du Colombier --broken.n;
10163e12c5d1SDavid du Colombier }
1017bd389b36SDavid du Colombier broken.p[broken.n++] = p;
1018bd389b36SDavid du Colombier qunlock(&broken);
1019bd389b36SDavid du Colombier
1020e288d156SDavid du Colombier edfstop(up);
1021bd389b36SDavid du Colombier p->state = Broken;
1022bd389b36SDavid du Colombier p->psstate = 0;
1023bd389b36SDavid du Colombier sched();
1024bd389b36SDavid du Colombier }
1025bd389b36SDavid du Colombier
1026bd389b36SDavid du Colombier void
unbreak(Proc * p)1027bd389b36SDavid du Colombier unbreak(Proc *p)
1028bd389b36SDavid du Colombier {
1029bd389b36SDavid du Colombier int b;
1030bd389b36SDavid du Colombier
1031bd389b36SDavid du Colombier qlock(&broken);
1032bd389b36SDavid du Colombier for(b=0; b < broken.n; b++)
1033bd389b36SDavid du Colombier if(broken.p[b] == p) {
10343e12c5d1SDavid du Colombier broken.n--;
1035bd389b36SDavid du Colombier memmove(&broken.p[b], &broken.p[b+1],
1036bd389b36SDavid du Colombier sizeof(Proc*)*(NBROKEN-(b+1)));
1037bd389b36SDavid du Colombier ready(p);
10383e12c5d1SDavid du Colombier break;
10393e12c5d1SDavid du Colombier }
1040bd389b36SDavid du Colombier qunlock(&broken);
10413e12c5d1SDavid du Colombier }
10423e12c5d1SDavid du Colombier
10433e12c5d1SDavid du Colombier int
freebroken(void)10443e12c5d1SDavid du Colombier freebroken(void)
10453e12c5d1SDavid du Colombier {
10463e12c5d1SDavid du Colombier int i, n;
10473e12c5d1SDavid du Colombier
1048bd389b36SDavid du Colombier qlock(&broken);
10493e12c5d1SDavid du Colombier n = broken.n;
1050bd389b36SDavid du Colombier for(i=0; i<n; i++) {
10513e12c5d1SDavid du Colombier ready(broken.p[i]);
1052bd389b36SDavid du Colombier broken.p[i] = 0;
1053bd389b36SDavid du Colombier }
10543e12c5d1SDavid du Colombier broken.n = 0;
1055bd389b36SDavid du Colombier qunlock(&broken);
10563e12c5d1SDavid du Colombier return n;
10573e12c5d1SDavid du Colombier }
10583e12c5d1SDavid du Colombier
10593e12c5d1SDavid du Colombier void
pexit(char * exitstr,int freemem)10603e12c5d1SDavid du Colombier pexit(char *exitstr, int freemem)
10613e12c5d1SDavid du Colombier {
10627dd7cddfSDavid du Colombier Proc *p;
1063bd389b36SDavid du Colombier Segment **s, **es;
10647dd7cddfSDavid du Colombier long utime, stime;
10653e12c5d1SDavid du Colombier Waitq *wq, *f, *next;
10667dd7cddfSDavid du Colombier Fgrp *fgrp;
10677dd7cddfSDavid du Colombier Egrp *egrp;
10687dd7cddfSDavid du Colombier Rgrp *rgrp;
10697dd7cddfSDavid du Colombier Pgrp *pgrp;
10707dd7cddfSDavid du Colombier Chan *dot;
10710701b922SDavid du Colombier void (*pt)(Proc*, int, vlong);
10723e12c5d1SDavid du Colombier
1073d1be6b08SDavid du Colombier if(up->syscalltrace)
1074d1be6b08SDavid du Colombier free(up->syscalltrace);
10757dd7cddfSDavid du Colombier up->alarm = 0;
1076e288d156SDavid du Colombier if (up->tt)
1077e288d156SDavid du Colombier timerdel(up);
1078e288d156SDavid du Colombier pt = proctrace;
10790701b922SDavid du Colombier if(pt)
10800701b922SDavid du Colombier pt(up, SDead, 0);
10813e12c5d1SDavid du Colombier
10827dd7cddfSDavid du Colombier /* nil out all the resources under lock (free later) */
10837dd7cddfSDavid du Colombier qlock(&up->debug);
10847dd7cddfSDavid du Colombier fgrp = up->fgrp;
10857dd7cddfSDavid du Colombier up->fgrp = nil;
10867dd7cddfSDavid du Colombier egrp = up->egrp;
10877dd7cddfSDavid du Colombier up->egrp = nil;
10887dd7cddfSDavid du Colombier rgrp = up->rgrp;
10897dd7cddfSDavid du Colombier up->rgrp = nil;
10907dd7cddfSDavid du Colombier pgrp = up->pgrp;
10917dd7cddfSDavid du Colombier up->pgrp = nil;
10927dd7cddfSDavid du Colombier dot = up->dot;
10937dd7cddfSDavid du Colombier up->dot = nil;
10947dd7cddfSDavid du Colombier qunlock(&up->debug);
10957dd7cddfSDavid du Colombier
10967dd7cddfSDavid du Colombier if(fgrp)
10977dd7cddfSDavid du Colombier closefgrp(fgrp);
10987dd7cddfSDavid du Colombier if(egrp)
10997dd7cddfSDavid du Colombier closeegrp(egrp);
11007dd7cddfSDavid du Colombier if(rgrp)
11017dd7cddfSDavid du Colombier closergrp(rgrp);
11027dd7cddfSDavid du Colombier if(dot)
11037dd7cddfSDavid du Colombier cclose(dot);
11047dd7cddfSDavid du Colombier if(pgrp)
11057dd7cddfSDavid du Colombier closepgrp(pgrp);
11063e12c5d1SDavid du Colombier
11073e12c5d1SDavid du Colombier /*
11083e12c5d1SDavid du Colombier * if not a kernel process and have a parent,
11093e12c5d1SDavid du Colombier * do some housekeeping.
11103e12c5d1SDavid du Colombier */
11117dd7cddfSDavid du Colombier if(up->kp == 0) {
11127dd7cddfSDavid du Colombier p = up->parent;
1113bd389b36SDavid du Colombier if(p == 0) {
11143e12c5d1SDavid du Colombier if(exitstr == 0)
11153e12c5d1SDavid du Colombier exitstr = "unknown";
11163e12c5d1SDavid du Colombier panic("boot process died: %s", exitstr);
11173e12c5d1SDavid du Colombier }
11183e12c5d1SDavid du Colombier
11193e12c5d1SDavid du Colombier while(waserror())
11203e12c5d1SDavid du Colombier ;
11217dd7cddfSDavid du Colombier
11223e12c5d1SDavid du Colombier wq = smalloc(sizeof(Waitq));
11233e12c5d1SDavid du Colombier poperror();
11243e12c5d1SDavid du Colombier
11259a747e4fSDavid du Colombier wq->w.pid = up->pid;
1126b7b24591SDavid du Colombier utime = up->time[TUser] + up->time[TCUser];
1127b7b24591SDavid du Colombier stime = up->time[TSys] + up->time[TCSys];
11283ff48bf5SDavid du Colombier wq->w.time[TUser] = tk2ms(utime);
11293ff48bf5SDavid du Colombier wq->w.time[TSys] = tk2ms(stime);
11303ff48bf5SDavid du Colombier wq->w.time[TReal] = tk2ms(MACHP(0)->ticks - up->time[TReal]);
11319a747e4fSDavid du Colombier if(exitstr && exitstr[0])
11329a747e4fSDavid du Colombier snprint(wq->w.msg, sizeof(wq->w.msg), "%s %lud: %s", up->text, up->pid, exitstr);
1133bd389b36SDavid du Colombier else
11343e12c5d1SDavid du Colombier wq->w.msg[0] = '\0';
11353e12c5d1SDavid du Colombier
11363e12c5d1SDavid du Colombier lock(&p->exl);
11377dd7cddfSDavid du Colombier /*
1138017579bfSDavid du Colombier * Check that parent is still alive.
11393e12c5d1SDavid du Colombier */
1140017579bfSDavid du Colombier if(p->pid == up->parentpid && p->state != Broken) {
11413e12c5d1SDavid du Colombier p->nchild--;
11423e12c5d1SDavid du Colombier p->time[TCUser] += utime;
11433e12c5d1SDavid du Colombier p->time[TCSys] += stime;
1144017579bfSDavid du Colombier /*
1145017579bfSDavid du Colombier * If there would be more than 128 wait records
1146017579bfSDavid du Colombier * processes for my parent, then don't leave a wait
1147017579bfSDavid du Colombier * record behind. This helps prevent badly written
1148017579bfSDavid du Colombier * daemon processes from accumulating lots of wait
1149017579bfSDavid du Colombier * records.
1150017579bfSDavid du Colombier */
1151017579bfSDavid du Colombier if(p->nwait < 128) {
11523e12c5d1SDavid du Colombier wq->next = p->waitq;
11533e12c5d1SDavid du Colombier p->waitq = wq;
11543e12c5d1SDavid du Colombier p->nwait++;
1155017579bfSDavid du Colombier wq = nil;
11563e12c5d1SDavid du Colombier wakeup(&p->waitr);
11573e12c5d1SDavid du Colombier }
1158017579bfSDavid du Colombier }
11593e12c5d1SDavid du Colombier unlock(&p->exl);
1160017579bfSDavid du Colombier if(wq)
11613e12c5d1SDavid du Colombier free(wq);
11623e12c5d1SDavid du Colombier }
11633e12c5d1SDavid du Colombier
11643e12c5d1SDavid du Colombier if(!freemem)
11657dd7cddfSDavid du Colombier addbroken(up);
11663e12c5d1SDavid du Colombier
11677dd7cddfSDavid du Colombier qlock(&up->seglock);
11687dd7cddfSDavid du Colombier es = &up->seg[NSEG];
11697dd7cddfSDavid du Colombier for(s = up->seg; s < es; s++) {
11707dd7cddfSDavid du Colombier if(*s) {
1171bd389b36SDavid du Colombier putseg(*s);
11727dd7cddfSDavid du Colombier *s = 0;
11737dd7cddfSDavid du Colombier }
11747dd7cddfSDavid du Colombier }
11757dd7cddfSDavid du Colombier qunlock(&up->seglock);
11763e12c5d1SDavid du Colombier
11777dd7cddfSDavid du Colombier lock(&up->exl); /* Prevent my children from leaving waits */
11789a747e4fSDavid du Colombier pidunhash(up);
11797dd7cddfSDavid du Colombier up->pid = 0;
11807dd7cddfSDavid du Colombier wakeup(&up->waitr);
11817dd7cddfSDavid du Colombier unlock(&up->exl);
11823e12c5d1SDavid du Colombier
11837dd7cddfSDavid du Colombier for(f = up->waitq; f; f = next) {
11843e12c5d1SDavid du Colombier next = f->next;
11853e12c5d1SDavid du Colombier free(f);
11863e12c5d1SDavid du Colombier }
11873e12c5d1SDavid du Colombier
11883e12c5d1SDavid du Colombier /* release debuggers */
11897dd7cddfSDavid du Colombier qlock(&up->debug);
11907dd7cddfSDavid du Colombier if(up->pdbg) {
11917dd7cddfSDavid du Colombier wakeup(&up->pdbg->sleep);
11927dd7cddfSDavid du Colombier up->pdbg = 0;
11933e12c5d1SDavid du Colombier }
11947dd7cddfSDavid du Colombier qunlock(&up->debug);
11953e12c5d1SDavid du Colombier
11967dd7cddfSDavid du Colombier /* Sched must not loop for these locks */
11973e12c5d1SDavid du Colombier lock(&procalloc);
11983e12c5d1SDavid du Colombier lock(&palloc);
11993e12c5d1SDavid du Colombier
1200e288d156SDavid du Colombier edfstop(up);
12017dd7cddfSDavid du Colombier up->state = Moribund;
12023e12c5d1SDavid du Colombier sched();
12033e12c5d1SDavid du Colombier panic("pexit");
12043e12c5d1SDavid du Colombier }
12053e12c5d1SDavid du Colombier
12063e12c5d1SDavid du Colombier int
haswaitq(void * x)12073e12c5d1SDavid du Colombier haswaitq(void *x)
12083e12c5d1SDavid du Colombier {
12093e12c5d1SDavid du Colombier Proc *p;
12103e12c5d1SDavid du Colombier
12113e12c5d1SDavid du Colombier p = (Proc *)x;
12123e12c5d1SDavid du Colombier return p->waitq != 0;
12133e12c5d1SDavid du Colombier }
12143e12c5d1SDavid du Colombier
12153e12c5d1SDavid du Colombier ulong
pwait(Waitmsg * w)12163e12c5d1SDavid du Colombier pwait(Waitmsg *w)
12173e12c5d1SDavid du Colombier {
12183e12c5d1SDavid du Colombier ulong cpid;
12193e12c5d1SDavid du Colombier Waitq *wq;
12203e12c5d1SDavid du Colombier
12217dd7cddfSDavid du Colombier if(!canqlock(&up->qwaitr))
1222219b2ee8SDavid du Colombier error(Einuse);
1223219b2ee8SDavid du Colombier
1224219b2ee8SDavid du Colombier if(waserror()) {
12257dd7cddfSDavid du Colombier qunlock(&up->qwaitr);
1226219b2ee8SDavid du Colombier nexterror();
1227219b2ee8SDavid du Colombier }
1228219b2ee8SDavid du Colombier
12297dd7cddfSDavid du Colombier lock(&up->exl);
12307dd7cddfSDavid du Colombier if(up->nchild == 0 && up->waitq == 0) {
12317dd7cddfSDavid du Colombier unlock(&up->exl);
12323e12c5d1SDavid du Colombier error(Enochild);
12333e12c5d1SDavid du Colombier }
12347dd7cddfSDavid du Colombier unlock(&up->exl);
12353e12c5d1SDavid du Colombier
12367dd7cddfSDavid du Colombier sleep(&up->waitr, haswaitq, up);
12373e12c5d1SDavid du Colombier
12387dd7cddfSDavid du Colombier lock(&up->exl);
12397dd7cddfSDavid du Colombier wq = up->waitq;
12407dd7cddfSDavid du Colombier up->waitq = wq->next;
12417dd7cddfSDavid du Colombier up->nwait--;
12427dd7cddfSDavid du Colombier unlock(&up->exl);
12433e12c5d1SDavid du Colombier
12447dd7cddfSDavid du Colombier qunlock(&up->qwaitr);
1245219b2ee8SDavid du Colombier poperror();
1246219b2ee8SDavid du Colombier
12473e12c5d1SDavid du Colombier if(w)
12483e12c5d1SDavid du Colombier memmove(w, &wq->w, sizeof(Waitmsg));
12499a747e4fSDavid du Colombier cpid = wq->w.pid;
12503e12c5d1SDavid du Colombier free(wq);
12513e12c5d1SDavid du Colombier return cpid;
12523e12c5d1SDavid du Colombier }
12533e12c5d1SDavid du Colombier
12543e12c5d1SDavid du Colombier Proc*
proctab(int i)12553e12c5d1SDavid du Colombier proctab(int i)
12563e12c5d1SDavid du Colombier {
12573e12c5d1SDavid du Colombier return &procalloc.arena[i];
12583e12c5d1SDavid du Colombier }
12593e12c5d1SDavid du Colombier
12603e12c5d1SDavid du Colombier void
dumpaproc(Proc * p)12617dd7cddfSDavid du Colombier dumpaproc(Proc *p)
12623e12c5d1SDavid du Colombier {
12633e12c5d1SDavid du Colombier ulong bss;
12647dd7cddfSDavid du Colombier char *s;
12653e12c5d1SDavid du Colombier
12667dd7cddfSDavid du Colombier if(p == 0)
12677dd7cddfSDavid du Colombier return;
12687dd7cddfSDavid du Colombier
12693e12c5d1SDavid du Colombier bss = 0;
12703e12c5d1SDavid du Colombier if(p->seg[BSEG])
12713e12c5d1SDavid du Colombier bss = p->seg[BSEG]->top;
12723e12c5d1SDavid du Colombier
12733e12c5d1SDavid du Colombier s = p->psstate;
12743e12c5d1SDavid du Colombier if(s == 0)
127580ee5cbfSDavid du Colombier s = statename[p->state];
1276a6a9e072SDavid du Colombier print("%3lud:%10s pc %8lux dbgpc %8lux %8s (%s) ut %ld st %ld bss %lux qpc %lux nl %lud nd %lud lpc %lux pri %lud\n",
12777dd7cddfSDavid du Colombier p->pid, p->text, p->pc, dbgpc(p), s, statename[p->state],
1278e288d156SDavid du Colombier p->time[0], p->time[1], bss, p->qpc, p->nlocks.ref, p->delaysched, p->lastlock ? p->lastlock->pc : 0, p->priority);
12797dd7cddfSDavid du Colombier }
12807dd7cddfSDavid du Colombier
12817dd7cddfSDavid du Colombier void
procdump(void)12827dd7cddfSDavid du Colombier procdump(void)
12837dd7cddfSDavid du Colombier {
12847dd7cddfSDavid du Colombier int i;
12857dd7cddfSDavid du Colombier Proc *p;
12867dd7cddfSDavid du Colombier
12877dd7cddfSDavid du Colombier if(up)
12887dd7cddfSDavid du Colombier print("up %lud\n", up->pid);
12897dd7cddfSDavid du Colombier else
12907dd7cddfSDavid du Colombier print("no current process\n");
12917dd7cddfSDavid du Colombier for(i=0; i<conf.nproc; i++) {
12927dd7cddfSDavid du Colombier p = &procalloc.arena[i];
12937dd7cddfSDavid du Colombier if(p->state == Dead)
12947dd7cddfSDavid du Colombier continue;
12957dd7cddfSDavid du Colombier
12967dd7cddfSDavid du Colombier dumpaproc(p);
12973e12c5d1SDavid du Colombier }
12983e12c5d1SDavid du Colombier }
12997dd7cddfSDavid du Colombier
13007dd7cddfSDavid du Colombier /*
13017dd7cddfSDavid du Colombier * wait till all processes have flushed their mmu
13027dd7cddfSDavid du Colombier * state about segement s
13037dd7cddfSDavid du Colombier */
13047dd7cddfSDavid du Colombier void
procflushseg(Segment * s)13057dd7cddfSDavid du Colombier procflushseg(Segment *s)
13067dd7cddfSDavid du Colombier {
13077dd7cddfSDavid du Colombier int i, ns, nm, nwait;
13087dd7cddfSDavid du Colombier Proc *p;
13097dd7cddfSDavid du Colombier
13107dd7cddfSDavid du Colombier /*
13117dd7cddfSDavid du Colombier * tell all processes with this
13127dd7cddfSDavid du Colombier * segment to flush their mmu's
13137dd7cddfSDavid du Colombier */
13147dd7cddfSDavid du Colombier nwait = 0;
13157dd7cddfSDavid du Colombier for(i=0; i<conf.nproc; i++) {
13167dd7cddfSDavid du Colombier p = &procalloc.arena[i];
13177dd7cddfSDavid du Colombier if(p->state == Dead)
13187dd7cddfSDavid du Colombier continue;
13197dd7cddfSDavid du Colombier for(ns = 0; ns < NSEG; ns++)
13207dd7cddfSDavid du Colombier if(p->seg[ns] == s){
13217dd7cddfSDavid du Colombier p->newtlb = 1;
13227dd7cddfSDavid du Colombier for(nm = 0; nm < conf.nmach; nm++){
13237dd7cddfSDavid du Colombier if(MACHP(nm)->proc == p){
13247dd7cddfSDavid du Colombier MACHP(nm)->flushmmu = 1;
13257dd7cddfSDavid du Colombier nwait++;
13267dd7cddfSDavid du Colombier }
13277dd7cddfSDavid du Colombier }
13287dd7cddfSDavid du Colombier break;
13297dd7cddfSDavid du Colombier }
13307dd7cddfSDavid du Colombier }
13317dd7cddfSDavid du Colombier
13327dd7cddfSDavid du Colombier if(nwait == 0)
13337dd7cddfSDavid du Colombier return;
13347dd7cddfSDavid du Colombier
13357dd7cddfSDavid du Colombier /*
13367dd7cddfSDavid du Colombier * wait for all processors to take a clock interrupt
13377dd7cddfSDavid du Colombier * and flush their mmu's
13387dd7cddfSDavid du Colombier */
13397dd7cddfSDavid du Colombier for(nm = 0; nm < conf.nmach; nm++)
13407dd7cddfSDavid du Colombier if(MACHP(nm) != m)
13417dd7cddfSDavid du Colombier while(MACHP(nm)->flushmmu)
13427dd7cddfSDavid du Colombier sched();
13437dd7cddfSDavid du Colombier }
13447dd7cddfSDavid du Colombier
13457dd7cddfSDavid du Colombier void
scheddump(void)13467dd7cddfSDavid du Colombier scheddump(void)
13477dd7cddfSDavid du Colombier {
13487dd7cddfSDavid du Colombier Proc *p;
13497dd7cddfSDavid du Colombier Schedq *rq;
13507dd7cddfSDavid du Colombier
13517dd7cddfSDavid du Colombier for(rq = &runq[Nrq-1]; rq >= runq; rq--){
1352219b2ee8SDavid du Colombier if(rq->head == 0)
1353219b2ee8SDavid du Colombier continue;
13547dd7cddfSDavid du Colombier print("rq%ld:", rq-runq);
1355219b2ee8SDavid du Colombier for(p = rq->head; p; p = p->rnext)
1356a6a9e072SDavid du Colombier print(" %lud(%lud)", p->pid, m->ticks - p->readytime);
1357219b2ee8SDavid du Colombier print("\n");
13587dd7cddfSDavid du Colombier delay(150);
1359219b2ee8SDavid du Colombier }
1360219b2ee8SDavid du Colombier print("nrdy %d\n", nrdy);
13613e12c5d1SDavid du Colombier }
13623e12c5d1SDavid du Colombier
13633e12c5d1SDavid du Colombier void
kproc(char * name,void (* func)(void *),void * arg)13643e12c5d1SDavid du Colombier kproc(char *name, void (*func)(void *), void *arg)
13653e12c5d1SDavid du Colombier {
13663e12c5d1SDavid du Colombier Proc *p;
13673e12c5d1SDavid du Colombier static Pgrp *kpgrp;
13683e12c5d1SDavid du Colombier
13693e12c5d1SDavid du Colombier p = newproc();
13709a747e4fSDavid du Colombier p->psstate = 0;
13719a747e4fSDavid du Colombier p->procmode = 0640;
13723e12c5d1SDavid du Colombier p->kp = 1;
1373b7b24591SDavid du Colombier p->noswap = 1;
13743e12c5d1SDavid du Colombier
13757dd7cddfSDavid du Colombier p->fpsave = up->fpsave;
13767dd7cddfSDavid du Colombier p->scallnr = up->scallnr;
13777dd7cddfSDavid du Colombier p->s = up->s;
13787dd7cddfSDavid du Colombier p->nerrlab = 0;
13797dd7cddfSDavid du Colombier p->slash = up->slash;
13807dd7cddfSDavid du Colombier p->dot = up->dot;
13812cca75a1SDavid du Colombier if(p->dot)
13827dd7cddfSDavid du Colombier incref(p->dot);
13837dd7cddfSDavid du Colombier
13847dd7cddfSDavid du Colombier memmove(p->note, up->note, sizeof(p->note));
13857dd7cddfSDavid du Colombier p->nnote = up->nnote;
13867dd7cddfSDavid du Colombier p->notified = 0;
13877dd7cddfSDavid du Colombier p->lastnote = up->lastnote;
13887dd7cddfSDavid du Colombier p->notify = up->notify;
13897dd7cddfSDavid du Colombier p->ureg = 0;
13907dd7cddfSDavid du Colombier p->dbgreg = 0;
13913e12c5d1SDavid du Colombier
1392a6a9e072SDavid du Colombier procpriority(p, PriKproc, 0);
1393219b2ee8SDavid du Colombier
13947dd7cddfSDavid du Colombier kprocchild(p, func, arg);
13953e12c5d1SDavid du Colombier
13969a747e4fSDavid du Colombier kstrdup(&p->user, eve);
13979a747e4fSDavid du Colombier kstrdup(&p->text, name);
13987dd7cddfSDavid du Colombier if(kpgrp == 0)
13993e12c5d1SDavid du Colombier kpgrp = newpgrp();
14003e12c5d1SDavid du Colombier p->pgrp = kpgrp;
14013e12c5d1SDavid du Colombier incref(kpgrp);
14023e12c5d1SDavid du Colombier
14033e12c5d1SDavid du Colombier memset(p->time, 0, sizeof(p->time));
14043e12c5d1SDavid du Colombier p->time[TReal] = MACHP(0)->ticks;
14053e12c5d1SDavid du Colombier ready(p);
14063e12c5d1SDavid du Colombier }
14073e12c5d1SDavid du Colombier
14083e12c5d1SDavid du Colombier /*
14093e12c5d1SDavid du Colombier * called splhi() by notify(). See comment in notify for the
14103e12c5d1SDavid du Colombier * reasoning.
14113e12c5d1SDavid du Colombier */
14123e12c5d1SDavid du Colombier void
procctl(Proc * p)14133e12c5d1SDavid du Colombier procctl(Proc *p)
14143e12c5d1SDavid du Colombier {
14153e12c5d1SDavid du Colombier char *state;
1416219b2ee8SDavid du Colombier ulong s;
14173e12c5d1SDavid du Colombier
14183e12c5d1SDavid du Colombier switch(p->procctl) {
14197dd7cddfSDavid du Colombier case Proc_exitbig:
14207dd7cddfSDavid du Colombier spllo();
14217dd7cddfSDavid du Colombier pexit("Killed: Insufficient physical memory", 1);
14227dd7cddfSDavid du Colombier
14233e12c5d1SDavid du Colombier case Proc_exitme:
14243e12c5d1SDavid du Colombier spllo(); /* pexit has locks in it */
14253e12c5d1SDavid du Colombier pexit("Killed", 1);
14263e12c5d1SDavid du Colombier
14273e12c5d1SDavid du Colombier case Proc_traceme:
14287dd7cddfSDavid du Colombier if(p->nnote == 0)
14293e12c5d1SDavid du Colombier return;
14303e12c5d1SDavid du Colombier /* No break */
14313e12c5d1SDavid du Colombier
14323e12c5d1SDavid du Colombier case Proc_stopme:
14333e12c5d1SDavid du Colombier p->procctl = 0;
14343e12c5d1SDavid du Colombier state = p->psstate;
14353e12c5d1SDavid du Colombier p->psstate = "Stopped";
14363e12c5d1SDavid du Colombier /* free a waiting debugger */
1437219b2ee8SDavid du Colombier s = spllo();
14383e12c5d1SDavid du Colombier qlock(&p->debug);
14393e12c5d1SDavid du Colombier if(p->pdbg) {
14403e12c5d1SDavid du Colombier wakeup(&p->pdbg->sleep);
14413e12c5d1SDavid du Colombier p->pdbg = 0;
14423e12c5d1SDavid du Colombier }
14433e12c5d1SDavid du Colombier qunlock(&p->debug);
14443e12c5d1SDavid du Colombier splhi();
1445219b2ee8SDavid du Colombier p->state = Stopped;
1446219b2ee8SDavid du Colombier sched();
14473e12c5d1SDavid du Colombier p->psstate = state;
1448219b2ee8SDavid du Colombier splx(s);
14493e12c5d1SDavid du Colombier return;
14503e12c5d1SDavid du Colombier }
14513e12c5d1SDavid du Colombier }
14523e12c5d1SDavid du Colombier
14533e12c5d1SDavid du Colombier #include "errstr.h"
14543e12c5d1SDavid du Colombier
14553e12c5d1SDavid du Colombier void
error(char * err)14563e12c5d1SDavid du Colombier error(char *err)
14573e12c5d1SDavid du Colombier {
1458219b2ee8SDavid du Colombier spllo();
1459dc5a79c1SDavid du Colombier
1460dc5a79c1SDavid du Colombier assert(up->nerrlab < NERR);
14619a747e4fSDavid du Colombier kstrcpy(up->errstr, err, ERRMAX);
14629a747e4fSDavid du Colombier setlabel(&up->errlab[NERR-1]);
14633e12c5d1SDavid du Colombier nexterror();
14643e12c5d1SDavid du Colombier }
14653e12c5d1SDavid du Colombier
14663e12c5d1SDavid du Colombier void
nexterror(void)14673e12c5d1SDavid du Colombier nexterror(void)
14683e12c5d1SDavid du Colombier {
14697dd7cddfSDavid du Colombier gotolabel(&up->errlab[--up->nerrlab]);
14703e12c5d1SDavid du Colombier }
14713e12c5d1SDavid du Colombier
14723e12c5d1SDavid du Colombier void
exhausted(char * resource)14733e12c5d1SDavid du Colombier exhausted(char *resource)
14743e12c5d1SDavid du Colombier {
14759a747e4fSDavid du Colombier char buf[ERRMAX];
14763e12c5d1SDavid du Colombier
1477f755faa2SDavid du Colombier snprint(buf, sizeof buf, "no free %s", resource);
14787dd7cddfSDavid du Colombier iprint("%s\n", buf);
14793e12c5d1SDavid du Colombier error(buf);
14803e12c5d1SDavid du Colombier }
14817dd7cddfSDavid du Colombier
14827dd7cddfSDavid du Colombier void
killbig(char * why)1483cd42b314SDavid du Colombier killbig(char *why)
14847dd7cddfSDavid du Colombier {
14857dd7cddfSDavid du Colombier int i;
14867dd7cddfSDavid du Colombier Segment *s;
14877dd7cddfSDavid du Colombier ulong l, max;
14887dd7cddfSDavid du Colombier Proc *p, *ep, *kp;
14897dd7cddfSDavid du Colombier
14907dd7cddfSDavid du Colombier max = 0;
14917dd7cddfSDavid du Colombier kp = 0;
14927dd7cddfSDavid du Colombier ep = procalloc.arena+conf.nproc;
14937dd7cddfSDavid du Colombier for(p = procalloc.arena; p < ep; p++) {
14947dd7cddfSDavid du Colombier if(p->state == Dead || p->kp)
14957dd7cddfSDavid du Colombier continue;
14967dd7cddfSDavid du Colombier l = 0;
14977dd7cddfSDavid du Colombier for(i=1; i<NSEG; i++) {
14987dd7cddfSDavid du Colombier s = p->seg[i];
14997dd7cddfSDavid du Colombier if(s != 0)
15007dd7cddfSDavid du Colombier l += s->top - s->base;
15017dd7cddfSDavid du Colombier }
1502cd42b314SDavid du Colombier if(l > max && ((p->procmode&0222) || strcmp(eve, p->user)!=0)) {
15037dd7cddfSDavid du Colombier kp = p;
15047dd7cddfSDavid du Colombier max = l;
15057dd7cddfSDavid du Colombier }
15067dd7cddfSDavid du Colombier }
1507cd42b314SDavid du Colombier
1508cd42b314SDavid du Colombier print("%lud: %s killed: %s\n", kp->pid, kp->text, why);
1509cd42b314SDavid du Colombier for(p = procalloc.arena; p < ep; p++) {
1510cd42b314SDavid du Colombier if(p->state == Dead || p->kp)
1511cd42b314SDavid du Colombier continue;
1512cd42b314SDavid du Colombier if(p != kp && p->seg[BSEG] && p->seg[BSEG] == kp->seg[BSEG])
1513cd42b314SDavid du Colombier p->procctl = Proc_exitbig;
1514cd42b314SDavid du Colombier }
15157dd7cddfSDavid du Colombier kp->procctl = Proc_exitbig;
15167dd7cddfSDavid du Colombier for(i = 0; i < NSEG; i++) {
15177dd7cddfSDavid du Colombier s = kp->seg[i];
15187dd7cddfSDavid du Colombier if(s != 0 && canqlock(&s->lk)) {
15197dd7cddfSDavid du Colombier mfreeseg(s, s->base, (s->top - s->base)/BY2PG);
15207dd7cddfSDavid du Colombier qunlock(&s->lk);
15217dd7cddfSDavid du Colombier }
15227dd7cddfSDavid du Colombier }
15237dd7cddfSDavid du Colombier }
15247dd7cddfSDavid du Colombier
15257dd7cddfSDavid du Colombier /*
15267dd7cddfSDavid du Colombier * change ownership to 'new' of all processes owned by 'old'. Used when
15277dd7cddfSDavid du Colombier * eve changes.
15287dd7cddfSDavid du Colombier */
15297dd7cddfSDavid du Colombier void
renameuser(char * old,char * new)15307dd7cddfSDavid du Colombier renameuser(char *old, char *new)
15317dd7cddfSDavid du Colombier {
15327dd7cddfSDavid du Colombier Proc *p, *ep;
15337dd7cddfSDavid du Colombier
15347dd7cddfSDavid du Colombier ep = procalloc.arena+conf.nproc;
15357dd7cddfSDavid du Colombier for(p = procalloc.arena; p < ep; p++)
15369a747e4fSDavid du Colombier if(p->user!=nil && strcmp(old, p->user)==0)
15379a747e4fSDavid du Colombier kstrdup(&p->user, new);
15387dd7cddfSDavid du Colombier }
15397dd7cddfSDavid du Colombier
15407dd7cddfSDavid du Colombier /*
15417dd7cddfSDavid du Colombier * time accounting called by clock() splhi'd
15427dd7cddfSDavid du Colombier */
15437dd7cddfSDavid du Colombier void
accounttime(void)15447dd7cddfSDavid du Colombier accounttime(void)
15457dd7cddfSDavid du Colombier {
15467dd7cddfSDavid du Colombier Proc *p;
15473ff48bf5SDavid du Colombier ulong n, per;
15483ff48bf5SDavid du Colombier static ulong nrun;
15497dd7cddfSDavid du Colombier
15507dd7cddfSDavid du Colombier p = m->proc;
15517dd7cddfSDavid du Colombier if(p) {
15527dd7cddfSDavid du Colombier nrun++;
15537dd7cddfSDavid du Colombier p->time[p->insyscall]++;
15547dd7cddfSDavid du Colombier }
15557dd7cddfSDavid du Colombier
15563ff48bf5SDavid du Colombier /* calculate decaying duty cycles */
15573ff48bf5SDavid du Colombier n = perfticks();
15583ff48bf5SDavid du Colombier per = n - m->perf.last;
15593ff48bf5SDavid du Colombier m->perf.last = n;
1560d9306527SDavid du Colombier per = (m->perf.period*(HZ-1) + per)/HZ;
1561d9306527SDavid du Colombier if(per != 0)
1562d9306527SDavid du Colombier m->perf.period = per;
15633ff48bf5SDavid du Colombier
15643ff48bf5SDavid du Colombier m->perf.avg_inidle = (m->perf.avg_inidle*(HZ-1)+m->perf.inidle)/HZ;
15653ff48bf5SDavid du Colombier m->perf.inidle = 0;
15663ff48bf5SDavid du Colombier
15673ff48bf5SDavid du Colombier m->perf.avg_inintr = (m->perf.avg_inintr*(HZ-1)+m->perf.inintr)/HZ;
15683ff48bf5SDavid du Colombier m->perf.inintr = 0;
15693ff48bf5SDavid du Colombier
15707dd7cddfSDavid du Colombier /* only one processor gets to compute system load averages */
15717dd7cddfSDavid du Colombier if(m->machno != 0)
15727dd7cddfSDavid du Colombier return;
15737dd7cddfSDavid du Colombier
157459c21d95SDavid du Colombier /*
157559c21d95SDavid du Colombier * calculate decaying load average.
157659c21d95SDavid du Colombier * if we decay by (n-1)/n then it takes
157759c21d95SDavid du Colombier * n clock ticks to go from load L to .36 L once
157859c21d95SDavid du Colombier * things quiet down. it takes about 5 n clock
157959c21d95SDavid du Colombier * ticks to go to zero. so using HZ means this is
158059c21d95SDavid du Colombier * approximately the load over the last second,
158159c21d95SDavid du Colombier * with a tail lasting about 5 seconds.
158259c21d95SDavid du Colombier */
15837dd7cddfSDavid du Colombier n = nrun;
15847dd7cddfSDavid du Colombier nrun = 0;
15857dd7cddfSDavid du Colombier n = (nrdy+n)*1000;
158659c21d95SDavid du Colombier m->load = (m->load*(HZ-1)+n)/HZ;
15877dd7cddfSDavid du Colombier }
15889a747e4fSDavid du Colombier
15899a747e4fSDavid du Colombier static void
pidhash(Proc * p)15909a747e4fSDavid du Colombier pidhash(Proc *p)
15919a747e4fSDavid du Colombier {
15929a747e4fSDavid du Colombier int h;
15939a747e4fSDavid du Colombier
15949a747e4fSDavid du Colombier h = p->pid % nelem(procalloc.ht);
15959a747e4fSDavid du Colombier lock(&procalloc);
15969a747e4fSDavid du Colombier p->pidhash = procalloc.ht[h];
15979a747e4fSDavid du Colombier procalloc.ht[h] = p;
15989a747e4fSDavid du Colombier unlock(&procalloc);
15999a747e4fSDavid du Colombier }
16009a747e4fSDavid du Colombier
16019a747e4fSDavid du Colombier static void
pidunhash(Proc * p)16029a747e4fSDavid du Colombier pidunhash(Proc *p)
16039a747e4fSDavid du Colombier {
16049a747e4fSDavid du Colombier int h;
16059a747e4fSDavid du Colombier Proc **l;
16069a747e4fSDavid du Colombier
16079a747e4fSDavid du Colombier h = p->pid % nelem(procalloc.ht);
16089a747e4fSDavid du Colombier lock(&procalloc);
16099a747e4fSDavid du Colombier for(l = &procalloc.ht[h]; *l != nil; l = &(*l)->pidhash)
16109a747e4fSDavid du Colombier if(*l == p){
16119a747e4fSDavid du Colombier *l = p->pidhash;
16129a747e4fSDavid du Colombier break;
16139a747e4fSDavid du Colombier }
16149a747e4fSDavid du Colombier unlock(&procalloc);
16159a747e4fSDavid du Colombier }
16169a747e4fSDavid du Colombier
16179a747e4fSDavid du Colombier int
procindex(ulong pid)16189a747e4fSDavid du Colombier procindex(ulong pid)
16199a747e4fSDavid du Colombier {
16209a747e4fSDavid du Colombier Proc *p;
16219a747e4fSDavid du Colombier int h;
16229a747e4fSDavid du Colombier int s;
16239a747e4fSDavid du Colombier
16249a747e4fSDavid du Colombier s = -1;
16259a747e4fSDavid du Colombier h = pid % nelem(procalloc.ht);
16269a747e4fSDavid du Colombier lock(&procalloc);
16279a747e4fSDavid du Colombier for(p = procalloc.ht[h]; p != nil; p = p->pidhash)
16289a747e4fSDavid du Colombier if(p->pid == pid){
16299a747e4fSDavid du Colombier s = p - procalloc.arena;
16309a747e4fSDavid du Colombier break;
16319a747e4fSDavid du Colombier }
16329a747e4fSDavid du Colombier unlock(&procalloc);
16339a747e4fSDavid du Colombier return s;
16349a747e4fSDavid du Colombier }
1635