@@ 66,7 66,7 @@ dumptask(char *p, char *e, Task *t, Ticks now)
char c;
p = seprint(p, e, "{%s, D%U, Δ%U,T%U, C%U, S%U",
- edf_statename[t->state], t->D, t->Δ, t->T, t->C, t->S);
+ edf_statename[t->state], t->D, t->Delta, t->T, t->C, t->S);
n = t->r - now;
if (n >= 0)
c = ' ';
@@ 214,7 214,7 @@ devrtinit(void)
static Chan *
devrtattach(char *param)
{
- return devattach(L'⌛', param);
+ return devattach(L'Σ', param);
}
static Walkqid *
@@ 327,6 327,7 @@ devrtread(Chan *c, void *v, long n, vlong offs)
Task *t;
int s, i, fst;
Ticks now;
+ Time tim;
n0 = n;
// print("schedread 0x%lux\n", (ulong)c->qid.path);
@@ 342,13 343,18 @@ devrtread(Chan *c, void *v, long n, vlong offs)
return devdirread(c, v, n, nil, 0, schedgen);
case Qtime:
- if (n < sizeof(Ticks))
+ if (n < sizeof(Time))
error(Ebadarg);
now = fastticks(nil);
- memmove(v, &now, sizeof(Ticks));
+ tim = ticks2time(now);
+ memmove(v, &tim, sizeof(Time));
n -= sizeof(Ticks);
if (n >= sizeof(Ticks)){
- memmove((char*)v + sizeof(Time), &fasthz, sizeof(Ticks));
+ memmove((char*)v + sizeof(Time), &now, sizeof(Ticks));
+ n -= sizeof(Ticks);
+ }
+ if (n >= sizeof(Ticks)){
+ memmove((char*)v + sizeof(Time) + sizeof(Ticks), &fasthz, sizeof(Ticks));
n -= sizeof(Ticks);
}
break;
@@ 403,10 409,10 @@ devrtread(Chan *c, void *v, long n, vlong offs)
}
p = seprint(p, e, "'");
}
- if (resources[i].Δ)
- p = seprint(p, e, " Δ=%T", ticks2time(resources[i].Δ));
- else if (resources[i].testΔ)
- p = seprint(p, e, " testΔ=%T", ticks2time(resources[i].testΔ));
+ if (resources[i].Delta)
+ p = seprint(p, e, " Δ=%T", ticks2time(resources[i].Delta));
+ else if (resources[i].testDelta)
+ p = seprint(p, e, " testΔ=%T", ticks2time(resources[i].testDelta));
p = seprint(p, e, "\n");
}
return readstr(offs, v, n, buf);
@@ 450,10 456,11 @@ devrtread(Chan *c, void *v, long n, vlong offs)
p = seprint(p, e, " D=%T", ticks2time(t->D));
if (t->C)
p = seprint(p, e, " C=%T", ticks2time(t->C));
- if (t->Δ)
- p = seprint(p, e, " Δ=%T", ticks2time(t->Δ));
- else if (t->testΔ)
- p = seprint(p, e, " testΔ=%T", ticks2time(t->testΔ));
+ if (t->Delta)
+ p = seprint(p, e, " Δ=%T", ticks2time(t->Delta));
+ else if (t->testDelta)
+ p = seprint(p, e, " testΔ=%T", ticks2time(t->testDelta));
+ p = seprint(p, e, " yieldonblock=%d", (t->flags & Verbose) != 0);
if (t->nres){
p = seprint(p, e, " resources='");
fst = 0;
@@ 603,6 610,49 @@ proctotask(Task *t, Proc *p, int add)
return nil;
}
+static void
+removetask(Task *t)
+{
+ int s, i;
+ Proc *p, **pp;
+ Resource *r;
+
+ qlock(t);
+ edf_expel(t);
+ for (pp = t->procs; pp < t->procs + nelem(t->procs); pp++)
+ if (p = *pp)
+ p->task = nil;
+ while (p = t->runq.head){
+ /* put runnable procs on regular run queue */
+ t->runq.head = p->rnext;
+ ready(p);
+ t->runq.n--;
+ }
+ t->runq.tail = nil;
+ assert(t->runq.n == 0);
+ for (s = 0; s < nelem(t->res); s++){
+ if (t->res[s] == nil)
+ continue;
+ r = t->res[s];
+ for (i = 0; i < nelem(r->tasks); i++)
+ if (r->name && r->tasks[i] == t){
+ r->tasks[i] = nil;
+ if (--r->ntasks == 0){
+ /* resource became unused, delete it */
+ free(r->name);
+ r->name = nil;
+ nresources--;
+ }
+ }
+ }
+ if(t->user){
+ free(t->user);
+ t->user = nil;
+ }
+ t->state = EdfUnused;
+ qunlock(t);
+}
+
static long
devrtwrite(Chan *c, void *va, long n, vlong)
{
@@ 611,6 661,7 @@ devrtwrite(Chan *c, void *va, long n, vlong)
Resource **rp, *r;
Proc **pp;
Task *t;
+ Ticks ticks;
Time time;
long pid;
Proc *p;
@@ 652,18 703,60 @@ devrtwrite(Chan *c, void *va, long n, vlong)
if (strcmp(a, "T") == 0){
if (e=parsetime(&time, v))
error(e);
+ ticks = time2ticks(time);
edf_expel(t);
- t->T = time2ticks(time);
+ switch(add){
+ case -1:
+ if (ticks > t->T)
+ t->T = 0;
+ else
+ t->T -= ticks;
+ break;
+ case 0:
+ t->T = ticks;
+ break;
+ case 1:
+ t->T += ticks;
+ break;
+ }
}else if (strcmp(a, "D") == 0){
if (e=parsetime(&time, v))
error(e);
+ ticks = time2ticks(time);
edf_expel(t);
- t->D = time2ticks(time);
+ switch(add){
+ case -1:
+ if (ticks > t->D)
+ t->D = 0;
+ else
+ t->D -= ticks;
+ break;
+ case 0:
+ t->D = ticks;
+ break;
+ case 1:
+ t->D += ticks;
+ break;
+ }
}else if (strcmp(a, "C") == 0){
if (e=parsetime(&time, v))
error(e);
+ ticks = time2ticks(time);
edf_expel(t);
- t->C = time2ticks(time);
+ switch(add){
+ case -1:
+ if (ticks > t->C)
+ t->C = 0;
+ else
+ t->C -= ticks;
+ break;
+ case 0:
+ t->C = ticks;
+ break;
+ case 1:
+ t->C += ticks;
+ break;
+ }
}else if (strcmp(a, "resources") == 0){
if (v == nil)
error("resources: value missing");
@@ 703,13 796,17 @@ devrtwrite(Chan *c, void *va, long n, vlong)
}
nrargs = tokenize(v, rargs, nelem(rargs));
for (j = 0; j < nrargs; j++){
- pid = atoi(rargs[j]);
- if (pid <= 0)
- error("bad process number");
- s = procindex(pid);
- if(s < 0)
- error("no such process");
- p = proctab(s);
+ if (strcmp("self", rargs[j]) == 0){
+ p = up;
+ }else{
+ pid = atoi(rargs[j]);
+ if (pid <= 0)
+ error("bad process number");
+ s = procindex(pid);
+ if(s < 0)
+ error("no such process");
+ p = proctab(s);
+ }
if (e = proctotask(t, p, add))
error(e);
}
@@ 717,15 814,25 @@ devrtwrite(Chan *c, void *va, long n, vlong)
/* Do the admission test */
if (e = edf_admit(t))
error(e);
+ }else if (strcmp(a, "expel") == 0){
+ /* Do the admission test */
+ edf_expel(t);
+ }else if (strcmp(a, "remove") == 0){
+ /* Do the admission test */
+ removetask(t);
+ return n; /* Ignore any subsequent commands */
}else if (strcmp(a, "verbose") == 0){
/* Do the admission test */
if (t->flags & Verbose)
t->flags &= ~Verbose;
else
t->flags |= Verbose;
- }else if (strcmp(a, "useblocking") == 0){
- /* Do the admission test */
- if (t->flags & Useblocking)
+ }else if (strcmp(a, "yieldonblock") == 0){
+ if (v == nil)
+ error("yieldonblock: value missing");
+ if (add != 0)
+ error("yieldonblock: cannot increment/decrement");
+ if (atoi(v) == 0)
t->flags &= ~Useblocking;
else
t->flags |= Useblocking;
@@ 745,10 852,8 @@ devrtwrite(Chan *c, void *va, long n, vlong)
static void
devrtremove(Chan *c)
{
- int s, i;
+ int s;
Task *t;
- Proc *p, **pp;
- Resource *r;
if ((c->qid.path & Qistask) == 0)
error(Eperm);
@@ 756,44 861,11 @@ devrtremove(Chan *c)
t = tasks + s;
if (s < 0 || s >= Maxtasks || t->state == EdfUnused)
error(Enonexist);
- qlock(t);
- edf_expel(t);
- for (pp = t->procs; pp < t->procs + nelem(t->procs); pp++)
- if (p = *pp)
- p->task = nil;
- while (p = t->runq.head){
- /* put runnable procs on regular run queue */
- t->runq.head = p->rnext;
- ready(p);
- t->runq.n--;
- }
- t->runq.tail = nil;
- assert(t->runq.n == 0);
- for (s = 0; s < nelem(t->res); s++){
- if (t->res[s] == nil)
- continue;
- r = t->res[s];
- for (i = 0; i < nelem(r->tasks); i++)
- if (r->name && r->tasks[i] == t){
- r->tasks[i] = nil;
- if (--r->ntasks == 0){
- /* resource became unused, delete it */
- free(r->name);
- r->name = nil;
- nresources--;
- }
- }
- }
- if(t->user){
- free(t->user);
- t->user = nil;
- }
- t->state = EdfUnused;
- qunlock(t);
+ removetask(t);
}
Dev realtimedevtab = {
- L'⌛',
+ L'Σ',
"scheduler",
devreset,
@@ 72,8 72,8 @@ void (*devrt)(Task*, Ticks, int);
static void edf_intr(Ureg*, Cycintr*);
static void edf_resched(Task *t);
-static void setΔ(void);
-static void testΔ(Task *thetask);
+static void setdelta(void);
+static void testdelta(Task *thetask);
static char * edf_testschedulability(Task *thetask);
static void edf_setclock(void);
@@ 226,10 226,14 @@ edf_block(Proc *p)
/* The current proc has blocked */
ilock(&edflock);
t = p->task;
+ assert(t);
+ if (t->state != EdfRunning){
+ /* called by a proc just joining the task */
+ iunlock(&edflock);
+ return;
+ }
DENTER("%.*s%d edf_block, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n);
- assert(t);
- assert(t->state == EdfRunning);
if (t->runq.n){
/* There's another runnable proc in the running task, leave task where it is */
iunlock(&edflock);
@@ 255,12 259,11 @@ edfdeadline(Proc *p, SEvent why)
if (p){
nt = p->task;
assert(nt);
- assert(nt->state == EdfRunning);
}
t = edfpop();
if(p != nil && nt != t){
- DPRINT("%.*s%d edfdeadline, %s, %d\n", ind, tabs, m->machno, edf_statename[p->task->state], p->task->runq.n);
+ iprint("edfdeadline, %s, %d\n", edf_statename[p->task->state], p->task->runq.n);
iunlock(&edflock);
assert(0 && p == nil || nt == t);
}
@@ 326,7 329,7 @@ edf_admit(Task *t)
t->scheduled = now;
t->state = EdfRunning;
if(devrt) devrt(t, now, SRun);
- setΔ();
+ setdelta();
assert(t->runq.n > 0 || (up && up->task == t));
edfpush(t);
edf_setclock();
@@ 336,7 339,7 @@ edf_admit(Task *t)
t->state = EdfAdmitted;
t->r = now;
edf_release(t);
- setΔ();
+ setdelta();
edf_resched(t);
}else{
edfenqueue(&qadmit, t);
@@ 393,7 396,7 @@ edf_expel(Task *t)
}
t->state = EdfExpelled;
if(devrt) devrt(t, now, SExpel);
- setΔ();
+ setdelta();
DLEAVE;
iunlock(&edflock);
qunlock(&edfschedlock);
@@ 739,7 742,7 @@ edf_runproc(void)
return nil;
}
DENTER("edf_runproc %lud\n", nilcount);
- if (nt && (t == nil || (nt->D < t->Δ && nt->d < t->d))){
+ if (nt && (t == nil || (nt->d < t->d && nt->D < t->Delta))){
/* released task is better than current */
DPRINT("%.*s%d edf_runproc: released\n", ind, tabs, m->machno);
edfdequeue(&qreleased);
@@ 777,8 780,6 @@ static Lock waitlock;
int
edf_waitlock(Lock *l)
{
- Task *t;
-
iprint("edf_waitlock\n");
ilock(&waitlock); /* can't afford normal locks here */
if (l->key == 0){
@@ 820,7 821,7 @@ edf_releaselock(Lock *l)
/* Schedulability testing and its supporting routines */
static void
-setΔ(void)
+setdelta(void)
{
Resource *r, **rr;
Task **tt, *t;
@@ 828,23 829,23 @@ setΔ(void)
for (r = resources; r < resources + nelem(resources); r++){
if (r->name == nil)
continue;
- r->Δ = ~0LL;
+ r->Delta = ~0LL;
for (tt = r->tasks; tt < r->tasks + nelem(r->tasks); tt++)
- if (*tt && (*tt)->D < r->Δ)
- r->Δ = (*tt)->D;
+ if (*tt && (*tt)->D < r->Delta)
+ r->Delta = (*tt)->D;
}
for (t = tasks; t < tasks + nelem(tasks); t++){
if (t->state < EdfIdle)
continue;
- t->Δ = t->D;
+ t->Delta = t->D;
for (rr = t->res; rr < t->res + nelem(t->res); rr++)
- if (*rr && (*rr)->Δ < t->Δ)
- t->Δ = (*rr)->Δ;
+ if (*rr && (*rr)->Delta < t->Delta)
+ t->Delta = (*rr)->Delta;
}
}
static void
-testΔ(Task *thetask)
+testdelta(Task *thetask)
{
Resource *r, **rr;
Task **tt, *t;
@@ 852,18 853,18 @@ testΔ(Task *thetask)
for (r = resources; r < resources + nelem(resources); r++){
if (r->name == nil)
continue;
- r->testΔ = ~0ULL;
+ r->testDelta = ~0ULL;
for (tt = r->tasks; tt < r->tasks + nelem(r->tasks); tt++)
- if (*tt && (*tt)->D < r->testΔ)
- r->testΔ = (*tt)->D;
+ if (*tt && (*tt)->D < r->testDelta)
+ r->testDelta = (*tt)->D;
}
for (t = tasks; t < tasks + nelem(tasks); t++){
if (t->state <= EdfExpelled && t != thetask)
continue;
- t->testΔ = t->D;
+ t->testDelta = t->D;
for (rr = t->res; rr < t->res + nelem(t->res); rr++)
- if (*rr && (*rr)->testΔ < t->testΔ)
- t->testΔ = (*rr)->testΔ;
+ if (*rr && (*rr)->testDelta < t->testDelta)
+ t->testDelta = (*rr)->testDelta;
}
}
@@ 877,7 878,7 @@ blockcost(Ticks ticks, Task *thetask)
for (t = tasks; t < tasks + Maxtasks; t++){
if (t->state <= EdfExpelled && t != thetask)
continue;
- if (t->testΔ <= ticks && ticks < t->D && Cb < t->C)
+ if (t->testDelta <= ticks && ticks < t->D && Cb < t->C)
Cb = t->C;
}
return Cb;
@@ 917,7 918,7 @@ edf_testschedulability(Task *thetask)
int steps;
/* initialize */
- testΔ(thetask);
+ testdelta(thetask);
if (thetask && (thetask->flags & Verbose))
pprint("schedulability test\n");
qschedulability = nil;
@@ 986,6 987,8 @@ Time
ticks2time(Ticks ticks)
{
assert(ticks >= 0);
+ if (fasthz == 0)
+ fastticks(&fasthz);
return uvmuldiv(ticks, Onesecond, fasthz);
}