static void deadlineintr(Ureg* ureg, Timer *t) { Proc *up = externup(); /* Proc reached deadline */ extern int panicking; Sched *sch; Proc *p; if(panicking || active.exiting) return; p = t->ta; now = ms(); DPRINT("%lu deadlineintr %d[%s]\n", now, p->pid, statename[p->state]); /* If we're interrupting something other than the proc pointed to by t->a, * we've already achieved recheduling, so we need not do anything * Otherwise, we must cause a reschedule, but if we call sched() * here directly, the timer interrupt routine will not finish its business * Instead, we cause the resched to happen when the interrupted proc * returns to user space */ if(p == up){ if(up->trace) proctrace(up, SInts, 0); up->delaysched++; sch = procsched(up); sch->delayedscheds++; } }
void edfrun(Proc *p, int edfpri) { Edf *e; int32_t tns; Sched *sch; e = p->edf; sch = procsched(p); /* Called with edflock held */ if(edfpri){ tns = e->d - now; if(tns <= 0 || e->S == 0){ /* Deadline reached or resources exhausted, * deschedule forthwith */ p->delaysched++; sch->delayedscheds++; e->s = now; return; } if(e->S < tns) tns = e->S; if(tns < 20) tns = 20; e->Timer.tns = 1000LL * tns; /* µs to ns */ if(e->Timer.tt == nil || e->Timer.tf != deadlineintr){ DPRINT("%lu edfrun, deadline=%lu\n", now, tns); }else{ DPRINT("v"); } if(p->trace) proctrace(p, SInte, todget(nil) + e->Timer.tns); e->Timer.tmode = Trelative; e->Timer.tf = deadlineintr; e->Timer.ta = p; timeradd(&e->Timer); }else{ DPRINT("<"); } e->s = now; }
int canpage(Proc *p) { int ok; Sched *sch; splhi(); sch = procsched(p); lock(sch); /* Only reliable way to see if we are Running */ if(p->mach == 0) { p->newtlb = 1; ok = 1; } else ok = 0; unlock(sch); spllo(); return ok; }
int edfready(Proc *p) { Edf *e; Sched *sch; Schedq *rq; Proc *l, *pp; int32_t n; if((e = edflock(p)) == nil) return 0; if(p->state == Wakeme && p->r){ iprint("edfready: wakeme\n"); } if(e->d - now <= 0){ /* past deadline, arrange for next release */ if((e->flags & Sporadic) == 0){ /* * Non sporadic processes stay true to their period; * calculate next release time. */ if((n = now - e->t) > 0){ if(n < e->T) e->t += e->T; else e->t = now + e->T - (n % e->T); } } if(now - e->t < 0){ /* Next release is in the future, schedule it */ if(e->Timer.tt == nil || e->Timer.tf != releaseintr){ n = e->t - now; if(n < 20) n = 20; e->Timer.tns = 1000LL * n; e->Timer.tmode = Trelative; e->Timer.tf = releaseintr; e->Timer.ta = p; timeradd(&e->Timer); DPRINT("%lu edfready %d[%s], release=%lu\n", now, p->pid, statename[p->state], e->t); } if(p->state == Running && (e->flags & (Yield|Yieldonblock)) == 0 && (e->flags & Extratime)){ /* If we were running, we've overrun our CPU allocation * or missed the deadline, continue running best-effort at low priority * Otherwise we were blocked. If we don't yield on block, we continue * best effort */ DPRINT(">"); p->basepri = PriExtra; p->fixedpri = 1; edfunlock(); return 0; /* Stick on runq[PriExtra] */ } DPRINT("%lu edfready %d[%s] wait release at %lu\n", now, p->pid, statename[p->state], e->t); p->state = Waitrelease; edfunlock(); return 1; /* Make runnable later */ } DPRINT("%lu edfready %d %s release now\n", now, p->pid, statename[p->state]); /* release now */ release(p); } edfunlock(); DPRINT("^"); sch = procsched(p); rq = &sch->runq[PriEdf]; /* insert in queue in earliest deadline order */ lock(&sch->l); l = nil; for(pp = rq->head; pp; pp = pp->rnext){ if(pp->edf->d > e->d) break; l = pp; } p->rnext = pp; if (l == nil) rq->head = p; else l->rnext = p; if(pp == nil) rq->tail = p; rq->n++; sch->nrdy++; sch->runvec |= 1 << PriEdf; p->priority = PriEdf; p->readytime = machp()->ticks; p->state = Ready; unlock(&sch->l); if(p->trace) proctrace(p, SReady, 0); return 1; }
static void releaseintr(Ureg* ureg, Timer *t) { Proc *up = externup(); Proc *p; extern int panicking; Sched *sch; Schedq *rq; if(panicking || active.exiting) return; p = t->ta; if((edflock(p)) == nil) return; sch = procsched(p); DPRINT("%lu releaseintr %d[%s]\n", now, p->pid, statename[p->state]); switch(p->state){ default: edfunlock(); return; case Ready: /* remove proc from current runq */ rq = &sch->runq[p->priority]; if(dequeueproc(sch, rq, p) != p){ DPRINT("releaseintr: can't find proc or lock race\n"); release(p); /* It'll start best effort */ edfunlock(); return; } p->state = Waitrelease; /* fall through */ case Waitrelease: release(p); edfunlock(); if(p->state == Wakeme){ iprint("releaseintr: wakeme\n"); } ready(p); if(up){ up->delaysched++; sch->delayedscheds++; } return; case Running: release(p); edfrun(p, 1); break; case Wakeme: release(p); edfunlock(); if(p->trend) wakeup(p->trend); p->trend = nil; if(up){ up->delaysched++; sch->delayedscheds++; } return; } edfunlock(); }
/* * ready(p) picks a new priority for a process and sticks it in the * runq for that priority. */ void ready(Proc *p) { schedready(procsched(p), p, 0); }