@@ 22,6 22,7 @@ static QLock elock;
static Ref logopens;
static Ref debugopens;
static uvlong fasthz;
+static int taskno;
static int timeconv(Fmt *);
static char * parsetime(Time *, char *);
@@ 32,6 33,7 @@ enum {
Qrealtime,
Qclone,
Qdebug,
+ Qdump,
Qlog,
Qnblog,
Qresrc,
@@ 51,6 53,7 @@ Dirtab scheddir[]={
".", {Qrealtime, 0, QTDIR}, 0, DMDIR|0555,
"clone", {Qclone}, 0, 0666,
"debug", {Qdebug}, 0, 0444,
+ "dump", {Qdump}, 0, 0444,
"log", {Qlog}, 0, 0444, /* one open only */
"nblog", {Qnblog}, 0, 0444, /* nonblocking version of log */
"resources", {Qresrc}, 0, 0444,
@@ 70,6 73,18 @@ 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)
{
@@ 122,6 137,42 @@ dumpq(char *p, char *e, Taskq *q, Ticks now)
return nil;
}
+static Task *
+taskinit(void)
+{
+ Dirtab *d;
+ Task *t;
+
+ t = malloc(sizeof(Task));
+ if (t == nil)
+ error("taskinit: malloc");
+ d = &t->dir;
+ if (up->user)
+ kstrdup(&t->user, up->user);
+ else
+ kstrdup(&t->user, eve);
+ t->state = EdfExpelled;
+ t->taskno = ++taskno;
+ snprint(d->name, sizeof d->name, "%d", t->taskno);
+ mkqid(&d->qid, Qistask | t->taskno, 0, QTFILE);
+ d->length = 0;
+ d->perm = 0600;
+ enlist(&tasks, t);
+ incref(t);
+ return t;
+}
+
+void
+taskfree(Task *t)
+{
+ if (decref(t))
+ return;
+ assert(t->procs.n == 0);
+ assert(t->res.n == 0);
+ free(t->user);
+ free(t);
+}
+
/*
* the zeroth element of the table MUST be the directory itself for ..
*/
@@ 133,18 184,28 @@ schedgen(Chan *c, char*, Dirtab *, int, int i, Dir *dp)
char *owner;
ulong taskindex;
Qid qid;
+ Task *t;
+ List *l;
if((ulong)c->qid.path & Qistask){
+ qlock(&edfschedlock);
taskindex = (ulong)c->qid.path & (Qistask-1);
- if (taskindex >= Maxtasks || tasks[taskindex].state == EdfUnused)
+ if ((t = findtask(taskindex)) == nil){
+ qunlock(&edfschedlock);
return -1;
+ }
}else if((ulong)c->qid.path == Qtask){
+ qlock(&edfschedlock);
+
taskindex = i;
- for (i = 0; i < Maxtasks; i++)
- if (tasks[i].state != EdfUnused && taskindex-- == 0)
+ SET(t);
+ for (l = tasks.next; l; l = l->next)
+ if ((t = l->i) && taskindex-- == 0)
break;
- if (i == Maxtasks)
+ if (l == nil){
+ qunlock(&edfschedlock);
return -1;
+ }
}else {
if((ulong)c->qid.path == Qdir){
tab = schedrootdir;
@@ 166,13 227,14 @@ schedgen(Chan *c, char*, Dirtab *, int, int i, Dir *dp)
if(i == DEVDOTDOT){
mkqid(&qid, Qtask, 0, QTDIR);
devdir(c, qid, ".", 0, eve, 0555, dp);
- return 1;
+ }else{
+ owner = t->user;
+ if (owner == nil)
+ owner = eve;
+ tab = &t->dir;
+ devdir(c, tab->qid, tab->name, tab->length, owner, tab->perm, dp);
}
- owner = tasks[i].user;
- if (owner == nil)
- owner = eve;
- tab = &tasks[i].dir;
- devdir(c, tab->qid, tab->name, tab->length, owner, tab->perm, dp);
+ qunlock(&edfschedlock);
return 1;
}
@@ 183,7 245,7 @@ _devrt(Task *t, Ticks t1, SEvent etype)
return;
if(edfprint)iprint("state %s\n", schedstatename[etype]);
- events[wevent].tid = t - tasks;
+ events[wevent].tid = t->taskno;
events[wevent].ts = 0;
if (t1)
events[wevent].ts = ticks2time(t1);
@@ 241,25 303,6 @@ devrtstat(Chan *c, uchar *db, int n)
return devstat(c, db, n, nil, 0, schedgen);
}
-static void
-taskinit(Task *t)
-{
- Dirtab *d;
-
- d = &t->dir;
- memset(t, 0, sizeof(Task));
- if (up->user)
- kstrdup(&t->user, up->user);
- else
- kstrdup(&t->user, eve);
- t->state = EdfExpelled;
- snprint(d->name, sizeof d->name, "%ld", t - tasks);
- mkqid(&d->qid, Qistask | (t - tasks), 0, QTFILE);
- d->length = 0;
- d->perm = 0600;
- ntasks++;
-}
-
static Chan *
devrtopen(Chan *c, int mode)
{
@@ 285,22 328,19 @@ devrtopen(Chan *c, int mode)
error("already open");
}
break;
+ case Qdump:
+ if (mode != OREAD)
+ error(Eperm);
+ break;
case Qclone:
if (mode == OREAD)
error(Eperm);
edf->edfinit();
+ qlock(&edfschedlock);
/* open a new task */
- for (t = tasks; t< tasks + Maxtasks; t++){
- qlock(t);
- if(t->state == EdfUnused){
- taskinit(t);
- c->qid.vers = t - tasks;
- break;
- }
- qunlock(t);
- }
- if (t == tasks + Maxtasks)
- error("too many tasks");
+ t = taskinit();
+ c->qid.vers = t->taskno;
+ qunlock(&edfschedlock);
break;
}
// print("open %lux, mode %o\n", (ulong)c->qid.path, mode);
@@ 337,9 377,11 @@ devrtread(Chan *c, void *v, long n, vlong offs)
long n0;
int navail;
Task *t;
- int s, i, fst;
+ int s, i;
Ticks now;
Time tim;
+ List *l;
+ Resource *r;
n0 = n;
// print("schedread 0x%lux\n", (ulong)c->qid.path);
@@ 403,32 445,45 @@ devrtread(Chan *c, void *v, long n, vlong offs)
qunlock(&elock);
break;
case Qresrc:
+ qlock(&edfschedlock);
+ if(waserror()){
+ qunlock(&edfschedlock);
+ nexterror();
+ }
p = buf;
e = p + sizeof(buf);
- for (i = 0; i < Maxresources; i++){
- if (resources[i].name == nil)
- continue;
- p = seprint(p, e, "name=%s", resources[i].name);
- if (resources[i].ntasks){
+ 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='");
- fst = 0;
- for (s = 0; s < nelem(resources[i].tasks); s++)
- if (resources[i].tasks[s]){
- if (fst)
- p = seprint(p, e, " ");
- p = seprint(p, e, "%ld", resources[i].tasks[s] - tasks);
- fst++;
- }
+ 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 (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));
+ 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");
}
+ qunlock(&edfschedlock);
+ poperror();
return readstr(offs, v, n, buf);
break;
+ case Qdump:
+ p = buf;
+ e = p + sizeof(buf);
+ qlock(&edfschedlock);
+ qunlock(&edfschedlock);
+ p = seprint(p, e, "\n");
+ return readstr(offs, v, n, buf);
case Qdebug:
p = buf;
e = p + sizeof(buf);
@@ 446,7 501,6 @@ devrtread(Chan *c, void *v, long n, vlong offs)
dumpq(p, e, &qextratime, now);
iunlock(&edflock);
return readstr(offs, v, n, buf);
- break;
case Qclone:
s = c->qid.vers;
goto common;
@@ 455,9 509,12 @@ devrtread(Chan *c, void *v, long n, vlong offs)
error(Enonexist);
s = (ulong)c->qid.path & (Qistask - 1);
common:
- if (s < 0 || s >= Maxtasks || tasks[s].state == EdfUnused)
+ qlock(&edfschedlock);
+ t = findtask(s);
+ if (t == nil){
+ qunlock(&edfschedlock);
error(Enonexist);
- t = tasks + s;
+ }
p = buf;
e = p + sizeof(buf);
p = seprint(p, e, "task=%d", s);
@@ 473,28 530,26 @@ 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->nres){
+ if (t->res.n){
p = seprint(p, e, " resources='");
- fst = 0;
- for (i = 0; i < nelem(t->res); i++)
- if (t->res[i]){
- if (fst)
- p = seprint(p, e, " ");
- p = seprint(p, e, "%s", t->res[i]->name);
- fst++;
- }
+ 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 = seprint(p, e, "'");
}
- if (t->nproc){
+ if (t->procs.n){
p = seprint(p, e, " procs='");
- fst = 0;
- for (i = 0; i < nelem(t->procs); i++)
- if (t->procs[i]){
- if (fst)
- p = seprint(p, e, " ");
- p = seprint(p, e, "%lud", t->procs[i]->pid);
- fst++;
- }
+ for (l = t->procs.next; l; l = l->next){
+ Proc *pr = l->i;
+ assert(pr);
+ if (l != t->procs.next)
+ p = seprint(p, e, " ");
+ p = seprint(p, e, "%lud", pr->pid);
+ }
p = seprint(p, e, "'");
}
if (t->periods)
@@ 508,6 563,7 @@ devrtread(Chan *c, void *v, long n, vlong offs)
if (t->aged)
p = seprint(p, e, " c=%T", ticks2time(t->aged));
seprint(p, e, "\n");
+ qunlock(&edfschedlock);
return readstr(offs, v, n, buf);
}
return n0 - n;
@@ 516,134 572,47 @@ devrtread(Chan *c, void *v, long n, vlong offs)
static Resource *
resource(char *name, int add)
{
- Resource *r, *i;
- Task **t;
-
- r = nil;
- for (i = resources; i < resources + nelem(resources); i++){
- if (i->name == nil)
- r = i;
- else if (strcmp(i->name, name) == 0)
- return i;
- }
- if (add == 0)
+ 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("too many resources");
+ error("resource: malloc");
kstrdup(&r->name, name);
- for (t = r->tasks; t < r->tasks + nelem(r->tasks); t++)
- *t = nil;
- r->ntasks = 0;
- nresources++;
+ enlist(&resources, r);
return r;
}
-static char *
-tasktoresource(Resource *r, Task *t, int add)
-{
- Task **et, **rt, **i;
-
- et = nil;
- rt = nil;
- for (i = r->tasks; i < r->tasks + nelem(r->tasks ); i++){
- if (*i == nil)
- et = i;
- else if (*i == t)
- rt = i;
- }
- if (add > 0){
- if (rt)
- return nil; /* resource already present */
- if (et == nil)
- return "too many resources";
- *et = t;
- r->ntasks++;
- }else{
- if (rt == nil)
- return nil; /* resource not found */
- *rt = nil;
- r->ntasks--;
- }
- return nil;
-}
-
-static char *
-resourcetotask(Task *t, Resource *r, int add)
+void
+resourcefree(Resource *r)
{
- Resource **i, **tr, **er;
-
- er = nil;
- tr = nil;
- for (i = t->res; i < t->res + nelem(t->res); i++){
- if (*i == nil)
- er = i;
- else if (*i == r)
- tr = i;
- }
- if (add > 0){
- if (tr)
- return nil; /* resource already present */
- if (er == nil)
- return "too many resources";
- *er = r;
- t->nres++;
- }else{
- if (tr == nil)
- return nil; /* resource not found */
- *tr = nil;
- t->nres--;
- }
- return nil;
-}
-
-static char *
-proctotask(Task *t, Proc *p, int add)
-{
- Proc **i, **tr, **er;
-
- er = nil;
- tr = nil;
- for (i = t->procs; i < t->procs + nelem(t->procs); i++){
- if (*i == nil)
- er = i;
- else if (*i == p)
- tr = i;
- }
- if (add > 0){
- if (tr){
- assert (p->task == t);
- return nil; /* proc already present */
- }
- if (er == nil)
- return "too many resources";
- if (p->task != nil && p->task != t)
- error("proc belongs to another task");
- p->task = t;
- *er = p;
- t->nproc++;
- }else{
- if (tr == nil)
- return nil; /* resource not found */
- assert(p->task == t);
- p->task = nil;
- *tr = nil;
- t->nproc--;
- }
- return nil;
+ if (decref(r))
+ return;
+ delist(&resources, r);
+ assert(r->tasks.n == 0);
+ free(r->name);
+ free(r);
}
static void
removetask(Task *t)
{
- int s, i;
- Proc *p, **pp;
+ Proc *p;
Resource *r;
+ List *l;
- qlock(t);
edf->edfexpel(t);
- for (pp = t->procs; pp < t->procs + nelem(t->procs); pp++)
- if (p = *pp)
- p->task = nil;
+ 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;
@@ 652,27 621,18 @@ removetask(Task *t)
}
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;
+ 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;
- qunlock(t);
+ if (delist(&tasks, t))
+ taskfree(t);
}
static long
@@ 680,8 640,7 @@ devrtwrite(Chan *c, void *va, long n, vlong)
{
char *a, *v, *e, *args[16], *rargs[16], buf[512];
int i, j, s, nargs, nrargs, add;
- Resource **rp, *r;
- Proc **pp;
+ Resource *r;
Task *t;
Ticks ticks;
Time time;
@@ 700,9 659,14 @@ devrtwrite(Chan *c, void *va, long n, vlong)
error(Enonexist);
s = (ulong)c->qid.path & (Qistask - 1);
common:
- if (s < 0 || s >= Maxtasks || tasks[s].state == EdfUnused)
+ qlock(&edfschedlock);
+ if (waserror()){
+ qunlock(&edfschedlock);
+ nexterror();
+ }
+ t = findtask(s);
+ if (t == nil)
error(Enonexist);
- t = tasks + s;
if(n >= sizeof(buf))
n = sizeof(buf)-1;
strncpy(buf, a, n);
@@ 788,22 752,32 @@ devrtwrite(Chan *c, void *va, long n, vlong)
error("resources: value missing");
edf->edfexpel(t);
if (add == 0){
- for (rp = t->res; rp < t->res + nelem(t->res); rp++)
- if (*rp){
- tasktoresource(*rp, t, 0);
- resourcetotask(t, *rp, 0);
- }
- assert(t->nres == 0);
+ List *l;
+
+ while (l = t->res.next) {
+ r = l->i;
+ assert(r);
+ if (delist(&r->tasks, t))
+ taskfree(t);
+ if (delist(&t->res, r))
+ resourcefree(r);
+ }
+ assert(t->res.n == 0);
add = 1;
}
nrargs = tokenize(v, rargs, nelem(rargs));
for (j = 0; j < nrargs; j++)
if (r = resource(rargs[j], add)){
- if (e = tasktoresource(r, t, add))
- error(e);
- if (e = resourcetotask(t, r, add)){
- tasktoresource(r, t, -1);
- error(e);
+ 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");
@@ 814,10 788,14 @@ devrtwrite(Chan *c, void *va, long n, vlong)
edf->edfexpel(t);
}
if (add == 0){
- for (pp = t->procs; pp < t->procs + nelem(t->procs); pp++)
- if (*pp){
- proctotask(t, *pp, -1);
- }
+ List *l;
+
+ while (l = t->procs.next){
+ p = l->i;
+ assert(p->task == t);
+ delist(&t->procs, p);
+ p->task = nil;
+ }
add = 1;
}
nrargs = tokenize(v, rargs, nelem(rargs));
@@ 833,8 811,15 @@ devrtwrite(Chan *c, void *va, long n, vlong)
error("no such process");
p = proctab(s);
}
- if (e = proctotask(t, p, add))
- error(e);
+ if(p->task && p->task != t)
+ error("proc belongs to another task");
+ if (add > 0){
+ enlist(&t->procs, p);
+ p->task = t;
+ }else{
+ delist(&t->procs, p);
+ p->task = nil;
+ }
}
}else if (strcmp(a, "admit") == 0){
if (e = edf->edfadmit(t))
@@ 843,6 828,8 @@ devrtwrite(Chan *c, void *va, long n, vlong)
edf->edfexpel(t);
}else if (strcmp(a, "remove") == 0){
removetask(t);
+ poperror();
+ qunlock(&edfschedlock);
return n; /* Ignore any subsequent commands */
}else if (strcmp(a, "verbose") == 0){
if (t->flags & Verbose)
@@ 861,12 848,16 @@ devrtwrite(Chan *c, void *va, long n, vlong)
}else if (strcmp(a, "yield") == 0){
if (edf->isedf(up) && up->task == t){
edf->edfdeadline(up); /* schedule next release */
+ qunlock(&edfschedlock);
sched();
+ qlock(&edfschedlock);
}else
error("yield outside task");
}else
error("unrecognized command");
}
+ poperror();
+ qunlock(&edfschedlock);
}
return n;
}
@@ 880,10 871,17 @@ devrtremove(Chan *c)
if ((c->qid.path & Qistask) == 0)
error(Eperm);
s = (ulong)c->qid.path & (Qistask - 1);
- t = tasks + s;
- if (s < 0 || s >= Maxtasks || t->state == EdfUnused)
+ t = findtask(s);
+ if (t == nil)
error(Enonexist);
+ qlock(&edfschedlock);
+ if (waserror()){
+ qunlock(&edfschedlock);
+ nexterror();
+ }
removetask(t);
+ poperror();
+ qunlock(&edfschedlock);
}
Dev realtimedevtab = {
@@ 977,3 975,58 @@ parsetime(Time *rt, char *s)
*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;
+}
@@ 32,13 32,12 @@ 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;
Lock edflock;
-Task tasks[Maxtasks];
-int ntasks;
-Resource resources[Maxresources];
-int nresources;
+Head tasks;
+Head resources;
int edfstateupdate;
int misseddeadlines;
@@ 301,6 300,7 @@ edfadmit(Task *t)
{
char *err;
+ /* Called with edfschedlock held */
if (t->state != EdfExpelled)
return "task state"; /* should never happen */
@@ 316,12 316,11 @@ edfadmit(Task *t)
if (t->C > t->D)
return "C > D";
- qlock(&edfschedlock);
if (err = edftestschedulability(t)){
- qunlock(&edfschedlock);
return err;
}
ilock(&edflock);
+ qunlock(&edfschedlock);
DPRINT("%d edfadmit, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
now = fastticks(nil);
@@ 358,7 357,7 @@ edfadmit(Task *t)
}
}
iunlock(&edflock);
- qunlock(&edfschedlock);
+ qlock(&edfschedlock);
return nil;
}
@@ 367,7 366,7 @@ edfexpel(Task *t)
{
Task *tt;
- qlock(&edfschedlock);
+ /* Called with edfschedlock held */
ilock(&edflock);
DPRINT("%d edfexpel, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
now = fastticks(nil);
@@ 376,7 375,6 @@ edfexpel(Task *t)
case EdfExpelled:
/* That was easy */
iunlock(&edflock);
- qunlock(&edfschedlock);
return;
case EdfAdmitted:
case EdfIdle:
@@ 408,7 406,6 @@ edfexpel(Task *t)
if(devrt) devrt(t, now, SExpel);
setdelta();
iunlock(&edflock);
- qunlock(&edfschedlock);
return;
}
@@ 497,7 494,6 @@ static void
edfbury(Proc *p)
{
Task *t;
- Proc **pp;
DPRINT("%d edfbury\n", m->machno);
ilock(&edflock);
@@ 509,16 505,12 @@ edfbury(Proc *p)
return;
}
assert(edfstack[m->machno].head == t);
- for (pp = t->procs; pp < t->procs + nelem(t->procs); pp++)
- if (*pp == p){
- t->nproc--;
- *pp = nil;
- }
+ delist(&t->procs, p);
if (t->runq.head == nil){
edfpop();
t->state = EdfBlocked;
}
- if (t->nproc == 0){
+ if (t->procs.n == 0){
assert(t->runq.head == nil);
t->state = EdfIdle;
}
@@ 564,7 556,7 @@ edfresched(Task *t)
Task *xt;
DPRINT("%d edfresched, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
- if (t->nproc == 0){
+ if (t->procs.n == 0){
/* No member processes */
if (t->state > EdfIdle){
t->state = EdfIdle;
@@ 788,48 780,66 @@ runt:
static void
setdelta(void)
{
- Resource *r, **rr;
- Task **tt, *t;
+ Resource *r;
+ Task *t;
+ List *lr, *lt;
- for (r = resources; r < resources + nelem(resources); r++){
- if (r->name == nil)
- continue;
+ for (lr = resources.next; lr; lr = lr->next){
+ r = lr->i;
+ assert(r);
r->Delta = ~0LL;
- for (tt = r->tasks; tt < r->tasks + nelem(r->tasks); tt++)
- if (*tt && (*tt)->D < r->Delta)
- r->Delta = (*tt)->D;
+ for (lt = r->tasks.next; lt; lt = lt->next){
+ t = lt->i;
+ assert(t);
+ if (t->D < r->Delta)
+ r->Delta = t->D;
+ }
}
- for (t = tasks; t < tasks + nelem(tasks); t++){
+ for (lt = tasks.next; lt ; lt = lt->next){
+ t = lt->i;
+ assert(t);
if (t->state < EdfIdle)
continue;
t->Delta = t->D;
- for (rr = t->res; rr < t->res + nelem(t->res); rr++)
- if (*rr && (*rr)->Delta < t->Delta)
- t->Delta = (*rr)->Delta;
+ for (lr = t->res.next; lr; lr = lr->next){
+ r = lr->i;
+ assert(r);
+ if (r->Delta < t->Delta)
+ t->Delta = r->Delta;
+ }
}
}
static void
testdelta(Task *thetask)
{
- Resource *r, **rr;
- Task **tt, *t;
+ Resource *r;
+ Task *t;
+ List *lr, *lt;
- for (r = resources; r < resources + nelem(resources); r++){
- if (r->name == nil)
- continue;
+ for (lr = resources.next; lr; lr = lr->next){
+ r = lr->i;
+ assert(r);
r->testDelta = ~0ULL;
- for (tt = r->tasks; tt < r->tasks + nelem(r->tasks); tt++)
- if (*tt && (*tt)->D < r->testDelta)
- r->testDelta = (*tt)->D;
+ for (lt = r->tasks.next; lt; lt = lt->next){
+ t = lt->i;
+ assert(t);
+ if (t->D < r->testDelta)
+ r->testDelta = t->D;
+ }
}
- for (t = tasks; t < tasks + nelem(tasks); t++){
+ for (lt = tasks.next; lt ; lt = lt->next){
+ t = lt->i;
+ assert(t);
if (t->state <= EdfExpelled && t != thetask)
continue;
t->testDelta = t->D;
- for (rr = t->res; rr < t->res + nelem(t->res); rr++)
- if (*rr && (*rr)->testDelta < t->testDelta)
- t->testDelta = (*rr)->testDelta;
+ for (lr = t->res.next; lr; lr = lr->next){
+ r = lr->i;
+ assert(r);
+ if (r->testDelta < t->testDelta)
+ t->testDelta = r->testDelta;
+ }
}
}
@@ 838,9 848,12 @@ blockcost(Ticks ticks, Task *thetask)
{
Task *t;
Ticks Cb;
+ List *lt;
Cb = 0;
- for (t = tasks; t < tasks + Maxtasks; t++){
+ 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)
@@ 881,19 894,22 @@ edftestschedulability(Task *thetask)
Task *t;
Ticks H, G, Cb, ticks;
int steps;
+ List *l;
/* initialize */
testdelta(thetask);
if (thetask && (thetask->flags & Verbose))
pprint("schedulability test\n");
qschedulability = nil;
- for (t = tasks; t < tasks + Maxtasks; t++){
+ for (l = tasks.next; l; l = l->next){
+ t = l->i;
+ assert(t);
if (t->state <= EdfExpelled && t != thetask)
continue;
t->testtype = Release;
t->testtime = 0;
if (thetask && (thetask->flags & Verbose))
- pprint("\tInit: enqueue task %lud\n", t - tasks);
+ pprint("\tInit: enqueue task %lud\n", t->taskno);
testenq(t);
}
H=0;
@@ 908,7 924,7 @@ edftestschedulability(Task *thetask)
Cb = blockcost(ticks, thetask);
if (thetask && (thetask->flags & Verbose))
pprint("\tStep %3d, Ticks %T, task %lud, deadline, H += %T → %T, Cb = %T\n",
- steps, ticks2time(ticks), t - tasks,
+ steps, ticks2time(ticks), t->taskno,
ticks2time(t->C), ticks2time(H), ticks2time(Cb));
if (H+Cb>ticks)
return "not schedulable";
@@ 919,7 935,7 @@ edftestschedulability(Task *thetask)
case Release:
if (thetask && (thetask->flags & Verbose))
pprint("\tStep %3d, Ticks %T, task %lud, release, G %T, C%T\n",
- steps, ticks2time(ticks), t - tasks,
+ steps, ticks2time(ticks), t->taskno,
ticks2time(t->C), ticks2time(G));
if(ticks && G <= ticks)
return nil;