From 1e4e061266d9170c137dbb53793c6634d2fdfd3b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 31 Aug 2002 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2002-08-31 --- port/auth.c | 2 +- port/devrealtime.c | 523 +++++++++++++++++++++++++-------------------- port/edf.c | 110 ++++++---- port/edf.h | 40 +++- 4 files changed, 382 insertions(+), 293 deletions(-) diff --git a/port/auth.c b/port/auth.c index 80a90ac487865b76ae1051aa8055557ce685ca39..77c79779dd2b51f82995b8c8efa761b084d6accf 100644 --- a/port/auth.c +++ b/port/auth.c @@ -67,7 +67,7 @@ sysfauth(ulong *arg) validaddr(arg[1], 1, 0); aname = (char*)arg[1]; - validname(aname, 0); + validname(aname, 1); c = fdtochan(arg[0], ORDWR, 0, 1); if(waserror()){ cclose(c); diff --git a/port/devrealtime.c b/port/devrealtime.c index 249406889729e05f6baf7dcfb5a8d9d94596e784..01377e4864a7063f0e55a1a44b19d3e5e026590d 100644 --- a/port/devrealtime.c +++ b/port/devrealtime.c @@ -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; +} diff --git a/port/edf.c b/port/edf.c index d0d6d1c5d794dd6e2486eddf2a3bacb827e10786..950d2c1c4c8637d7c085015a0c4b680bebc3be13 100644 --- a/port/edf.c +++ b/port/edf.c @@ -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; diff --git a/port/edf.h b/port/edf.h index 9013d572385a430b4181e78a784ba6f5b5e2d916..c8f2807f6e3c2ec63b7ca29898b15db3309f08ef 100644 --- a/port/edf.h +++ b/port/edf.h @@ -18,6 +18,8 @@ typedef struct Task Task; typedef struct Resource Resource; typedef struct Edf Edf; typedef struct Taskq Taskq; +typedef struct List List; +typedef struct Head Head; enum Edfstate { EdfUnused, /* task structure not in use */ @@ -35,6 +37,16 @@ enum Edfstate { }; typedef enum Edfstate Edfstate; +struct List { + List * next; /* next in list */ + void * i; /* item in list */ +}; + +struct Head { + List *next; /* First item in list */ + int n; /* number of items in list */ +}; + struct Edf { /* time intervals */ Ticks D; /* Deadline */ @@ -63,13 +75,13 @@ struct Edf { struct Task { QLock; + Ref; /* ref count for farbage collection */ + int taskno; /* task number in Qid */ Edf; Ticks scheduled; Schedq runq; /* Queue of runnable member procs */ - Proc * procs[Nproc]; /* List of member procs; may contain holes */ - int nproc; /* number of them */ - Resource* res[Nres]; /* List of resources; may contain holes */ - int nres; /* number of them */ + Head procs; /* List of member procs */ + Head res; /* List of resources */ char *user; /* mallocated */ Dirtab dir; int flags; /* e.g., Verbose */ @@ -85,18 +97,23 @@ struct Taskq struct Resource { + Ref; char * name; - Task * tasks[Ntask]; /* may contain holes */ - int ntasks; + Head tasks; Ticks Delta; /* for schedulability testing */ Ticks testDelta; }; -extern Lock edftestlock; /* for atomic admitting/expelling */ -extern Task tasks[Maxtasks]; /* may contain holes */ -extern int ntasks; -extern Resource resources[Maxresources]; /* may contain holes */ +struct ResourceItem { + List; /* links and identifies the resource (must be first) */ + Ticks C; /* cost */ + Head h; /* sub resource items */ +}; + +extern QLock edfschedlock; +extern Head tasks; +extern Head resources; extern int nresources; extern Lock edflock; extern Taskq qwaitrelease; @@ -112,3 +129,6 @@ extern char * edfstatename[]; Time ticks2time(Ticks); Ticks time2ticks(Time); +int putlist(Head*, List*); +int enlist(Head*, void*); +int delist(Head*, void*);