@@ 1147,9 1147,10 @@ procctlreq(Proc *p, char *va, int n)
procpriority(p, pri, 0);
break;
case CMfixedpri:
- if(!iseve())
+ pri = atoi(cb->f[1]);
+ if(pri > PriNormal && !iseve())
error(Eperm);
- procpriority(p, atoi(cb->f[1]), 1);
+ procpriority(p, pri, 1);
break;
case CMprivate:
p->privatemem = 1;
@@ 260,25 260,100 @@ ready(Proc *p)
}
/*
- * yield the processor to any other runnable process
+ * remove a process from a scheduling queue (called splhi)
+ */
+static Proc*
+dequeueproc(Schedq *rq, Proc *tp)
+{
+ Proc *l, *p;
+
+ if(!canlock(runq))
+ return nil;
+
+ /*
+ * the queue may have changed before we locked runq,
+ * refind the target process.
+ */
+ l = 0;
+ for(p = rq->head; p; p = p->rnext){
+ if(p == tp)
+ break;
+ l = p;
+ }
+
+ /*
+ * p->mach==0 only when process state is saved
+ */
+ if(p == 0 || p->mach){
+ unlock(runq);
+ return nil;
+ }
+ if(p->rnext == 0)
+ rq->tail = l;
+ if(l)
+ l->rnext = p->rnext;
+ else
+ rq->head = p->rnext;
+ if(rq->head == nil)
+ runvec &= ~(1<<(rq-runq));
+ rq->n--;
+ nrdy--;
+ if(p->state != Ready)
+ print("dequeueproc %s %lud %s\n", p->text, p->pid, statename[p->state]);
+
+ unlock(runq);
+ return p;
+}
+
+/*
+ * yield the processor and drop our priority
*/
void
yield(void)
{
if(anyready()){
- up->yield = 1;
+ up->quanta = 0; /* act like you used them all up */
sched();
}
}
/*
+ * move up any process waiting more than its quanta
+ */
+static void
+rebalance(void)
+{
+ Schedq *rq;
+ Proc *p;
+
+ for(rq = runq; rq < &runq[Nrq]; rq++){
+ p = rq->head;
+ if(p == nil)
+ continue;
+ if(p->mp != MACHP(m->machno))
+ continue;
+ if(p->priority == p->basepri)
+ continue;
+ if(m->ticks - p->readytime < quanta[p->priority]/4)
+ continue;
+ splhi();
+ p = dequeueproc(rq, p);
+ spllo();
+ if(p == nil)
+ continue;
+ p->quanta = quanta[p->priority]; /* act like we used none */
+ ready(p);
+ }
+}
+
+/*
* pick a process to run
*/
Proc*
runproc(void)
{
Schedq *rq;
- Proc *p, *l, *tp;
+ Proc *p;
ulong start, now;
int i;
@@ 287,6 362,11 @@ runproc(void)
if ((p = edf->edfrunproc()) != nil)
return p;
+ if(m->fairness++ == 10){
+ m->fairness = 0;
+ rebalance();
+ }
+
loop:
/*
* find a process that last ran on this processor (affinity),
@@ 301,13 381,9 @@ loop:
*
*/
for(rq = &runq[Nrq-1]; rq >= runq; rq--){
- for(tp = rq->head; tp; tp = tp->rnext){
- if(tp->yield){
- tp->yield = 0;
- continue;
- }
- if(tp->mp == nil || tp->mp == MACHP(m->machno)
- || (!tp->wired && i > 0))
+ for(p = rq->head; p; p = p->rnext){
+ if(p->mp == nil || p->mp == MACHP(m->machno)
+ || (!p->wired && i > 0))
goto found;
}
}
@@ 323,40 399,9 @@ loop:
found:
splhi();
- if(!canlock(runq))
- goto loop;
-
- /*
- * the queue may have changed before we locked runq,
- * refind the target process.
- */
- l = 0;
- for(p = rq->head; p; p = p->rnext){
- if(p == tp)
- break;
- l = p;
- }
-
- /*
- * p->mach==0 only when process state is saved
- */
- if(p == 0 || p->mach){
- unlock(runq);
+ p = dequeueproc(rq, p);
+ if(p == nil)
goto loop;
- }
- if(p->rnext == 0)
- rq->tail = l;
- if(l)
- l->rnext = p->rnext;
- else
- rq->head = p->rnext;
- if(rq->head == nil)
- runvec &= ~(1<<(rq-runq));
- rq->n--;
- nrdy--;
- if(p->state != Ready)
- print("runproc %s %lud %s\n", p->text, p->pid, statename[p->state]);
- unlock(runq);
p->state = Scheding;
p->mp = MACHP(m->machno);