M carrera/clock.c => carrera/clock.c +1 -2
@@ 47,7 47,6 @@ clockinit(void)
void
clock(Ureg *ur)
{
- int n;
wrcompare(rdcount()+(m->speed*1000000)/HZ);
@@ 78,7 77,7 @@ clock(Ureg *ur)
if(up == 0 || up->state != Running)
return;
- if(anyready() && !up->inlock)
+ if(anyready())
sched();
/* user profiling clock */
M carrera/trap.c => carrera/trap.c +1 -1
@@ 397,7 397,7 @@ intr(Ureg *ur)
}
/* preemptive scheduling */
- if(up && up->state == Running && anyhigher() && !up->inlock)
+ if(up && up->state == Running && anyhigher())
sched();
}
M pc/clock.c => pc/clock.c +1 -1
@@ 45,7 45,7 @@ clock(Ureg *ur, void *arg)
uartclock();
if(up && up->state == Running){
- if(anyready() && !up->inlock)
+ if(anyready())
sched();
/* user profiling clock */
M port/auth.c => port/auth.c +3 -5
@@ 124,10 124,8 @@ sysfsession(ulong *arg)
unlock(c);
/* back off if someone else is doing an fsession */
- while(!canlock(&s->send)) {
- up->yield = 1;
+ while(!canlock(&s->send))
sched();
- }
if(s->valid == 0){
/*
@@ 575,7 573,7 @@ userwrite(char *a, int n)
error(Eperm);
memset(up->user, 0, NAMELEN);
strcpy(up->user, "none");
- up->nice = NiceNormal;
+ up->basepri = PriNormal;
return n;
}
@@ 600,7 598,7 @@ hostownerwrite(char *a, int n)
renameuser(eve, buf);
memmove(eve, buf, NAMELEN);
memmove(up->user, buf, NAMELEN);
- up->nice = NiceNormal;
+ up->basepri = PriNormal;
return n;
}
M port/devXXX.c => port/devXXX.c +27 -19
@@ 12,13 12,13 @@
#include "devtab.h"
enum{
- XXXdirqid,
- XXXdataqid,
+ Qdir,
+ Qdata,
};
Dirtab XXXtab[]={
- "data", XXXdataqid, 0, 0600,
+ "data", {Qdata, 0}, 0, 0600,
};
-#define NXXXtab (sizeof(XXXTab)/sizeof(Dirtab))
+#define NXXXtab (sizeof(XXXtab)/sizeof(Dirtab))
void
XXXreset(void)
@@ 45,43 45,39 @@ XXXclone(Chan *c, Chan *nc)
int
XXXwalk(Chan *c, char *name)
{
- return devwalk(c, name, XXXtab, (long)NXXXtab, devgen);
+ return devwalk(c, name, XXXtab, NXXXtab, devgen);
}
void
XXXstat(Chan *c, char *db)
{
- devstat(c, db, XXXtab, (long)NXXXtab, devgen);
+ devstat(c, db, XXXtab, NXXXtab, devgen);
}
Chan *
XXXopen(Chan *c, int omode)
{
- if(c->qid.path == CHDIR){
- if(omode != OREAD)
- error(Eperm);
- }
- c->mode = openmode(omode);
- c->flag |= COPEN;
- c->offset = 0;
- return c;
+ return devopen(c, omode, XXXtab, NXXXtab, devgen);
}
void
XXXcreate(Chan *c, char *name, int omode, ulong perm)
{
+ USED(c, name, omode, perm);
error(Eperm);
}
void
XXXremove(Chan *c)
{
+ USED(c);
error(Eperm);
}
void
XXXwstat(Chan *c, char *dp)
{
+ USED(c, dp);
error(Eperm);
}
@@ 93,10 89,10 @@ XXXclose(Chan *c)
long
XXXread(Chan *c, void *a, long n, ulong offset)
{
- switch((int)(c->qid.path&~CHDIR)){
- case XXXdirqid:
+ switch(c->qid.path & ~CHDIR){
+ case Qdir:
return devdirread(c, a, n, XXXtab, NXXXtab, devgen);
- case XXXdataqid:
+ case Qdata:
break;
default:
n=0;
@@ 105,14 101,26 @@ XXXread(Chan *c, void *a, long n, ulong offset)
return n;
}
+Block*
+XXXbread(Chan *c, long n, ulong offset)
+{
+ return devbread(c, n, offset);
+}
+
long
XXXwrite(Chan *c, char *a, long n, ulong offset)
{
- switch((int)(c->qid.path&~CHDIR)){
- case XXXdataqid:
+ switch(c->qid.path & ~CHDIR){
+ case Qdata:
break;
default:
error(Ebadusefd);
}
return n;
}
+
+long
+XXXbwrite(Chan *c, Block *bp, ulong offset)
+{
+ return devbwrite(c, bp, offset);
+}
M port/devproc.c => port/devproc.c +10 -8
@@ 396,8 396,8 @@ procread(Chan *c, void *va, long n, ulong offset)
l += s->top - s->base;
}
readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, l>>10, NUMSIZE);
- readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->nice, NUMSIZE);
- readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->pri, NUMSIZE);
+ readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE);
+ readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE);
memmove(a, statbuf+offset, n);
return n;
@@ 749,15 749,17 @@ procctlreq(Proc *p, char *va, int n)
ready(p);
}
else
- if(strncmp(buf, "nice", 4) == 0){
- if(n < 5)
+ if(strncmp(buf, "pri", 3) == 0){
+ if(n < 4)
error(Ebadctl);
- i = NiceNormal+atoi(buf+5);
+ i = atoi(buf+4);
if(i < 0)
i = 0;
- if(i >= NiceMax)
- i = NiceMax - 1;
- p->nice = i;
+ if(i >= Nrq)
+ i = Nrq - 1;
+ if(i < p->basepri && !iseve())
+ error(Eperm);
+ p->basepri = i;
}
else
if(strncmp(buf, "wired", 5) == 0){
M port/portdat.h => port/portdat.h +12 -9
@@ 503,10 503,10 @@ enum
NERR = 15,
NNOTE = 5,
- NiceMax = 10, /* max nice */
- NiceNormal = 5, /* base nice for normal processes */
- NiceKproc = NiceNormal-2, /* nice for kernel processes */
- NiceRoot = NiceNormal-2, /* nice for root processes */
+ Nrq = 20, /* number of scheduler priority levels */
+ PriNormal = 10, /* base priority for normal processes */
+ PriKproc = 13, /* base priority for kernel processes */
+ PriRoot = 13, /* base priority for root processes */
};
struct Proc
@@ 586,11 586,14 @@ struct Proc
Note lastnote;
int (*notify)(void*, char*);
- Mach *wired; /* machine this process must run on */
- int pri; /* scheduling priority - low is high priority */
- short nice; /* time-passing algorithm - low is high priority */
- char yield; /* force one lap in the runq */
- char inlock; /* temp hi proirity ~= 2*num of locks set */
+ Mach *wired;
+ Mach *mp; /* machine this process last ran on */
+ ulong priority; /* priority level */
+ ulong basepri; /* base priority level */
+ ulong rt; /* # ticks used since last blocked */
+ ulong art; /* avg # ticks used since last blocked */
+ ulong movetime; /* last time process switched processors */
+ ulong readytime; /* time process went ready */
void *ureg; /* User registers for notes */
void *dbgreg; /* User registers for devproc */
M port/proc.c => port/proc.c +145 -119
@@ 29,8 29,9 @@ typedef struct
int n;
} Schedq;
-Schedq runq;
-int priconst[NiceMax];
+int nrdy;
+int lastreadied;
+Schedq runq[Nrq];
char *statename[] =
{ /* BUG: generate automatically */
@@ 106,109 107,155 @@ sched(void)
int
anyready(void)
{
- return runq.n;
+ return nrdy;
}
int
anyhigher(void)
{
- Proc *p;
- int pri;
+ int x;
- pri = up->pri;
- for(p=runq.head; p; p=p->rnext)
- if(p->pri <= pri)
- if(p->wired == 0 || p->wired == m)
- return 1;
- return 0;
+ x = lastreadied;
+ lastreadied = 0;
+ return nrdy && x >= up->priority;
}
+enum
+{
+ Squantum = (HZ+Nrq-1)/Nrq,
+};
+
void
ready(Proc *p)
{
- int s;
+ int s, pri;
+ Schedq *rq;
s = splhi();
- lock(&runq);
+ /* history counts */
+ if(p->state == Running){
+ p->rt++;
+ pri = ((p->art + (p->rt<<1))>>2)/Squantum;
+ } else {
+ p->art = (p->art + (p->rt<<1))>>2;
+ p->rt = 0;
+ pri = p->art/Squantum;
+ }
+ pri = p->basepri - pri;
+ if(pri < 0)
+ pri = 0;
+
+ /* the only intersection between the classes is at PriNormal */
+ if(pri < PriNormal && p->basepri > PriNormal)
+ pri = PriNormal;
+ p->priority = pri;
+ rq = &runq[p->priority];
+
+ lock(runq);
p->rnext = 0;
- if(runq.tail)
- runq.tail->rnext = p;
+ if(rq->tail)
+ rq->tail->rnext = p;
else
- runq.head = p;
- runq.tail = p;
- runq.n++;
+ rq->head = p;
+ rq->tail = p;
+ rq->n++;
+ nrdy++;
+ p->readytime = m->ticks;
p->state = Ready;
- unlock(&runq);
+ if(p->priority > lastreadied)
+ lastreadied = p->priority;
+ unlock(runq);
splx(s);
}
Proc*
runproc(void)
{
- Proc *p, *bp, *op;
+ int i;
+ Schedq *rq;
+ Proc *p, *l;
loop:
+
+ /*
+ * find a process that last ran on this processor (affinity),
+ * or one that hasn't moved in a while (load balancing).
+ */
spllo();
+ for(;;){
+ /*
+ * Once a second we look for a long waiting process
+ * in the lowest priority queue to make sure nothing
+ * gets starved out by a malfunctioning high priority
+ * process.
+ */
+ if((m->ticks % HZ) == 0){
+ for(rq = runq; rq < &runq[Nrq]; rq++){
+ p = rq->head;
+ if(p == 0 || p->mp != m)
+ continue;
+
+ i = m->ticks - p->readytime;
+ if(i < HZ)
+ break;
+
+ p->art = 0;
+ goto found;
+ }
+ }
- /* look for potential proc while not locked */
- for(p = runq.head; p; p=p->rnext) {
/*
- * state is not saved or wired to another machine
+ * get highest priority process that this
+ * processor can run given affinity constraints
*/
- if(!(p->mach || (p->wired && p->wired != m)))
- break;
+ for(rq = &runq[Nrq-1]; rq >= runq; rq--){
+ p = rq->head;
+ if(p == 0)
+ continue;
+ for(; p; p = p->rnext){
+ if(p->mp == m || p->movetime < m->ticks)
+ goto found;
+ }
+ }
}
- if(p == 0)
- goto loop;
+
+found:
splhi();
- lock(&runq);
+ lock(runq);
- /* find best proc while locked */
- bp = 0;
- for(p = runq.head; p; p=p->rnext) {
- if(p->mach || (p->wired && p->wired != m))
- continue;
- if(bp == 0) {
- if(p->yield)
- p->yield = 0;
- bp = p;
- } else
- if(p->yield == 0 && p->pri < bp->pri)
- bp = p;
- }
- if(bp == 0) {
- unlock(&runq);
- goto loop;
+ l = 0;
+ for(p = rq->head; p; p = p->rnext){
+ if(p->mp == m || p->movetime < m->ticks)
+ break;
+ l = p;
}
-found:
- /* unlink found proc from runq */
- op = 0;
- for(p=runq.head; p; p=p->rnext) {
- if(p == bp)
- break;
- op = p;
+ /*
+ * p->mach==0 only when process state is saved
+ */
+ if(p == 0 || p->mach){
+ unlock(runq);
+ goto loop;
}
- if(op == 0)
- runq.head = bp->rnext;
+ if(p->rnext == 0)
+ rq->tail = l;
+ if(l)
+ l->rnext = p->rnext;
else
- op->rnext = bp->rnext;
- if(bp == runq.tail)
- runq.tail = op;
-
- /* clear next so that unlocked runq will not loop */
- bp->rnext = 0;
+ rq->head = p->rnext;
+ rq->n--;
+ nrdy--;
+ if(p->state != Ready)
+ print("runproc %s %d %s\n", p->text, p->pid, statename[p->state]);
+ unlock(runq);
- runq.n--;
-
- if(bp->state != Ready)
- print("runproc %s %d %s\n", bp->text, bp->pid, statename[bp->state]);
- unlock(&runq);
-
- bp->state = Scheding;
- return bp;
+ p->state = Scheding;
+ if(p->mp != m)
+ p->movetime = m->ticks + HZ/2;
+ p->mp = m;
+ return p;
}
int
@@ 217,13 264,13 @@ canpage(Proc *p)
int ok = 0;
splhi();
- lock(&runq);
+ lock(runq);
/* Only reliable way to see if we are Running */
if(p->mach == 0) {
p->newtlb = 1;
ok = 1;
}
- unlock(&runq);
+ unlock(runq);
spllo();
return ok;
@@ 263,8 310,8 @@ newproc(void)
p->kp = 0;
p->procctl = 0;
p->notepending = 0;
- p->nice = NiceNormal;
- p->pri = 0;
+ p->mp = 0;
+ p->movetime = 0;
p->wired = 0;
memset(p->seg, 0, sizeof p->seg);
p->pid = incref(&pidalloc);
@@ 298,6 345,8 @@ procwired(Proc *p)
if(nwired[i] < nwired[bm])
bm = i;
p->wired = MACHP(bm);
+ p->movetime = 0xffffffff;
+ p->mp = p->wired;
}
void
@@ 313,14 362,6 @@ procinit0(void) /* bad planning - clashes with devproc.c */
for(i=0; i<conf.nproc-1; i++,p++)
p->qnext = p+1;
p->qnext = 0;
-
- /*
- * set up priority increments
- * normal priority sb about 1000/HZ
- * highest pri (lowest number) sb about 0
- */
- for(i=0; i<NiceMax; i++)
- priconst[i] = (i*1000)/(NiceNormal*HZ);
}
void
@@ 364,11 405,12 @@ sleep(Rendez *r, int (*f)(void*), void *arg)
{
int s;
+ if((getstatus()&IE) == 0)
+ print("sleep hi %lux\n", getcallerpc(r));
+
sleep1(r, f, arg);
- if(up->notepending == 0) {
- up->yield = 1;
+ if(up->notepending == 0)
sched(); /* notepending may go true while asleep */
- }
if(up->notepending) {
up->notepending = 0;
@@ 394,6 436,9 @@ tsleep(Rendez *r, int (*fn)(void*), void *arg, int ms)
ulong when;
Proc *f, **l;
+ if((getstatus()&IE) == 0)
+ print("tsleep hi %lux\n", getcallerpc(r));
+
when = MS2TK(ms)+MACHP(0)->ticks;
lock(&talarm);
@@ 750,6 795,7 @@ procdump(void)
char *s;
Proc *p;
ulong bss;
+ Schedq *rq;
for(i=0; i<conf.nproc; i++) {
p = &procalloc.arena[i];
@@ 766,13 812,15 @@ procdump(void)
p->pid, p->text, p->pc, s, statename[p->state],
p->time[0], p->time[1], bss);
}
- if(runq.head != 0) {
- print("rq:");
- for(p = runq.head; p; p = p->rnext)
- print(" %d(%d)", p->pid, p->pri);
+ for(rq = &runq[Nrq-1]; rq >= runq; rq--){
+ if(rq->head == 0)
+ continue;
+ print("rq%d:", rq-runq);
+ for(p = rq->head; p; p = p->rnext)
+ print(" %d(%d)", p->pid, m->ticks - p->readytime);
print("\n");
}
- print("nrdy %d\n", runq.n);
+ print("nrdy %d\n", nrdy);
}
void
@@ 802,8 850,8 @@ kproc(char *name, void (*func)(void *), void *arg)
p->ureg = 0;
p->dbgreg = 0;
- p->nice = NiceKproc;
- p->pri = 0;
+ p->basepri = PriKproc;
+ p->priority = p->basepri;
kprocchild(p, func, arg);
@@ 872,6 920,9 @@ procctl(Proc *p)
void
error(char *err)
{
+ if((getstatus()&IE) == 0)
+ print("error hi %lux\n", getcallerpc(err));
+ spllo();
strncpy(up->error, err, ERRLEN);
nexterror();
}
@@ 950,21 1001,13 @@ void
accounttime(void)
{
Proc *p;
- int i, pri;
- static int nrun, m0ticks;
+ int n;
+ static int nrun;
p = m->proc;
if(p) {
nrun++;
p->time[p->insyscall]++;
- p->pri += priconst[p->nice];
- }
-
- if(up) {
- i = up->inlock-1;
- if(i < 0)
- i = 0;
- up->inlock = i;
}
/* only one processor gets to compute system load averages */
@@ 972,26 1015,9 @@ accounttime(void)
return;
/* calculate decaying load average */
- pri = nrun;
+ n = nrun;
nrun = 0;
- pri = (runq.n+pri)*1000;
- m->load = (m->load*19+pri)/20;
-
- /*
- * decay per-process cpu usage
- * pri = (3/4)*pri twice per second
- * tc = (3/4)^2/(1-(3/4)^2) = 1.286 sec
- */
- m0ticks--;
- if(m0ticks <= 0) {
- m0ticks = HZ/2;
- p = proctab(0);
- for(i=conf.nproc-1; i!=0; i--,p++)
- if(p->state != Dead) {
- pri = p->pri;
- pri -= pri >> 2;
- p->pri = pri;
- }
- }
+ n = (nrdy+n)*1000;
+ m->load = (m->load*19+n)/20;
}
M port/sysproc.c => port/sysproc.c +7 -7
@@ 178,8 178,9 @@ sysrfork(ulong *arg)
* (i.e. has bad properties) and has to be discarded.
*/
flushmmu();
- p->nice = up->nice;
- p->pri = up->pri;
+ p->priority = up->priority;
+ p->basepri = up->basepri;
+ p->mp = up->mp;
if(up->wired)
procwired(p);
ready(p);
@@ 397,10 398,9 @@ sysexec(ulong *arg)
/*
* '/' processes are higher priority (hack to make /ip more responsive).
*/
- if(devchar[tc->type] == L'/') {
- up->nice = NiceRoot;
- up->pri = 0;
- }
+ if(devchar[tc->type] == L'/')
+ up->basepri = PriRoot;
+ up->priority = up->basepri;
poperror();
close(tc);
@@ 462,11 462,11 @@ return0(void *a)
long
syssleep(ulong *arg)
{
+
int n;
n = arg[0];
if(n <= 0) {
- up->yield = 1;
sched();
return 0;
}
M port/taslock.c => port/taslock.c +21 -48
@@ 8,86 8,59 @@
void
lock(Lock *l)
{
- int n;
+ if(tas(&l->key) == 0)
+ return;
- if(up) {
- n = up->inlock+2;
- up->inlock = n;
+ for(;;){
+ while(l->key)
+ ;
if(tas(&l->key) == 0)
return;
-
- for(;;){
- while(l->key)
- if(conf.nproc == 1) {
- up->yield = 1;
- sched();
- }
- up->inlock = n;
- if(tas(&l->key) == 0)
- return;
- }
}
+}
- if(tas(&l->key) == 0)
+void
+ilock(Lock *l)
+{
+ ulong x;
+
+ x = splhi();
+ if(tas(&l->key) == 0){
+ l->sr = x;
return;
+ }
+
for(;;){
while(l->key)
;
- if(tas(&l->key) == 0)
+ if(tas(&l->key) == 0){
+ l->sr = x;
return;
+ }
}
}
int
canlock(Lock *l)
{
- int n;
-
- if(up) {
- n = up->inlock;
- up->inlock = n+2;
- if(tas(&l->key)) {
- up->inlock = n;
- return 0;
- }
- return 1;
- }
-
if(tas(&l->key))
return 0;
+
return 1;
}
void
unlock(Lock *l)
{
- int n;
-
- if(up) {
- n = up->inlock-2;
- if(n < 0)
- n = 0;
- up->inlock = n;
- }
l->key = 0;
}
void
-ilock(Lock *l)
-{
- ulong sr;
-
- sr = splhi();
- lock(l);
- l->sr = sr;
-}
-
-void
iunlock(Lock *l)
{
ulong sr;
sr = l->sr;
- unlock(l);
+ l->key = 0;
splx(sr);
}
M power/clock.c => power/clock.c +1 -1
@@ 103,7 103,7 @@ clock(Ureg *ur)
if(up == 0 || (ur->status&IEP) == 0 || up->state != Running)
return;
- if(anyready() && !up->inlock)
+ if(anyready())
sched();
/* user profiling clock */