@@ 1094,7 1094,7 @@ void
procctlreq(Proc *p, char *va, int n)
{
Segment *s;
- int i, npc;
+ int npc, pri;
Cmdbuf *cb;
Cmdtab *ct;
@@ 1116,17 1116,6 @@ procctlreq(Proc *p, char *va, int n)
case CMclosefiles:
procctlclosefiles(p, 1, 0);
break;
- case CMfixedpri:
- i = atoi(cb->f[1]);
- if(i < 0)
- i = 0;
- if(i >= Nrq)
- i = Nrq - 1;
- if(i > p->basepri && !iseve())
- error(Eperm);
- p->basepri = i;
- p->fixedpri = 1;
- break;
case CMhang:
p->hang = 1;
break;
@@ 1152,15 1141,15 @@ procctlreq(Proc *p, char *va, int n)
p->noswap = 1;
break;
case CMpri:
- i = atoi(cb->f[1]);
- if(i < 0)
- i = 0;
- if(i >= Nrq)
- i = Nrq - 1;
- if(i > p->basepri && !iseve())
+ pri = atoi(cb->f[1]);
+ if(pri > PriNormal && !iseve())
+ error(Eperm);
+ procpriority(p, pri, 0);
+ break;
+ case CMfixedpri:
+ if(!iseve())
error(Eperm);
- p->basepri = i;
- p->fixedpri = 0;
+ procpriority(p, atoi(cb->f[1]), 1);
break;
case CMprivate:
p->privatemem = 1;
@@ 119,6 119,7 @@ char* getconfenv(void);
int haswaitq(void*);
long hostdomainwrite(char*, int);
long hostownerwrite(char*, int);
+void hzsched(void);
void iallocinit(void);
Block* iallocb(int);
void iallocsummary(void);
@@ 204,6 205,7 @@ void panic(char*, ...);
Cmdbuf* parsecmd(char *a, int n);
ulong perfticks(void);
void pexit(char*, int);
+int preempted(void);
void printinit(void);
int procindex(ulong);
void pgrpcpy(Pgrp*, Pgrp*);
@@ 222,6 224,7 @@ void procdump(void);
int procfdprint(Chan*, int, int, char*, int);
void procinit0(void);
void procflushseg(Segment*);
+void procpriority(Proc*, int, int);
Proc* proctab(int);
void procwired(Proc*, int);
Pte* ptealloc(void);
@@ 20,7 20,22 @@ static struct Procalloc
Proc* free;
} procalloc;
+enum
+{
+ Q=(HZ/20)*4,
+ DQ=((HZ-Q)/40)*2,
+};
+
static Schedq runq[Nrq];
+static ulong runvec;
+static int quanta[Nrq] =
+{
+ Q+19*DQ, Q+18*DQ, Q+17*DQ, Q+16*DQ,
+ Q+15*DQ, Q+14*DQ, Q+13*DQ, Q+12*DQ,
+ Q+11*DQ, Q+10*DQ, Q+ 9*DQ, Q+ 8*DQ,
+ Q+ 7*DQ, Q+ 6*DQ, Q+ 5*DQ, Q+ 4*DQ,
+ Q+ 3*DQ, Q+ 2*DQ, Q+ 1*DQ, Q+ 0*DQ,
+};
extern Edfinterface nulledf;
@@ 128,28 143,54 @@ sched(void)
int
anyready(void)
{
- return nrdy || edf->edfanyready();
+ return runvec || edf->edfanyready();
}
int
anyhigher(void)
{
- Schedq *rq;
+ return runvec & ~((1<<(up->priority+1))-1);
+}
- if(nrdy == 0)
- return 0;
+/*
+ * here once per clock tick to see if we should resched
+ */
+void
+hzsched(void)
+{
+ /* another cycle, another quantum */
+ up->quanta--;
- for(rq = &runq[Nrq-1]; rq > &runq[up->priority]; rq--)
- if(rq->head != nil)
- return 1;
+ /* edf scheduler always gets first chance */
+ if(edf->isedf(up))
+ return;
- return 0;
+ /* don't bother unless someone is elegible */
+ if(anyhigher() || (!up->fixedpri && anyready())){
+ sched();
+ splhi();
+ }
}
-enum
+/*
+ * here at the end of non-clock interrupts to see if we should preempt the
+ * current process. Returns 1 if preempted, 0 otherwise.
+ */
+int
+preempted(void)
{
- Squantum = 1,
-};
+ if(up && up->state == Running)
+ if(up->preempted == 0)
+ if(anyhigher())
+ if(!active.exiting){
+ up->preempted = 1;
+ sched();
+ splhi();
+ up->preempted = 0;
+ return 1;
+ }
+ return 0;
+}
void
ready(Proc *p)
@@ 164,34 205,37 @@ ready(Proc *p)
splx(s);
return;
}
+
+ pri = p->priority;
+
if(p->fixedpri){
pri = p->basepri;
+ p->quanta = HZ;
+ } else if(p->state == Running){
+ if(p->quanta <= 0){
+ /* degrade priority of anyone that used their whole quanta */
+
+ /* processes > PriNormal and those below don't mix */
+ if(p->basepri > PriNormal){
+ if(pri > PriNormal)
+ pri--;
+ } else {
+ if(pri > 0)
+ pri--;
+ }
+ p->quanta = quanta[pri];
+ }
} else {
- /* history counts */
- if(p->state == Running){
- p->rt++;
- pri = (p->art + p->rt)/2;
- } else {
- p->art = (p->art + p->rt + 2)/2;
- pri = (p->art + p->rt)/2;
- p->rt = 0;
+ if(p->quanta > quanta[pri]/2){
+ /* blocked before using half its quanta, go up */
+ if(++pri > p->basepri)
+ pri = p->basepri;
}
- pri = p->basepri - (pri/Squantum);
- if(pri < 0)
- pri = 0;
-
- /* the only intersection between the classes is at PriNormal */
- if(pri < PriNormal && p->basepri > PriNormal)
- pri = PriNormal;
-
- /* stick at low priority any process waiting for a lock */
- if(p->lockwait)
- pri = PriLock;
+ p->quanta = quanta[pri];
}
+ rq = &runq[pri];
p->priority = pri;
- rq = &runq[p->priority];
-
lock(runq);
p->rnext = 0;
if(rq->tail)
@@ 201,6 245,7 @@ ready(Proc *p)
rq->tail = p;
rq->n++;
nrdy++;
+ runvec |= 1<<pri;
p->readytime = m->ticks;
p->state = Ready;
unlock(runq);
@@ 210,10 255,10 @@ ready(Proc *p)
Proc*
runproc(void)
{
- Schedq *rq, *xrq;
+ Schedq *rq;
Proc *p, *l;
- ulong rt;
ulong start, now;
+ int i;
start = perfticks();
@@ 221,55 266,30 @@ runproc(void)
return p;
loop:
-
/*
* find a process that last ran on this processor (affinity),
- * or one that hasn't moved in a while (load balancing).
+ * or one that hasn't moved in a while (load balancing). Every
+ * time around the loop affinity goes down.
*/
spllo();
- for(;;){
- if((++(m->fairness) & 0x3) == 0){
- /*
- * once in a while, run process that's been waiting longest
- * regardless of movetime
- */
- rt = 0xffffffff;
- xrq = nil;
- for(rq = runq; rq < &runq[Nrq]; rq++){
- p = rq->head;
- if(p == 0)
- continue;
- if(p->readytime < rt){
- xrq = rq;
- rt = p->readytime;
- }
- }
- if(xrq != nil){
- rq = xrq;
- p = rq->head;
- if(p != nil && p->wired == nil)
- p->movetime = 0;
- goto found;
- }
- } else {
- /*
- * get highest priority process that this
- * processor can run given affinity constraints
- */
- for(rq = &runq[Nrq-1]; rq >= runq; rq--){
- p = rq->head;
- if(p == 0)
- continue;
- for(; p; p = p->rnext){
- if(p->mp == MACHP(m->machno)
- || p->movetime < MACHP(0)->ticks)
- goto found;
- }
+ for(i = 0;; i++){
+ /*
+ * get highest priority process that this
+ * processor can run given affinity constraints
+ */
+ for(rq = &runq[Nrq-1]; rq >= runq; rq--){
+ p = rq->head;
+ if(p == 0)
+ continue;
+ for(; p; p = p->rnext){
+ if(p->mp == MACHP(m->machno) || (!p->wired && i > 0))
+ goto found;
}
}
- /* remember how much time we're here */
idlehands();
+
+ /* remember how much time we're here */
now = perfticks();
m->perf.inidle += now-start;
start = now;
@@ 282,7 302,7 @@ found:
l = 0;
for(p = rq->head; p; p = p->rnext){
- if(p->mp == MACHP(m->machno) || p->movetime <= MACHP(0)->ticks)
+ if(p->mp == MACHP(m->machno) || (!p->wired && i > 0))
break;
l = p;
}
@@ 300,6 320,8 @@ found:
l->rnext = p->rnext;
else
rq->head = p->rnext;
+ if(rq->head == nil)
+ runvec &= ~(1<<(rq-runq));
rq->n--;
nrdy--;
if(p->state != Ready)
@@ 307,8 329,6 @@ found:
unlock(runq);
p->state = Scheding;
- if(p->mp != MACHP(m->machno))
- p->movetime = MACHP(0)->ticks + HZ/10;
p->mp = MACHP(m->machno);
return p;
@@ 366,20 386,15 @@ newproc(void)
p->kp = 0;
p->procctl = 0;
p->notepending = 0;
- p->mp = 0;
- p->movetime = 0;
- p->wired = 0;
p->ureg = 0;
p->privatemem = 0;
p->noswap = 0;
- p->lockwait = nil;
p->errstr = p->errbuf0;
p->syserrstr = p->errbuf1;
p->errbuf0[0] = '\0';
p->errbuf1[0] = '\0';
p->nlocks = 0;
p->delaysched = 0;
- p->movetime = 0;
kstrdup(&p->user, "*nouser");
kstrdup(&p->text, "*notext");
kstrdup(&p->args, "");
@@ 394,6 409,11 @@ newproc(void)
if(p->kstack == 0)
p->kstack = smalloc(KSTACK);
+ /* sched params */
+ p->mp = 0;
+ p->wired = 0;
+ procpriority(p, PriNormal, 0);
+
p->task = nil;
return p;
@@ 430,11 450,28 @@ procwired(Proc *p, int bm)
}
p->wired = MACHP(bm);
- p->movetime = 0xffffffff;
p->mp = p->wired;
}
void
+procpriority(Proc *p, int pri, int fixed)
+{
+ if(pri >= Nrq)
+ pri = Nrq - 1;
+ else if(pri < 0)
+ pri = 0;
+ p->basepri = pri;
+ p->priority = pri;
+ if(fixed){
+ p->quanta = 0xfffff;
+ p->fixedpri = 1;
+ } else {
+ p->quanta = quanta[pri];
+ p->fixedpri = 0;
+ }
+}
+
+void
procinit0(void) /* bad planning - clashes with devproc.c */
{
Proc *p;
@@ 967,9 1004,9 @@ dumpaproc(Proc *p)
s = p->psstate;
if(s == 0)
s = statename[p->state];
- print("%3lud:%10s pc %8lux dbgpc %8lux %8s (%s) ut %ld st %ld bss %lux qpc %lux nl %lud nd %lud lpc %lux\n",
+ 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",
p->pid, p->text, p->pc, dbgpc(p), s, statename[p->state],
- p->time[0], p->time[1], bss, p->qpc, p->nlocks, p->delaysched, p->lastlock ? p->lastlock->pc : 0);
+ p->time[0], p->time[1], bss, p->qpc, p->nlocks, p->delaysched, p->lastlock ? p->lastlock->pc : 0, p->priority);
}
void
@@ 1047,8 1084,7 @@ scheddump(void)
continue;
print("rq%ld:", rq-runq);
for(p = rq->head; p; p = p->rnext)
- print(" %lud(%lud, %lud)", p->pid, m->ticks - p->readytime,
- MACHP(0)->ticks - p->movetime);
+ print(" %lud(%lud)", p->pid, m->ticks - p->readytime);
print("\n");
delay(150);
}
@@ 1083,8 1119,7 @@ kproc(char *name, void (*func)(void *), void *arg)
p->ureg = 0;
p->dbgreg = 0;
- p->basepri = PriKproc;
- p->priority = p->basepri;
+ procpriority(p, PriKproc, 0);
kprocchild(p, func, arg);