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