#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h"#include <interp.h> Ref pidalloc; struct{ Lock; Proc* arena; Proc* free;}procalloc; typedef struct{ Lock; Proc* head; Proc* tail;}Schedq; static Schedq runq[Nrq];static ulong occupied;int nrdy; char *statename[] ={ /* BUG: generate automatically */ "Dead", "Moribund", "Ready", "Scheding", "Running", "Queueing", "Wakeme", "Broken", "Stopped", "Rendez",}; /* * Always splhi()'ed. */voidschedinit(void) /* never returns */{ setlabel(&m->sched); if(up) {/* if((e = up->edf) && (e->flags & Admitted)) edfrecord(up);*/ m->proc = nil; switch(up->state) { case Running: ready(up); break; case Moribund: up->state = Dead;/* edfstop(up); if(up->edf){ free(up->edf); up->edf = nil; }*/ /* * Holding locks from pexit: * procalloc */ up->qnext = procalloc.free; procalloc.free = up; unlock(&procalloc); break; } up->mach = nil; up = nil; } sched();} voidsched(void){ if(up) { splhi(); procsave(up); if(setlabel(&up->sched)) { /* procrestore(up); */ spllo(); return; } gotolabel(&m->sched); } up = runproc(); up->state = Running; up->mach = MACHP(m->machno); /* m might be a fixed address; use MACHP */ m->proc = up; gotolabel(&up->sched);} voidready(Proc *p){ int s; Schedq *rq; s = splhi();/* if(edfready(p)){ splx(s); return; }*/ rq = &runq[p->pri]; lock(runq); p->rnext = 0; if(rq->tail) rq->tail->rnext = p; else rq->head = p; rq->tail = p; nrdy++; occupied |= 1<<p->pri; p->state = Ready; unlock(runq); splx(s);} intanyready(void){ /* same priority only */ return occupied & (1<<up->pri);} intanyhigher(void){ return occupied & ((1<<up->pri)-1);} intpreemption(int tick){ if(up != nil && up->state == Running && !up->preempted && (anyhigher() || tick && anyready())){ up->preempted = 1; sched(); splhi(); up->preempted = 0; return 1; } return 0;} Proc*runproc(void){ Proc *p, *l; Schedq *rq, *erq; erq = runq + Nrq - 1;loop: splhi(); for(rq = runq; rq->head == 0; rq++) if(rq >= erq) { idlehands(); spllo(); goto loop; } if(!canlock(runq)) goto loop; /* choose first one we last ran on this processor at this level or hasn't moved recently */ l = nil; for(p = rq->head; p != nil; p = p->rnext) if(p->mp == nil || p->mp == MACHP(m->machno) || p->movetime < MACHP(0)->ticks) break; if(p == nil) p = rq->head; /* p->mach==0 only when process state is saved */ if(p == 0 || p->mach) { unlock(runq); goto loop; } if(p->rnext == nil) rq->tail = l; if(l) l->rnext = p->rnext; else rq->head = p->rnext; if(rq->head == nil){ rq->tail = nil; occupied &= ~(1<<p->pri); } nrdy--; if(p->dbgstop){ p->state = Stopped; unlock(runq); goto loop; } if(p->state != Ready) print("runproc %s %lud %s\n", p->text, p->pid, statename[p->state]); unlock(runq); p->state = Scheding; if(p->mp != MACHP(m->machno)) p->movetime = MACHP(0)->ticks + HZ/10; p->mp = MACHP(m->machno); /* if(edflock(p)){ edfrun(p, rq == &runq[PriEdf]); // start deadline timer and do admin edfunlock(); }*/ return p;} intsetpri(int pri){ int p; /* called by up so not on run queue */ p = up->pri; up->pri = pri; if(up->state == Running && anyhigher()) sched(); return p;} Proc*newproc(void){ Proc *p; lock(&procalloc); for(;;) { if(p = procalloc.free) break; unlock(&procalloc); resrcwait("no procs"); lock(&procalloc); } procalloc.free = p->qnext; unlock(&procalloc); p->type = Unknown; p->state = Scheding; p->pri = PriNormal; p->psstate = "New"; p->mach = 0; p->qnext = 0; p->fpstate = FPINIT; p->kp = 0; p->killed = 0; p->swipend = 0; p->mp = 0; p->movetime = 0; p->delaysched = 0; p->edf = nil; memset(&p->defenv, 0, sizeof(p->defenv)); p->env = &p->defenv; p->dbgreg = 0; kstrdup(&p->env->user, "*nouser"); p->env->errstr = p->env->errbuf0; p->env->syserrstr = p->env->errbuf1; p->pid = incref(&pidalloc); if(p->pid == 0) panic("pidalloc"); if(p->kstack == 0) p->kstack = smalloc(KSTACK); addprog(p); return p;} voidprocinit(void){ Proc *p; int i; procalloc.free = xalloc(conf.nproc*sizeof(Proc)); procalloc.arena = procalloc.free; p = procalloc.free; for(i=0; i<conf.nproc-1; i++,p++) p->qnext = p+1; p->qnext = 0; debugkey('p', "processes", procdump, 0);} voidsleep(Rendez *r, int (*f)(void*), void *arg){ int s; if(up == nil) panic("sleep() not in process (%lux)", getcallerpc(&r)); /* * spl is to allow lock to be called * at interrupt time. lock is mutual exclusion */ s = splhi(); lock(&up->rlock); lock(r); /* * if killed or condition happened, never mind */ if(up->killed || f(arg)){ unlock(r); }else{ /* * now we are committed to * change state and call scheduler */ if(r->p != nil) { print("double sleep pc=0x%lux %lud %lud r=0x%lux\n", getcallerpc(&r), r->p->pid, up->pid, r); dumpstack(); panic("sleep"); } up->state = Wakeme; r->p = up; unlock(r); up->swipend = 0; up->r = r; /* for swiproc */ unlock(&up->rlock); sched(); splhi(); /* sched does spllo */ lock(&up->rlock); up->r = nil; } if(up->killed || up->swipend) { up->killed = 0; up->swipend = 0; unlock(&up->rlock); splx(s); error(Eintr); } unlock(&up->rlock); splx(s);} inttfn(void *arg){ return MACHP(0)->ticks >= up->twhen || (*up->tfn)(arg);} voidtsleep(Rendez *r, int (*fn)(void*), void *arg, int ms){ ulong when; Proc *f, **l; if(up == nil) panic("tsleep() not in process (0x%lux)", getcallerpc(&r)); when = MS2TK(ms)+MACHP(0)->ticks; lock(&talarm); /* take out of list if checkalarm didn't */ if(up->trend) { l = &talarm.list; for(f = *l; f; f = f->tlink) { if(f == up) { *l = up->tlink; break; } l = &f->tlink; } } /* insert in increasing time order */ l = &talarm.list; for(f = *l; f; f = f->tlink) { if(f->twhen >= when) break; l = &f->tlink; } up->trend = r; up->twhen = when; up->tfn = fn; up->tlink = *l; *l = up; unlock(&talarm); if(waserror()){ up->twhen = 0; nexterror(); } sleep(r, tfn, arg); up->twhen = 0; poperror();} intwakeup(Rendez *r){ Proc *p; int s; s = splhi(); lock(r); p = r->p; if(p){ r->p = nil; if(p->state != Wakeme) panic("wakeup: state"); ready(p); } unlock(r); splx(s); return p != nil;} voidswiproc(Proc *p, int interp){ ulong s; Rendez *r; if(p == nil) return; s = splhi(); lock(&p->rlock); if(!interp) p->killed = 1; r = p->r; if(r != nil) { lock(r); if(r->p == p){ p->swipend = 1; r->p = nil; ready(p); } unlock(r); } unlock(&p->rlock); splx(s);} voidnotkilled(void){ lock(&up->rlock); up->killed = 0; unlock(&up->rlock);} voidpexit(char*, int){ Osenv *o; up->alarm = 0; o = up->env; if(o != nil){ closefgrp(o->fgrp); closepgrp(o->pgrp); closeegrp(o->egrp); closesigs(o->sigs); } /* Sched must not loop for this lock */ lock(&procalloc); /* edfstop(up);*/ up->state = Moribund; sched(); panic("pexit");} Proc*proctab(int i){ return &procalloc.arena[i];} voidprocdump(void){ int i; char *s;Lines 1–500 of 788. Load more
#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include <interp.h> Ref pidalloc; struct { Lock; Proc* arena; Proc* free; }procalloc; typedef struct { Lock; Proc* head; Proc* tail; }Schedq; static Schedq runq[Nrq]; static ulong occupied; int nrdy; char *statename[] = { /* BUG: generate automatically */ "Dead", "Moribund", "Ready", "Scheding", "Running", "Queueing", "Wakeme", "Broken", "Stopped", "Rendez", }; /* * Always splhi()'ed. */ void schedinit(void) /* never returns */ { setlabel(&m->sched); if(up) { /* if((e = up->edf) && (e->flags & Admitted)) edfrecord(up); */ m->proc = nil; switch(up->state) { case Running: ready(up); break; case Moribund: up->state = Dead; /* edfstop(up); if(up->edf){ free(up->edf); up->edf = nil; } */ /* * Holding locks from pexit: * procalloc */ up->qnext = procalloc.free; procalloc.free = up; unlock(&procalloc); break; } up->mach = nil; up = nil; } sched(); } void sched(void) { if(up) { splhi(); procsave(up); if(setlabel(&up->sched)) { /* procrestore(up); */ spllo(); return; } gotolabel(&m->sched); } up = runproc(); up->state = Running; up->mach = MACHP(m->machno); /* m might be a fixed address; use MACHP */ m->proc = up; gotolabel(&up->sched); } void ready(Proc *p) { int s; Schedq *rq; s = splhi(); /* if(edfready(p)){ splx(s); return; } */ rq = &runq[p->pri]; lock(runq); p->rnext = 0; if(rq->tail) rq->tail->rnext = p; else rq->head = p; rq->tail = p; nrdy++; occupied |= 1<<p->pri; p->state = Ready; unlock(runq); splx(s); } int anyready(void) { /* same priority only */ return occupied & (1<<up->pri); } int anyhigher(void) { return occupied & ((1<<up->pri)-1); } int preemption(int tick) { if(up != nil && up->state == Running && !up->preempted && (anyhigher() || tick && anyready())){ up->preempted = 1; sched(); splhi(); up->preempted = 0; return 1; } return 0; } Proc* runproc(void) { Proc *p, *l; Schedq *rq, *erq; erq = runq + Nrq - 1; loop: splhi(); for(rq = runq; rq->head == 0; rq++) if(rq >= erq) { idlehands(); spllo(); goto loop; } if(!canlock(runq)) goto loop; /* choose first one we last ran on this processor at this level or hasn't moved recently */ l = nil; for(p = rq->head; p != nil; p = p->rnext) if(p->mp == nil || p->mp == MACHP(m->machno) || p->movetime < MACHP(0)->ticks) break; if(p == nil) p = rq->head; /* p->mach==0 only when process state is saved */ if(p == 0 || p->mach) { unlock(runq); goto loop; } if(p->rnext == nil) rq->tail = l; if(l) l->rnext = p->rnext; else rq->head = p->rnext; if(rq->head == nil){ rq->tail = nil; occupied &= ~(1<<p->pri); } nrdy--; if(p->dbgstop){ p->state = Stopped; unlock(runq); goto loop; } if(p->state != Ready) print("runproc %s %lud %s\n", p->text, p->pid, statename[p->state]); unlock(runq); p->state = Scheding; if(p->mp != MACHP(m->machno)) p->movetime = MACHP(0)->ticks + HZ/10; p->mp = MACHP(m->machno); /* if(edflock(p)){ edfrun(p, rq == &runq[PriEdf]); // start deadline timer and do admin edfunlock(); } */ return p; } int setpri(int pri) { int p; /* called by up so not on run queue */ p = up->pri; up->pri = pri; if(up->state == Running && anyhigher()) sched(); return p; } Proc* newproc(void) { Proc *p; lock(&procalloc); for(;;) { if(p = procalloc.free) break; unlock(&procalloc); resrcwait("no procs"); lock(&procalloc); } procalloc.free = p->qnext; unlock(&procalloc); p->type = Unknown; p->state = Scheding; p->pri = PriNormal; p->psstate = "New"; p->mach = 0; p->qnext = 0; p->fpstate = FPINIT; p->kp = 0; p->killed = 0; p->swipend = 0; p->mp = 0; p->movetime = 0; p->delaysched = 0; p->edf = nil; memset(&p->defenv, 0, sizeof(p->defenv)); p->env = &p->defenv; p->dbgreg = 0; kstrdup(&p->env->user, "*nouser"); p->env->errstr = p->env->errbuf0; p->env->syserrstr = p->env->errbuf1; p->pid = incref(&pidalloc); if(p->pid == 0) panic("pidalloc"); if(p->kstack == 0) p->kstack = smalloc(KSTACK); addprog(p); return p; } void procinit(void) { Proc *p; int i; procalloc.free = xalloc(conf.nproc*sizeof(Proc)); procalloc.arena = procalloc.free; p = procalloc.free; for(i=0; i<conf.nproc-1; i++,p++) p->qnext = p+1; p->qnext = 0; debugkey('p', "processes", procdump, 0); } void sleep(Rendez *r, int (*f)(void*), void *arg) { int s; if(up == nil) panic("sleep() not in process (%lux)", getcallerpc(&r)); /* * spl is to allow lock to be called * at interrupt time. lock is mutual exclusion */ s = splhi(); lock(&up->rlock); lock(r); /* * if killed or condition happened, never mind */ if(up->killed || f(arg)){ unlock(r); }else{ /* * now we are committed to * change state and call scheduler */ if(r->p != nil) { print("double sleep pc=0x%lux %lud %lud r=0x%lux\n", getcallerpc(&r), r->p->pid, up->pid, r); dumpstack(); panic("sleep"); } up->state = Wakeme; r->p = up; unlock(r); up->swipend = 0; up->r = r; /* for swiproc */ unlock(&up->rlock); sched(); splhi(); /* sched does spllo */ lock(&up->rlock); up->r = nil; } if(up->killed || up->swipend) { up->killed = 0; up->swipend = 0; unlock(&up->rlock); splx(s); error(Eintr); } unlock(&up->rlock); splx(s); } int tfn(void *arg) { return MACHP(0)->ticks >= up->twhen || (*up->tfn)(arg); } void tsleep(Rendez *r, int (*fn)(void*), void *arg, int ms) { ulong when; Proc *f, **l; if(up == nil) panic("tsleep() not in process (0x%lux)", getcallerpc(&r)); when = MS2TK(ms)+MACHP(0)->ticks; lock(&talarm); /* take out of list if checkalarm didn't */ if(up->trend) { l = &talarm.list; for(f = *l; f; f = f->tlink) { if(f == up) { *l = up->tlink; break; } l = &f->tlink; } } /* insert in increasing time order */ l = &talarm.list; for(f = *l; f; f = f->tlink) { if(f->twhen >= when) break; l = &f->tlink; } up->trend = r; up->twhen = when; up->tfn = fn; up->tlink = *l; *l = up; unlock(&talarm); if(waserror()){ up->twhen = 0; nexterror(); } sleep(r, tfn, arg); up->twhen = 0; poperror(); } int wakeup(Rendez *r) { Proc *p; int s; s = splhi(); lock(r); p = r->p; if(p){ r->p = nil; if(p->state != Wakeme) panic("wakeup: state"); ready(p); } unlock(r); splx(s); return p != nil; } void swiproc(Proc *p, int interp) { ulong s; Rendez *r; if(p == nil) return; s = splhi(); lock(&p->rlock); if(!interp) p->killed = 1; r = p->r; if(r != nil) { lock(r); if(r->p == p){ p->swipend = 1; r->p = nil; ready(p); } unlock(r); } unlock(&p->rlock); splx(s); } void notkilled(void) { lock(&up->rlock); up->killed = 0; unlock(&up->rlock); } void pexit(char*, int) { Osenv *o; up->alarm = 0; o = up->env; if(o != nil){ closefgrp(o->fgrp); closepgrp(o->pgrp); closeegrp(o->egrp); closesigs(o->sigs); } /* Sched must not loop for this lock */ lock(&procalloc); /* edfstop(up); */ up->state = Moribund; sched(); panic("pexit"); } Proc* proctab(int i) { return &procalloc.arena[i]; } void procdump(void) { int i; char *s;