/* * wire this proc to a machine */ void procwired(Proc *p, int bm) { Proc *pp; int i; char nwired[MAXMACH]; Mach *wm; if(bm < 0){ /* pick a machine to wire to */ memset(nwired, 0, sizeof(nwired)); p->wired = nil; pp = proctab(0); for(i=0; i<conf.nproc; i++, pp++){ wm = pp->wired; if(wm != nil && pp->pid) nwired[wm->machno]++; } bm = 0; for(i=0; i<conf.nmach; i++) if(nwired[i] < nwired[bm]) bm = i; } else { /* use the virtual machine requested */ bm = bm % conf.nmach; } p->wired = MACHP(bm); p->mp = p->wired; }
void pgrpnote(ulong noteid, char *a, long n, int flag) { Proc *p, *ep; char buf[ERRMAX]; if(n >= ERRMAX-1) error(Etoobig); memmove(buf, a, n); buf[n] = 0; p = proctab(0); ep = p+conf.nproc; for(; p < ep; p++) { if(p->state == Dead) continue; if(up != p && p->noteid == noteid && p->kp == 0) { qlock(&p->debug); if(p->pid == 0 || p->noteid != noteid){ qunlock(&p->debug); continue; } if(!waserror()) { postnote(p, 0, buf, flag); poperror(); } qunlock(&p->debug); } } }
static int canflush(Proc *p, Segment *s) { int i; Proc *ep; lock(&s->ref.lk); if(s->ref.ref == 1) { /* Easy if we are the only user */ s->ref.ref++; unlock(&s->ref.lk); return canpage(p); } s->ref.ref++; unlock(&s->ref.lk); /* Now we must do hardwork to ensure all processes which have tlb * entries for this segment will be flushed if we succeed in paging it out */ p = proctab(0); ep = &p[conf.nproc]; while(p < ep) { if(p->state != Dead) { for(i = 0; i < NSEG; i++) if(p->seg[i] == s) if(!canpage(p)) return 0; } p++; } return 1; }
static char * testschedulability(Proc *theproc) { Proc *p; vlong H, G, Cb, ticks; int steps, i; /* initialize */ DPRINT("schedulability test %lud\n", theproc->pid); qschedulability = nil; for(i=0; i<conf.nproc; i++) { p = proctab(i); if(p->state == Dead) continue; if ((p->edf == nil || (p->edf->flags & Admitted) == 0) && p != theproc) continue; p->edf->testtype = Rl; p->edf->testtime = 0; DPRINT("\tInit: edfenqueue %lud\n", p->pid); testenq(p); } H=0; G=0; for(steps = 0; steps < Maxsteps; steps++){ p = qschedulability; qschedulability = p->edf->testnext; ticks = p->edf->testtime; switch (p->edf->testtype){ case Dl: H += p->edf->C; Cb = 0; DPRINT("\tStep %3d, Ticks %t, pid %lud, deadline, H += %t → %t, Cb = %t\n", steps, ticks, p->pid, p->edf->C, H, Cb); if (H+Cb>ticks){ DPRINT("not schedulable\n"); return "not schedulable"; } p->edf->testtime += p->edf->T - p->edf->D; p->edf->testtype = Rl; testenq(p); break; case Rl: DPRINT("\tStep %3d, Ticks %t, pid %lud, release, G %t, C%t\n", steps, ticks, p->pid, p->edf->C, G); if(ticks && G <= ticks){ DPRINT("schedulable\n"); return nil; } G += p->edf->C; p->edf->testtime += p->edf->D; p->edf->testtype = Dl; testenq(p); break; default: assert(0); } } DPRINT("probably not schedulable\n"); return "probably not schedulable"; }
void fddump() { Proc *p; Osenv *o; int i; Chan *c; p = proctab(6); o = p->env; for(i = 0; i <= o->fgrp->maxfd; i++) { if((c = o->fgrp->fd[i]) == nil) continue; print("%d: %s\n", i, c->name == nil? "???": c->name->s); } }
static void pager(void *junk) { int i; Segment *s; Proc *p, *ep; if(waserror()) panic("pager: os error\n"); p = proctab(0); ep = &p[conf.nproc]; loop: up->psstate = "Idle"; sleep(&swapalloc.r, needpages, 0); print("uh oh. someone woke the pager\n"); while(needpages(junk)) { if(swapimage.c) { p++; if(p >= ep) p = proctab(0); if(p->state == Dead || p->noswap) continue; if(!canqlock(&p->seglock)) continue; /* process changing its segments */ for(i = 0; i < NSEG; i++) { if(!needpages(junk)){ qunlock(&p->seglock); goto loop; } if((s = p->seg[i])) { switch(s->type&SG_TYPE) { default: break; case SG_TEXT: pageout(p, s); break; case SG_DATA: case SG_BSS: case SG_STACK: case SG_SHARED: up->psstate = "Pageout"; pageout(p, s); if(ioptr != 0) { up->psstate = "I/O"; executeio(); } break; } } } qunlock(&p->seglock); } else { print("out of physical memory; no swap configured\n"); if(!cpuserver || freebroken() == 0) killbig("out of memory"); /* Emulate the old system if no swap channel */ tsleep(&up->sleep, return0, 0, 5000); wakeup(&palloc.r); } } goto loop; }
char * edfadmit(Proc *p) { char *err; Edf *e; int i; Proc *r; void (*pt)(Proc*, int, vlong); e = p->edf; if (e->flags & Admitted) return "task state"; /* should never happen */ /* simple sanity checks */ if (e->T == 0) return "T not set"; if (e->C == 0) return "C not set"; if (e->D > e->T) return "D > T"; if (e->D == 0) /* if D is not set, set it to T */ e->D = e->T; if (e->C > e->D) return "C > D"; qlock(&edfschedlock); if (err = testschedulability(p)){ qunlock(&edfschedlock); return err; } e->flags |= Admitted; edflock(p); if(pt = proctrace) pt(p, SAdmit, now); /* Look for another proc with the same period to synchronize to */ SET(r); for(i=0; i<conf.nproc; i++) { r = proctab(i); if(r->state == Dead || r == p) continue; if (r->edf == nil || (r->edf->flags & Admitted) == 0) continue; if (r->edf->T == e->T) break; } if (i == conf.nproc){ /* Can't synchronize to another proc, release now */ e->t = now; e->d = 0; release(p); if (p == up){ DPRINT("%t edfadmit self %lud[%s], release now: r=%t d=%t t=%t\n", now, p->pid, statename[p->state], e->r, e->d, e->t); /* We're already running */ edfrun(p, 1); }else{ /* We're releasing another proc */ DPRINT("%t edfadmit other %lud[%s], release now: r=%t d=%t t=%t\n", now, p->pid, statename[p->state], e->r, e->d, e->t); p->ta = p; edfunlock(); qunlock(&edfschedlock); releaseintr(nil, p); return nil; } }else{ /* Release in synch to something else */ e->t = r->edf->t; if (p == up){ DPRINT("%t edfadmit self %lud[%s], release at %t\n", now, p->pid, statename[p->state], e->t); edfunlock(); qunlock(&edfschedlock); return nil; }else{ DPRINT("%t edfadmit other %lud[%s], release at %t\n", now, p->pid, statename[p->state], e->t); if(e->tt == nil){ e->tf = releaseintr; e->ta = p; e->tns = e->t; e->tmode = Tabsolute; timeradd(e); } } } edfunlock(); qunlock(&edfschedlock); return nil; }