@@ 6,8 6,7 @@
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
-#include "../port/devrealtime.h"
-#include "../port/edf.h"
+#include "../port/realtime.h"
#pragma varargck type "T" vlong
@@ 22,10 21,6 @@ static QLock elock;
static Ref logopens;
static Ref debugopens;
static uvlong fasthz;
-static int taskno;
-
-static int timeconv(Fmt *);
-static char * parsetime(Time *, char *);
enum {
Qistask = 0x10000,
@@ 73,69 68,7 @@ static char *schedstatename[] = {
[SExpel] = "Expel",
};
-Task *
-findtask(int taskno)
-{
- List *l;
- Task *t;
-
- for (l = tasks.next; l; l = l->next)
- if ((t = l->i) && t->taskno == taskno)
- return t;
- return nil;
-}
-
-static char*
-dumptask(char *p, char *e, Task *t, Ticks now)
-{
- vlong n;
- char c;
-
- p = seprint(p, e, "{%s, D%U, Δ%U,T%U, C%U, S%U",
- edfstatename[t->state], t->D, t->Delta, t->T, t->C, t->S);
- n = t->r - now;
- if (n >= 0)
- c = ' ';
- else {
- n = -n;
- c = '-';
- }
- p = seprint(p, e, ", r%c%U", c, (uvlong)n);
- n = t->d - now;
- if (n >= 0)
- c = ' ';
- else {
- n = -n;
- c = '-';
- }
- p = seprint(p, e, ", d%c%U", c, (uvlong)n);
- n = t->t - now;
- if (n >= 0)
- c = ' ';
- else {
- n = -n;
- c = '-';
- }
- p = seprint(p, e, ", t%c%U}", c, (uvlong)n);
- return p;
-}
-
-static char*
-dumpq(char *p, char *e, Taskq *q, Ticks now)
-{
- Task *t;
-
- t = q->head;
- for(;;){
- if (t == nil)
- return seprint(p, e, "\n");
- p = dumptask(p, e, t, now);
- t = t->rnext;
- if (t)
- seprint(p, e, ", ");
- }
- return nil;
-}
+static int taskno;
static Task *
taskinit(void)
@@ 168,7 101,7 @@ taskfree(Task *t)
if (decref(t))
return;
assert(t->procs.n == 0);
- assert(t->res.n == 0);
+ assert(t->csns.n == 0);
free(t->user);
free(t);
}
@@ 381,7 314,6 @@ devrtread(Chan *c, void *v, long n, vlong offs)
Ticks now;
Time tim;
List *l;
- Resource *r;
n0 = n;
// print("schedread 0x%lux\n", (ulong)c->qid.path);
@@ 450,29 382,7 @@ devrtread(Chan *c, void *v, long n, vlong offs)
qunlock(&edfschedlock);
nexterror();
}
- p = buf;
- e = p + sizeof(buf);
- for (l = resources.next; l; l = l->next){
- r = l->i;
- assert(r);
- p = seprint(p, e, "name=%s", r->name);
- if (r->tasks.n){
- List *l;
-
- p = seprint(p, e, " tasks='");
- for (l = r->tasks.next; l; l = l->next) {
- if (l != r->tasks.next)
- p = seprint(p, e, " ");
- p = seprint(p, e, "%d", ((Task *)l->i)->taskno);
- }
- p = seprint(p, e, "'");
- }
- if (r->Delta)
- p = seprint(p, e, " Δ=%T", ticks2time(r->Delta));
- else if (r->testDelta)
- p = seprint(p, e, " testΔ=%T", ticks2time(r->testDelta));
- p = seprint(p, e, "\n");
- }
+ seprintresources(buf, buf + sizeof(buf));
qunlock(&edfschedlock);
poperror();
return readstr(offs, v, n, buf);
@@ 482,7 392,7 @@ devrtread(Chan *c, void *v, long n, vlong offs)
e = p + sizeof(buf);
qlock(&edfschedlock);
qunlock(&edfschedlock);
- p = seprint(p, e, "\n");
+ seprint(p, e, "\n");
return readstr(offs, v, n, buf);
case Qdebug:
p = buf;
@@ 530,15 440,9 @@ devrtread(Chan *c, void *v, long n, vlong offs)
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->res.n){
+ if (t->csns.n){
p = seprint(p, e, " resources='");
- for (l = t->res.next; l; l = l->next){
- r = l->i;
- assert(r);
- if (l != t->res.next)
- p = seprint(p, e, " ");
- p = seprint(p, e, "%s", r->name);
- }
+ p = seprintcsn(p, e, &t->csns);
p = seprint(p, e, "'");
}
if (t->procs.n){
@@ 569,72 473,6 @@ devrtread(Chan *c, void *v, long n, vlong offs)
return n0 - n;
}
-static Resource *
-resource(char *name, int add)
-{
- Resource *r;
- List *l;
-
- for (l = resources.next; l; l = l->next)
- if ((r = l->i) && strcmp(r->name, name) == 0)
- return r;
- if (add < 0)
- return nil;
- r = malloc(sizeof(Resource));
- if (r == nil)
- error("resource: malloc");
- kstrdup(&r->name, name);
- enlist(&resources, r);
- return r;
-}
-
-void
-resourcefree(Resource *r)
-{
- if (decref(r))
- return;
- delist(&resources, r);
- assert(r->tasks.n == 0);
- free(r->name);
- free(r);
-}
-
-static void
-removetask(Task *t)
-{
- Proc *p;
- Resource *r;
- List *l;
-
- edf->edfexpel(t);
- while (l = t->procs.next){
- p = l->i;
- assert(p);
- p->task = nil;
- delist(&t->procs, p);
- }
- 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);
- while (l = t->res.next){
- r = l->i;
- if (delist(&r->tasks, t))
- taskfree(t);
- if (delist(&t->res, r))
- resourcefree(r);
- }
- free(t->user);
- t->user = nil;
- t->state = EdfUnused;
- if (delist(&tasks, t))
- taskfree(t);
-}
-
static long
devrtwrite(Chan *c, void *va, long n, vlong)
{
@@ 646,6 484,7 @@ devrtwrite(Chan *c, void *va, long n, vlong)
Time time;
long pid;
Proc *p;
+ CSN *l;
a = va;
if (c->mode == OREAD)
@@ 707,6 546,7 @@ devrtwrite(Chan *c, void *va, long n, vlong)
}
if (t->T < time2ticks(10000000/HZ))
error("period too short");
+ DEBUG("Task %d, T=%T\n", t->taskno, ticks2time(t->T));
}else if (strcmp(a, "D") == 0){
if (e=parsetime(&time, v))
error(e);
@@ 726,6 566,7 @@ devrtwrite(Chan *c, void *va, long n, vlong)
t->D += ticks;
break;
}
+ DEBUG("Task %d, D=%T\n", t->taskno, ticks2time(t->D));
}else if (strcmp(a, "C") == 0){
if (e=parsetime(&time, v))
error(e);
@@ 747,40 588,54 @@ devrtwrite(Chan *c, void *va, long n, vlong)
}
if (t->C < time2ticks(10000000/HZ))
error("cost too small");
+ DEBUG("Task %d, C=%T\n", t->taskno, ticks2time(t->C));
}else if (strcmp(a, "resources") == 0){
if (v == nil)
error("resources: value missing");
edf->edfexpel(t);
+ if (add < 0)
+ error("can't remove resources yet");
if (add == 0){
List *l;
-
- while (l = t->res.next) {
+
+ while (l = t->csns.next) {
r = l->i;
assert(r);
if (delist(&r->tasks, t))
taskfree(t);
- if (delist(&t->res, r))
+ if (delist(&t->csns, r))
resourcefree(r);
}
- assert(t->res.n == 0);
+ assert(t->csns.n == 0);
add = 1;
+ USED(add);
}
- nrargs = tokenize(v, rargs, nelem(rargs));
- for (j = 0; j < nrargs; j++)
- if (r = resource(rargs[j], add)){
- if (add > 0){
- if (enlist(&r->tasks, t))
- incref(t);
- if (enlist(&t->res, r))
- incref(r);
- }else{
- if (delist(&r->tasks, t))
- taskfree(t);
- if (delist(&t->res, r))
- resourcefree(r);
- }
- }else
- error("resource not found");
+ v = parseresource(&t->csns, nil, v);
+ if (v && *v)
+ error("resources: parse error");
+ }else if (strcmp(a, "acquire") == 0){
+ if (v == nil)
+ error("acquire: value missing");
+ if ((r = resource(v, 0)) == nil)
+ error("acquire: no such resource");
+ for (l = (CSN*)t->csns.next; l; l = (CSN*)l->next){
+ if (l->i == r){
+DEBUG("l->p (0x%p) == t->curcsn (0x%p) && l->S (%T) != 0\n", l->p, t->curcsn, ticks2time(l->S));
+ if(l->p == t->curcsn && l->S != 0)
+ break;
+ }
+ }
+ if (l == nil)
+ error("acquire: no access or resource exhausted");
+ edf->resacquire(t, l);
+ }else if (strcmp(a, "release") == 0){
+ if (v == nil)
+ error("release: value missing");
+ if ((r = resource(v, 0)) == nil)
+ error("release: no such resource");
+ if (t->curcsn->i != r)
+ error("release: release not held or illegal release order");
+ edf->resrelease(t);
}else if (strcmp(a, "procs") == 0){
if (v == nil)
error("procs: value missing");
@@ 904,129 759,3 @@ Dev realtimedevtab = {
devrtremove,
devwstat,
};
-
-static int
-timeconv(Fmt *f)
-{
- char buf[128], *sign;
- Time t;
- Ticks ticks;
-
- buf[0] = 0;
- switch(f->r) {
- case 'U':
- ticks = va_arg(f->args, Ticks);
- t = ticks2time(ticks);
- break;
- case 'T': // Time in nanoseconds
- t = va_arg(f->args, Time);
- break;
- default:
- return fmtstrcpy(f, "(timeconv)");
- }
- if (t < 0) {
- sign = "-";
- t = -t;
- }
- else
- sign = "";
- if (t > Onesecond)
- sprint(buf, "%s%d.%.3ds", sign, (int)(t / Onesecond), (int)(t % Onesecond)/1000000);
- else if (t > Onemillisecond)
- sprint(buf, "%s%d.%.3dms", sign, (int)(t / Onemillisecond), (int)(t % Onemillisecond)/1000);
- else if (t > Onemicrosecond)
- sprint(buf, "%s%d.%.3dµs", sign, (int)(t / Onemicrosecond), (int)(t % Onemicrosecond));
- else
- sprint(buf, "%s%dns", sign, (int)t);
- return fmtstrcpy(f, buf);
-}
-
-static char *
-parsetime(Time *rt, char *s)
-{
- uvlong ticks;
- ulong l;
- char *e, *p;
- static int p10[] = {100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
-
- if (s == nil)
- return("missing value");
- ticks=strtoul(s, &e, 10);
- if (*e == '.'){
- p = e+1;
- l = strtoul(p, &e, 10);
- if(e-p > nelem(p10))
- return "too many digits after decimal point";
- if(e-p == 0)
- return "ill-formed number";
- l *= p10[e-p-1];
- }else
- l = 0;
- if (*e){
- if(strcmp(e, "s") == 0)
- ticks = 1000000000 * ticks + l;
- else if (strcmp(e, "ms") == 0)
- ticks = 1000000 * ticks + l/1000;
- else if (strcmp(e, "µs") == 0 || strcmp(e, "us") == 0)
- ticks = 1000 * ticks + l/1000000;
- else if (strcmp(e, "ns") != 0)
- return "unrecognized unit";
- }
- *rt = ticks;
- return nil;
-}
-
-int
-putlist(Head *h, List *l)
-{
- l->next = h->next;
- h->next = l;
- h->n++;
- return 1;
-}
-
-int
-enlist(Head *h, void *i)
-{
- List *l;
-
- for (l = h->next; l; l = l->next)
- if (l->i == i){
- /* already on the list */
- return 0;
- }
- l = malloc(sizeof(List));
- if (l == nil)
- panic("malloc in enlist");
- l->i = i;
- l->next = h->next;
- h->next = l;
- h->n++;
- return 1;
-}
-
-int
-delist(Head *h, void *i)
-{
- List *l, **p;
-
- for (p = &h->next; l = *p; p = &l->next)
- if (l->i == i){
- *p = l->next;
- free(l);
- h->n--;
- return 1;
- }
- return 0;
-}
-
-void *
-findlist(Head *h, void *i)
-{
- List *l;
-
- for (l = h->next; l; l = l->next)
- if (l->i == i)
- return i;
- return nil;
-}
@@ 5,8 5,7 @@
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
-#include "../port/devrealtime.h"
-#include "../port/edf.h"
+#include "../port/realtime.h"
/* debugging */
int edfprint = 0;
@@ 30,7 29,6 @@ static Timer deadlinetimer[MAXMACH]; /* Time of next deadline */
static Timer releasetimer[MAXMACH]; /* Time of next release */
static int initialized;
-static uvlong fasthz;
static Ticks now;
/* Edfschedlock protects modification of sched params, including resources */
QLock edfschedlock;
@@ 62,6 60,8 @@ Taskq qextratime;
/* Running/Preempted EDF tasks, head running, one stack per processor */
Taskq edfstack[MAXMACH];
+static Task *qschedulability;
+
void (*devrt)(Task*, Ticks, int);
static void edfresched(Task *t);
@@ 83,7 83,6 @@ edfinit(void)
iunlock(&edflock);
return;
}
- fastticks(&fasthz);
for (i = 0; i < conf.nmach; i++){
deadlinetimer[i].f = edfdeadlineintr;
deadlinetimer[i].a = &deadlinetimer[i];
@@ 298,7 297,9 @@ edfdeadline(Proc *p)
static char *
edfadmit(Task *t)
{
- char *err;
+ char *err, *p;
+ static char csndump[512];
+ CSN *c;
/* Called with edfschedlock held */
if (t->state != EdfExpelled)
@@ 316,11 317,19 @@ edfadmit(Task *t)
if (t->C > t->D)
return "C > D";
+ resourcetimes(t, &t->csns);
+
+ DEBUG("task %d: T %T, C %T, D %T, tΔ %T\n",
+ t->taskno, ticks2time(t->T), ticks2time(t->C),
+ ticks2time(t->D), ticks2time(t->testDelta));
+ p = seprintresources(csndump, csndump+sizeof csndump);
+ seprintcsn(p, csndump+sizeof csndump, &t->csns);
+ DEBUG("%s\n", csndump);
+
if (err = edftestschedulability(t)){
return err;
}
ilock(&edflock);
- qunlock(&edfschedlock);
DPRINT("%d edfadmit, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
now = fastticks(nil);
@@ 339,6 348,10 @@ edfadmit(Task *t)
t->periods++;
if(devrt) devrt(t, now, SRun);
setdelta();
+ for (c = (CSN*)t->csns.next; c; c = (CSN*)c->next){
+ DEBUG("admit csn: C=%T\n", ticks2time(c->C));
+ c->S = c->C;
+ }
assert(t->runq.n > 0 || (up && up->task == t));
edfpush(t);
if (deadlinetimer[m->machno].when)
@@ 357,7 370,6 @@ edfadmit(Task *t)
}
}
iunlock(&edflock);
- qlock(&edfschedlock);
return nil;
}
@@ 413,13 425,14 @@ static void
edfreleaseintr(Ureg*, Timer*)
{
Task *t;
+ extern int panicking;
DPRINT("%d edfreleaseintr\n", m->machno);
timerdel(&releasetimer[m->machno]);
releasetimer[m->machno].when = 0;
- if(active.exiting)
+ if(panicking || active.exiting)
return;
ilock(&edflock);
@@ 442,18 455,23 @@ edfdeadlineintr(Ureg*, Timer*)
Ticks used;
Task *t;
+ Resource *r;
+ char buf[128];
+ int noted;
+ extern int panicking;
DPRINT("%d edfdeadlineintr\n", m->machno);
timerdel(&deadlinetimer[m->machno]);
deadlinetimer[m->machno].when = 0;
- if(active.exiting)
+ if(panicking || active.exiting)
return;
ilock(&edflock);
// If up is not set, we're running inside the scheduler
- // for non-real-time processes.
+ // for non-real-time processes.
+ noted = 0;
if (up && isedf(up)) {
now = fastticks(nil);
@@ 465,18 483,33 @@ edfdeadlineintr(Ureg*, Timer*)
t->total += used;
if (t->r < now){
- if (t->S <= used)
+ if (t->curcsn){
+ if (t->curcsn->S <= used){
+ t->curcsn->S = 0LL;
+ r = t->curcsn->i;
+ noted++;
+ snprint(buf, sizeof buf, "sys: deadline miss: resource %s", r->name);
+ }else
+ t->curcsn->S -= used;
+ }
+
+ if (t->S <= used){
t->S = 0LL;
- else
+ if (!noted){
+ noted++;
+ snprint(buf, sizeof buf, "sys: deadline miss: runtime");
+ }
+ }else
t->S -= used;
-
- if (t->d <= now || t->S == 0LL){
+
+ if (t->d <= now || t->S == 0LL || t->curcsn == 0LL){
/* Task has reached its deadline/slice, remove from queue */
if (t->d <= now){
t->missed++;
misseddeadlines++;
}
deadline(up, SSlice);
+
while (t = edfstack[m->machno].head){
if (now < t->d)
break;
@@ 486,6 519,8 @@ edfdeadlineintr(Ureg*, Timer*)
}
}
iunlock(&edflock);
+ if (noted)
+ postnote(up, 1, buf, NUser);
sched();
splhi();
}
@@ 667,12 702,18 @@ edfresched(Task *t)
static void
edfrelease(Task *t)
{
+ CSN *c;
+
DPRINT("%d edfrelease, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
assert(t->runq.n > 0 || (up && up->task == t));
t->t = t->r + t->T;
t->d = t->r + t->D;
if(devrt) devrt(t, t->d, SDeadline);
t->S = t->C;
+ for (c = (CSN*)t->csns.next; c; c = (CSN*)c->next){
+ DEBUG("release csn: C=%T\n", ticks2time(c->C));
+ c->S = c->C;
+ }
t->state = EdfReleased;
edfenqueue(&qreleased, t);
if(devrt) devrt(t, now, SRelease);
@@ 781,29 822,44 @@ setdelta(void)
{
Resource *r;
Task *t;
- List *lr, *lt;
+ int R;
+ List *lr, *l;
+ TaskLink *lt;
+ CSN *c;
for (lr = resources.next; lr; lr = lr->next){
r = lr->i;
assert(r);
- r->Delta = ~0LL;
- for (lt = r->tasks.next; lt; lt = lt->next){
+ r->Delta = Infinity;
+ R = 1;
+ for (lt = (TaskLink*)r->tasks.next; lt; lt = (TaskLink*)lt->next){
t = lt->i;
assert(t);
- if (t->D < r->Delta)
+ if (t->D < r->Delta){
r->Delta = t->D;
+ }
+ if (lt->R == 0){
+ R = 0;
+ }
}
+ if (R)
+ r->Delta = Infinity; /* Read-only resource, no exclusion */
}
- for (lt = tasks.next; lt ; lt = lt->next){
- t = lt->i;
+
+ /* Enumerate the critical sections */
+ for (l = tasks.next; l ; l = l->next){
+ t = l->i;
assert(t);
- if (t->state < EdfIdle)
+ if (t->state <= EdfExpelled)
continue;
- t->Delta = t->D;
- for (lr = t->res.next; lr; lr = lr->next){
- r = lr->i;
+ t->Delta = Infinity;
+ for (c = (CSN*)t->csns.next; c; c = (CSN*)c->next){
+ r = c->i;
assert(r);
- if (r->Delta < t->Delta)
+ c->Delta = r->Delta;
+ if (c->p && c->p->Delta < c->Delta)
+ c->Delta = c->p->Delta;
+ if (c->C == t->C && r->Delta < t->Delta)
t->Delta = r->Delta;
}
}
@@ 814,55 870,104 @@ testdelta(Task *thetask)
{
Resource *r;
Task *t;
- List *lr, *lt;
+ int R;
+ List *lr, *l;
+ TaskLink *lt;
+ CSN *c;
for (lr = resources.next; lr; lr = lr->next){
r = lr->i;
assert(r);
- r->testDelta = ~0ULL;
- for (lt = r->tasks.next; lt; lt = lt->next){
+ DEBUG("Resource %s: ", r->name);
+ r->testDelta = Infinity;
+ R = 1;
+ for (lt = (TaskLink*)r->tasks.next; lt; lt = (TaskLink*)lt->next){
t = lt->i;
assert(t);
- if (t->D < r->testDelta)
+ if (t->D < r->testDelta){
r->testDelta = t->D;
+ DEBUG("%d→%T ", t->taskno, ticks2time(t->D));
+ }
+ if (lt->R == 0){
+ DEBUG("%d→X ", t->taskno);
+ R = 0;
+ }
}
+ if (R)
+ r->testDelta = Infinity; /* Read-only resource, no exclusion */
+ DEBUG("tΔ = %T\n", ticks2time(r->testDelta));
}
- for (lt = tasks.next; lt ; lt = lt->next){
- t = lt->i;
+
+ /* Enumerate the critical sections */
+ for (l = tasks.next; l ; l = l->next){
+ t = l->i;
assert(t);
if (t->state <= EdfExpelled && t != thetask)
continue;
- t->testDelta = t->D;
- for (lr = t->res.next; lr; lr = lr->next){
- r = lr->i;
+ t->testDelta = Infinity;
+ for (c = (CSN*)t->csns.next; c; c = (CSN*)c->next){
+ r = c->i;
assert(r);
- if (r->testDelta < t->testDelta)
+ c->testDelta = r->testDelta;
+ if (c->p && c->p->testDelta < c->testDelta)
+ c->testDelta = c->p->testDelta;
+ if (c->C == t->C && r->testDelta < t->testDelta)
t->testDelta = r->testDelta;
+ DEBUG("Task %d Resource %s: tΔ = %T\n",
+ t->taskno, r->name, ticks2time(r->testDelta));
}
}
}
static Ticks
-blockcost(Ticks ticks, Task *thetask)
+blockcost(Ticks ticks, Task *task, Task *thetask)
{
+ Ticks Cb, Cbt;
+ List *l;
+ Resource *r;
+ CSN *c, *lc;
+ int R;
Task *t;
- Ticks Cb;
- List *lt;
Cb = 0;
- for (lt = tasks.next; lt ; lt = lt->next){
- t = lt->i;
- assert(t);
- if (t->state <= EdfExpelled && t != thetask)
- continue;
- if (t->testDelta <= ticks && ticks < t->D && Cb < t->C)
- Cb = t->C;
+ /* for each resource in task t, find all CSNs that refer to the
+ * resource. If their Δ <= ticks < D and c->C > current CB
+ * Cb = c->C
+ */
+ DEBUG("blockcost task %d: ", task->taskno);
+ for (c = (CSN*)task->csns.next; c; c = (CSN*)c->next){
+ r = c->i;
+ assert(r);
+
+ DEBUG("%s ", r->name);
+ Cbt = Cb;
+ R = 1; /* R == 1: resource is only used in read-only mode */
+ for (l = tasks.next; l; l = l->next){
+ t = l->i;
+ if (t->state <= EdfExpelled && t != thetask)
+ continue; /* csn belongs to an irrelevant task */
+ for (lc = (CSN*)t->csns.next; lc; lc = (CSN*)lc->next){
+ if (lc->i != r)
+ continue; /* wrong resource */
+ if (lc->R == 0)
+ R = 0; /* Resource is used in exclusive mode */
+ DEBUG("(%T≤%T<%T: %T) ",
+ ticks2time(lc->testDelta), ticks2time(ticks), ticks2time(t->D),
+ ticks2time(lc->C));
+ if (lc->testDelta <= ticks && ticks < t->D && Cbt < lc->C)
+ Cbt = lc->C;
+ }
+ }
+ if (R == 0){
+ DEBUG("%T, ", ticks2time(Cbt));
+ Cb = Cbt;
+ }
+ DEBUG("ro, ");
}
+ DEBUG("Cb = %T\n", ticks2time(Cb));
return Cb;
}
-static Task *qschedulability;
-
static void
testenq(Task *t)
{
@@ 898,7 1003,7 @@ edftestschedulability(Task *thetask)
/* initialize */
testdelta(thetask);
if (thetask && (thetask->flags & Verbose))
- pprint("schedulability test\n");
+ pprint("schedulability test for task %d\n", thetask->taskno);
qschedulability = nil;
for (l = tasks.next; l; l = l->next){
t = l->i;
@@ 908,7 1013,7 @@ edftestschedulability(Task *thetask)
t->testtype = Release;
t->testtime = 0;
if (thetask && (thetask->flags & Verbose))
- pprint("\tInit: enqueue task %lud\n", t->taskno);
+ pprint("\tInit: enqueue task %d\n", t->taskno);
testenq(t);
}
H=0;
@@ 920,24 1025,32 @@ edftestschedulability(Task *thetask)
switch (t->testtype){
case Deadline:
H += t->C;
- Cb = blockcost(ticks, thetask);
+ Cb = blockcost(ticks, t, thetask);
if (thetask && (thetask->flags & Verbose))
- pprint("\tStep %3d, Ticks %T, task %lud, deadline, H += %T → %T, Cb = %T\n",
+ pprint("\tStep %3d, Ticks %T, task %d, deadline, H += %T → %T, Cb = %T\n",
steps, ticks2time(ticks), t->taskno,
ticks2time(t->C), ticks2time(H), ticks2time(Cb));
- if (H+Cb>ticks)
+ if (H+Cb>ticks){
+ if (thetask && (thetask->flags & Verbose))
+ pprint("task %d not schedulable: H=%T + Cb=%T > ticks=%T\n",
+ thetask->taskno, ticks2time(H), ticks2time(Cb), ticks2time(ticks));
return "not schedulable";
+ }
t->testtime += t->T - t->D;
t->testtype = Release;
testenq(t);
break;
case Release:
if (thetask && (thetask->flags & Verbose))
- pprint("\tStep %3d, Ticks %T, task %lud, release, G %T, C%T\n",
+ pprint("\tStep %3d, Ticks %T, task %d, release, G %T, C%T\n",
steps, ticks2time(ticks), t->taskno,
ticks2time(t->C), ticks2time(G));
- if(ticks && G <= ticks)
+ if(ticks && G <= ticks){
+ if (thetask && (thetask->flags & Verbose))
+ pprint("task %d schedulable: G=%T <= ticks=%T\n",
+ thetask->taskno, ticks2time(G), ticks2time(ticks));
return nil;
+ }
G += t->C;
t->testtime += t->D;
t->testtype = Deadline;
@@ 950,32 1063,64 @@ edftestschedulability(Task *thetask)
return "probably not schedulable";
}
-static uvlong
-uvmuldiv(uvlong x, ulong num, ulong den)
+static void
+resacquire(Task *t, CSN *c)
{
- /* multiply, then divide, avoiding overflow */
- uvlong hi;
+ Ticks now, when, used;
- hi = (x & 0xffffffff00000000LL) >> 32;
- x &= 0xffffffffLL;
- hi *= num;
- return (x*num + (hi%den << 32)) / den + (hi/den << 32);
+ now = fastticks(nil);
+ used = now - t->scheduled;
+ t->scheduled = now;
+ t->total += used;
+ t->S -= used;
+ if (t->curcsn)
+ t->curcsn->S -= used;
+ when = now + c->S;
+ if (when < deadlinetimer[m->machno].when){
+ timerdel(&deadlinetimer[m->machno]);
+ deadlinetimer[m->machno].when = when;
+ timeradd(&deadlinetimer[m->machno]);
+ }
+ t->Delta = c->Delta;
+ t->curcsn = c;
+ /* priority is going up, no need to reschedule */
}
-Time
-ticks2time(Ticks ticks)
+static void
+resrelease(Task *t)
{
- assert(ticks >= 0);
- if (fasthz == 0)
- fastticks(&fasthz);
- return uvmuldiv(ticks, Onesecond, fasthz);
-}
+ Ticks now, when, used;
+ CSN *c;
-Ticks
-time2ticks(Time time)
-{
- assert(time >= 0);
- return uvmuldiv(time, fasthz, Onesecond);
+ c = t->curcsn;
+ assert(c);
+ t->curcsn = c->p;
+ now = fastticks(nil);
+ used = now - t->scheduled;
+ t->scheduled = now;
+ t->total += used;
+ t->S -= used;
+ c->S -= used;
+ if (now + t->S > t->d)
+ when = t->d;
+ else
+ when = now + t->S;
+ if (t->curcsn){
+ t->curcsn->S -= c->S; /* the sins of the fathers shall be visited upon the children */
+ t->Delta = t->curcsn->Delta;
+ if (when > now + t->curcsn->S)
+ when = now + t->curcsn->S;
+ }else
+ t->Delta = Infinity;
+ c->S = 0LL; /* don't allow reuse */
+ if (deadlinetimer[m->machno].when)
+ timerdel(&deadlinetimer[m->machno]);
+ deadlinetimer[m->machno].when = when;
+ timeradd(&deadlinetimer[m->machno]);
+
+ qunlock(&edfschedlock);
+ sched(); /* reschedule */
+ qlock(&edfschedlock);
}
Edfinterface realedf = {
@@ 989,4 1134,6 @@ Edfinterface realedf = {
.edfexpel = edfexpel,
.edfadmit = edfadmit,
.edfdeadline = edfdeadline,
+ .resacquire = resacquire,
+ .resrelease = resrelease,
};