From d61471a38e31bc1bfcacf62059a52bbdf5ae5fec Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 16 Mar 2002 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2002-03-16 --- port/devrealtime.c | 880 +++++++++++++++++++++++++++++++++++++++++++++ port/devrealtime.h | 27 ++ port/devsd.c | 221 ++++++------ port/edf.c | 114 +++--- port/edf.h | 3 +- 5 files changed, 1086 insertions(+), 159 deletions(-) create mode 100644 port/devrealtime.c create mode 100644 port/devrealtime.h diff --git a/port/devrealtime.c b/port/devrealtime.c new file mode 100644 index 0000000000000000000000000000000000000000..84cd9b48e8ae9047c2514e2bacad5b9c08cb41ca --- /dev/null +++ b/port/devrealtime.c @@ -0,0 +1,880 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "ureg.h" +#include "../port/error.h" +#include "../port/devrealtime.h" +#include "../port/edf.h" + +#pragma varargck type "T" vlong + +/* debugging */ +extern int edfprint; +extern char tabs[16]; +extern int ind; + +static Schedevent *events; +static int nevents, revent, wevent; +static Rendez eventr; +static QLock elock; +static Ref logopens; +static Ref debugopens; +static uvlong fasthz; + +static int timeconv(Fmt *); +static char * parsetime(Time *, char *); + +enum { + Qistask = 0x10000, + Qdir = 0, + Qrealtime, + Qclone, + Qdebug, + Qlog, + Qnblog, + Qresrc, + Qtask, + Qtime, + + Nevents = 10000, + Clockshift = 17, // Good to about 10GHz clock and max. 5(s) +}; + +Dirtab schedrootdir[]={ + ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, + "realtime", {Qrealtime, 0, QTDIR}, 0, DMDIR|0555, +}; + +Dirtab scheddir[]={ + ".", {Qrealtime, 0, QTDIR}, 0, DMDIR|0555, + "clone", {Qclone}, 0, 0666, + "debug", {Qdebug}, 0, 0444, + "log", {Qlog}, 0, 0444, /* one open only */ + "nblog", {Qnblog}, 0, 0444, /* nonblocking version of log */ + "resources", {Qresrc}, 0, 0444, + "task", {Qtask, 0, QTDIR}, 0, DMDIR|0555, + "time", {Qtime}, 0, 0444, +}; + +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", + edf_statename[t->state], t->D, t->Δ, 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; +} + +/* + * the zeroth element of the table MUST be the directory itself for .. +*/ +int +schedgen(Chan *c, char*, Dirtab *, int, int i, Dir *dp) +{ + Dirtab *tab; + int ntab; + char *owner; + ulong taskindex; + Qid qid; + + if((ulong)c->qid.path & Qistask){ + taskindex = (ulong)c->qid.path & (Qistask-1); + if (taskindex >= Maxtasks || tasks[taskindex].state == EdfUnused) + return -1; + }else if((ulong)c->qid.path == Qtask){ + taskindex = i; + for (i = 0; i < Maxtasks; i++) + if (tasks[i].state != EdfUnused && taskindex-- == 0) + break; + if (i == Maxtasks) + return -1; + }else { + if((ulong)c->qid.path == Qdir){ + tab = schedrootdir; + ntab = nelem(schedrootdir); + }else{ + tab = scheddir; + ntab = nelem(scheddir); + } + if(i != DEVDOTDOT){ + /* skip over the first element, that for . itself */ + i++; + if(i >= ntab) + return -1; + tab += i; + } + devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp); + return 1; + } + if(i == DEVDOTDOT){ + mkqid(&qid, Qtask, 0, QTDIR); + devdir(c, qid, ".", 0, eve, 0555, dp); + return 1; + } + 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); + return 1; +} + +static void +_devrt(Task *t, Ticks t1, SEvent etype) +{ + if (logopens.ref == 0 || nevents == Nevents) + return; + + if(edfprint)iprint("%.*sstate %s\n", ind, tabs, edf_statename[etype]); + events[wevent].tid = t - tasks; + events[wevent].ts = 0; + if (t1) + events[wevent].ts = ticks2time(t1); + else + events[wevent].ts = 0; + events[wevent].etype = etype; + + if (!canqlock(&elock)) + return; + + wevent = (wevent + 1) % Nevents; + if (nevents < Nevents) + nevents++; + else + revent = (revent + 1) % Nevents; + + if(edfprint)iprint("%.*swakesched\n", ind, tabs); + /* To avoid circular wakeup when used in combination with + * EDF scheduling. + */ + if (eventr.p && eventr.p->state == Wakeme) + wakeup(&eventr); + + qunlock(&elock); +} + +static void +devrtinit(void) +{ + fmtinstall('T', timeconv); + fmtinstall('U', timeconv); + fastticks(&fasthz); + devrt = _devrt; + events = (Schedevent *)malloc(sizeof(Schedevent) * Nevents); + assert(events); + nevents = revent = wevent = 0; +} + +static Chan * +devrtattach(char *param) +{ + return devattach(L'⌛', param); +} + +static Walkqid * +devrtwalk(Chan *c, Chan *nc, char **name, int nname) +{ + return devwalk(c, nc, name, nname, nil, 0, schedgen); +} + +static int +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) +{ + Task *t; + + switch ((ulong)c->qid.path){ + case Qlog: + case Qnblog: + if (mode != OREAD) + error(Eperm); + incref(&logopens); + if (logopens.ref > 1){ + decref(&logopens); + error("already open"); + } + break; + case Qdebug: + if (mode != OREAD) + error(Eperm); + incref(&debugopens); + if (debugopens.ref > 1){ + decref(&debugopens); + error("already open"); + } + break; + case Qclone: + if (mode == OREAD) + error(Eperm); + edf_init(); + /* 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"); + break; + } +// print("open %lux, mode %o\n", (ulong)c->qid.path, mode); + return devopen(c, mode, nil, 0, schedgen); +} + +static void +devrtclose(Chan *c) +{ + switch ((ulong)c->qid.path){ + case Qlog: + case Qnblog: + nevents = revent = wevent = 0; + decref(&logopens); + break; + case Qdebug: + nevents = revent = wevent = 0; + decref(&debugopens); + break; + } +} + +static int +eventsavailable(void *) +{ + return nevents > 0; +} + +static long +devrtread(Chan *c, void *v, long n, vlong offs) +{ + char *p, *e; + char buf[1024]; + long n0; + int navail; + Task *t; + int s, i, fst; + Ticks now; + + n0 = n; +// print("schedread 0x%lux\n", (ulong)c->qid.path); + buf[0] = '\0'; + switch((ulong)c->qid.path){ + case Qdir: + return devdirread(c, v, n, schedrootdir, nelem(schedrootdir), devgen); + + case Qrealtime: + return devdirread(c, v, n, scheddir, nelem(scheddir), devgen); + + case Qtask: + return devdirread(c, v, n, nil, 0, schedgen); + + case Qtime: + if (n < sizeof(Ticks)) + error(Ebadarg); + now = fastticks(nil); + memmove(v, &now, sizeof(Ticks)); + n -= sizeof(Ticks); + if (n >= sizeof(Ticks)){ + memmove((char*)v + sizeof(Time), &fasthz, sizeof(Ticks)); + n -= sizeof(Ticks); + } + break; + + case Qnblog: + if (eventsavailable(nil)) + goto getevnt; + break; + + case Qlog: + + while (!eventsavailable(nil)) + sleep(&eventr, eventsavailable, nil); + getevnt: + + p = (char *)v; + + navail = nevents; + if (navail > n / sizeof(Schedevent)) + navail = n / sizeof(Schedevent); + n -= navail * sizeof(Schedevent); + + qlock(&elock); + while (navail > 0) { + int ncopy; + + ncopy = (revent + navail > Nevents)? Nevents - revent: navail; + memmove(p, &events[revent], ncopy * sizeof(Schedevent)); + revent = (revent+ ncopy) % Nevents; + p += ncopy * sizeof(Schedevent); + navail -= ncopy; + nevents -= ncopy; + } + qunlock(&elock); + break; + case Qresrc: + 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){ + 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++; + } + 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Δ)); + p = seprint(p, e, "\n"); + } + return readstr(offs, v, n, buf); + break; + case Qdebug: + p = buf; + e = p + sizeof(buf); + ilock(&edflock); + now = fastticks(nil); + for (i = 0; i < conf.nmach; i++){ + p = seprint(p, e, "edfstack[%d]\n", i); + p = dumpq(p, e, edfstack + i, now); + } + p = seprint(p, e, "qreleased\n"); + p = dumpq(p, e, &qreleased, now); + p = seprint(p, e, "qwaitrelease\n"); + p = dumpq(p, e, &qwaitrelease, now); + p = seprint(p, e, "qextratime\n"); + dumpq(p, e, &qextratime, now); + iunlock(&edflock); + return readstr(offs, v, n, buf); + break; + case Qclone: + s = c->qid.vers; + goto common; + default: + if ((c->qid.path & Qistask) == 0) + error(Enonexist); + s = (ulong)c->qid.path & (Qistask - 1); + common: + if (s < 0 || s >= Maxtasks || tasks[s].state == EdfUnused) + error(Enonexist); + t = tasks + s; + p = buf; + e = p + sizeof(buf); + p = seprint(p, e, "task=%d", s); + p = seprint(p, e, " state=%s", edf_statename[t->state]); + if (t->T) + p = seprint(p, e, " T=%T", ticks2time(t->T)); + if (t->D) + 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->nres){ + 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++; + } + p = seprint(p, e, "'"); + } + if (t->nproc){ + 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++; + } + p = seprint(p, e, "'"); + } + seprint(p, e, "\n"); + return readstr(offs, v, n, buf); + } + return n0 - n; +} + +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) + return nil; + if (r == nil) + error("too many resources"); + kstrdup(&r->name, name); + for (t = r->tasks; t < r->tasks + nelem(r->tasks); t++) + *t = nil; + r->ntasks = 0; + nresources++; + 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) +{ + 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; +} + +static long +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; + Task *t; + Time time; + long pid; + Proc *p; + + a = va; + if (c->mode == OREAD) + error(Eperm); + switch((ulong)c->qid.path){ + case Qclone: + s = c->qid.vers; + goto common; + default: + if ((c->qid.path & Qistask) == 0) + error(Enonexist); + s = (ulong)c->qid.path & (Qistask - 1); + common: + if (s < 0 || s >= Maxtasks || tasks[s].state == EdfUnused) + error(Enonexist); + t = tasks + s; + if(n >= sizeof(buf)) + n = sizeof(buf)-1; + strncpy(buf, a, n); + buf[n] = 0; + nargs = tokenize(buf, args, nelem(args)); + for (i = 0; i < nargs; i++){ + a = args[i]; + add = 0; + if (v = strchr(a, '=')){ + if (v != a && v[-1] == '+'){ + add = 1; + v[-1] = '\0'; + } else if (v != a && v[-1] == '-'){ + add = -1; + v[-1] = '\0'; + } + *v++ = '\0'; + } + if (strcmp(a, "T") == 0){ + if (e=parsetime(&time, v)) + error(e); + edf_expel(t); + t->T = time2ticks(time); + }else if (strcmp(a, "D") == 0){ + if (e=parsetime(&time, v)) + error(e); + edf_expel(t); + t->D = time2ticks(time); + }else if (strcmp(a, "C") == 0){ + if (e=parsetime(&time, v)) + error(e); + edf_expel(t); + t->C = time2ticks(time); + }else if (strcmp(a, "resources") == 0){ + if (v == nil) + error("resources: value missing"); + edf_expel(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); + 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); + } + }else + error("resource not found"); + }else if (strcmp(a, "procs") == 0){ + if (v == nil) + error("procs: value missing"); + if (add <= 0) + edf_expel(t); + if (add == 0){ + for (pp = t->procs; pp < t->procs + nelem(t->procs); pp++) + if (*pp) + proctotask(t, *pp, -1); + add = 1; + } + 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 (e = proctotask(t, p, add)) + error(e); + } + }else if (strcmp(a, "admit") == 0){ + /* Do the admission test */ + if (e = edf_admit(t)) + error(e); + }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) + t->flags &= ~Useblocking; + else + t->flags |= Useblocking; + }else if (strcmp(a, "yield") == 0){ + if (isedf(up) && up->task == t){ + edf_deadline(up); /* schedule next release */ + sched(); + }else + error("yield outside task"); + }else + error("unrecognized command"); + } + } + return n; +} + +static void +devrtremove(Chan *c) +{ + int s, i; + Task *t; + Proc *p, **pp; + Resource *r; + + 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) + 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); +} + +Dev realtimedevtab = { + L'⌛', + "scheduler", + + devreset, + devrtinit, + devshutdown, + devrtattach, + devrtwalk, + devrtstat, + devrtopen, + devcreate, + devrtclose, + devrtread, + devbread, + devrtwrite, + devbwrite, + 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 == '\0' || 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; +} diff --git a/port/devrealtime.h b/port/devrealtime.h new file mode 100644 index 0000000000000000000000000000000000000000..4691185788cf7c5c67e1261d21936d7bf8d4a0a9 --- /dev/null +++ b/port/devrealtime.h @@ -0,0 +1,27 @@ +#define Onemicrosecond ((Time)1000ULL) +#define Onemillisecond ((Time)1000*Onemicrosecond) +#define Onesecond ((Time)1000*Onemillisecond) + +typedef vlong Time; +typedef struct Schedevent Schedevent; + +enum SEvent { + SAdmit, /* new proc arrives*/ + SRelease, /* released, but not yet scheduled (on qreleased) */ + SRun, /* one of this task's procs started running */ + SPreempt, /* the running proc was preempted */ + SBlock, /* none of the procs are runnable as a result of sleeping */ + SResume, /* one or more procs became runnable */ + SDeadline, /* proc's deadline */ + SYield, /* proc reached voluntary early deadline */ + SSlice, /* slice exhausted */ + SExpel, /* proc is gone */ +}; +typedef enum SEvent SEvent; + +struct Schedevent { + ulong tid; // Task ID + Time ts; // Event time + SEvent etype; // Event type +}; + diff --git a/port/devsd.c b/port/devsd.c index 3c6419f3e66386c97b032e658b59859aba6e260e..3681d5612d6f49766908faedd8c30b58bcd7cbff 100644 --- a/port/devsd.c +++ b/port/devsd.c @@ -16,13 +16,13 @@ extern Dev sddevtab; extern SDifc* sdifc[]; typedef struct { - SDev *dt_dev; - int dt_nunits; /* num units in dev */ + SDev* dt_dev; + int dt_nunits; /* num units in dev */ } dev_t; -static dev_t *devs; /* all devices */ -static QLock devslock; /* insertion and removal of devices */ -static int ndevs; /* total number of devices in the system */ +static dev_t* devs; /* all devices */ +static QLock devslock; /* insertion and removal of devices */ +static int ndevs; /* total number of devices in the system */ enum { Rawcmd, @@ -68,7 +68,7 @@ enum { #define TYPE(q) ((((ulong)(q).path)>>TypeSHIFT) & TypeMASK) #define PART(q) ((((ulong)(q).path)>>PartSHIFT) & PartMASK) #define UNIT(q) ((((ulong)(q).path)>>UnitSHIFT) & UnitMASK) -#define DEV(q) ((((ulong)(q).path)>>DevSHIFT) & DevMASK) +#define DEV(q) ((((ulong)(q).path)>>DevSHIFT) & DevMASK) #define QID(d,u, p, t) (((d)<idno == idno) break; - if (i == ndevs) + if(i == ndevs) sdev = nil; - else { + else{ sdev = devs[i].dt_dev; incref(&sdev->r); } @@ -255,7 +255,7 @@ sdgetunit(SDev* sdev, int subno) * successfully accessed. */ qlock(&sdev->unitlock); - if (subno > sdev->nunit) { + if(subno > sdev->nunit){ qunlock(&sdev->unitlock); return nil; } @@ -323,14 +323,14 @@ sdreset(void) tail->next = sdev; else sdlist = sdev; - for(tail = sdev; tail->next != nil; tail = tail->next) { - tail->unit = (SDunit **)malloc(tail->nunit * sizeof(SDunit *)); - tail->unitflg = (int *)malloc(tail->nunit * sizeof(int)); + for(tail = sdev; tail->next != nil; tail = tail->next){ + tail->unit = (SDunit**)malloc(tail->nunit * sizeof(SDunit*)); + tail->unitflg = (int*)malloc(tail->nunit * sizeof(int)); assert(tail->unit && tail->unitflg); ndevs++; } - tail->unit = (SDunit **)malloc(tail->nunit * sizeof(SDunit *)); - tail->unitflg = (int *)malloc(tail->nunit * sizeof(int)); + tail->unit = (SDunit**)malloc(tail->nunit * sizeof(SDunit*)); + tail->unitflg = (int*)malloc(tail->nunit * sizeof(int)); ndevs++; } @@ -359,10 +359,10 @@ sdreset(void) * The IDs have been set, unlink the sdlist and copy the spec to * the devtab. */ - devs = (dev_t *)malloc(ndevs * sizeof(dev_t)); + devs = (dev_t*)malloc(ndevs * sizeof(dev_t)); memset(devs, 0, ndevs * sizeof(dev_t)); i = 0; - while (sdlist != nil) { + while(sdlist != nil){ devs[i].dt_dev = sdlist; devs[i].dt_nunits = sdlist->nunit; sdlist = sdlist->next; @@ -457,7 +457,7 @@ sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp) SDev *sdev; switch(TYPE(c->qid)){ - case Qtopdir: { + case Qtopdir: if(s == DEVDOTDOT){ mkqid(&q, QID(0, s, 0, Qtopdir), 0, QTDIR); sprint(up->genbuf, "#%C", sddevtab.dc); @@ -465,24 +465,24 @@ sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp) return 1; } - if (s == 0 || s == 1) + if(s == 0 || s == 1) return sd1gen(c, s + Qtopbase, dp); s -= 2; qlock(&devslock); - for (i = 0; i != ndevs; i++) { + for(i = 0; i != ndevs; i++){ if (s < devs[i].dt_nunits) break; s -= devs[i].dt_nunits; } - if (i == ndevs) { + if(i == ndevs){ /* Run of the end of the list */ qunlock(&devslock); return -1; } - if ((sdev = devs[i].dt_dev) == nil) { + if ((sdev = devs[i].dt_dev) == nil){ qunlock(&devslock); return 0; } @@ -491,7 +491,7 @@ sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp) qunlock(&devslock); if((unit = sdev->unit[s]) == nil) - if((unit = sdgetunit(sdev, s)) == nil) { + if((unit = sdgetunit(sdev, s)) == nil){ decref(&sdev->r); return 0; } @@ -502,7 +502,6 @@ sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp) devdir(c, q, unit->name, 0, unit->user, unit->perm, dp); decref(&sdev->r); return 1; - } case Qunitdir: if(s == DEVDOTDOT){ @@ -512,7 +511,7 @@ sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp) return 1; } - if ((sdev = sdgetdev(DEV(c->qid))) == nil) { + if((sdev = sdgetdev(DEV(c->qid))) == nil){ devdir(c, q, "unavailable", 0, eve, 0, dp); return 1; } @@ -562,7 +561,7 @@ sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp) case Qraw: case Qctl: case Qpart: - if ((sdev = sdgetdev(DEV(c->qid))) == nil) { + if((sdev = sdgetdev(DEV(c->qid))) == nil){ devdir(c, q, "unavailable", 0, eve, 0, dp); return 1; } @@ -608,7 +607,7 @@ sdattach(char* spec) if ((sdev = devs[i].dt_dev) != nil && sdev->idno == idno) break; - if (i == ndevs || subno >= sdev->nunit || sdgetunit(sdev, subno) == nil) { + if(i == ndevs || subno >= sdev->nunit || sdgetunit(sdev, subno) == nil){ qunlock(&devslock); error(Enonexist); } @@ -643,11 +642,11 @@ sdopen(Chan* c, int omode) uchar tp; c = devopen(c, omode, 0, 0, sdgen); - if ((tp = TYPE(c->qid)) != Qctl && tp != Qraw && tp != Qpart) + if((tp = TYPE(c->qid)) != Qctl && tp != Qraw && tp != Qpart) return c; sdev = sdgetdev(DEV(c->qid)); - if (sdev == nil) + if(sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; @@ -717,10 +716,10 @@ sdbio(Chan* c, int write, char* a, long len, vlong off) ulong bno, max, nb, offset; sdev = sdgetdev(DEV(c->qid)); - if (sdev == nil) + if(sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; - if (unit == nil) + if(unit == nil) error(Enonexist); nchange = 0; @@ -804,7 +803,7 @@ sdbio(Chan* c, int write, char* a, long len, vlong off) else if(len > l - offset) len = l - offset; } - else { + else{ l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno); if(l < 0) error(Eio); @@ -885,10 +884,10 @@ sdread(Chan *c, void *a, long n, vlong off) assert(p); e = p + READSTR; qlock(&devslock); - for (i = 0; i != ndevs; i++) { + for(i = 0; i != ndevs; i++){ SDev *sdev = devs[i].dt_dev; - if (sdev->ifc->stat) + if(sdev->ifc->stat) p = sdev->ifc->stat(sdev, p, e); else p = seprint(e, "%s; no statistics available\n", sdev->name); @@ -978,37 +977,37 @@ sdread(Chan *c, void *a, long n, vlong off) } typedef struct { - int o_on; - char *o_spec; + int o_on; + char* o_spec; DevConf o_cf; } confdata_t; static void -parse_switch(confdata_t *cd, char *option) +parse_switch(confdata_t* cd, char* option) { - if (!strcmp("on", option)) + if(!strcmp("on", option)) cd->o_on = 1; - else if (!strcmp("off", option)) + else if(!strcmp("off", option)) cd->o_on = 0; else error(Ebadarg); } static void -parse_spec(confdata_t *cd, char *option) +parse_spec(confdata_t* cd, char* option) { - if (strlen(option) > 1) + if(strlen(option) > 1) error(Ebadarg); cd->o_spec = option; } -static port_t * -getnewport(DevConf *dc) +static port_t* +getnewport(DevConf* dc) { port_t *p; p = (port_t *)malloc((dc->nports + 1) * sizeof(port_t)); - if (dc->nports > 0) { + if(dc->nports > 0){ memmove(p, dc->ports, dc->nports * sizeof(port_t)); free(dc->ports); } @@ -1020,62 +1019,65 @@ getnewport(DevConf *dc) } static void -parse_port(confdata_t *cd, char *option) +parse_port(confdata_t* cd, char* option) { char *e; port_t *p; - - p = (cd->o_cf.nports == 0 || - cd->o_cf.ports[cd->o_cf.nports -1].port != (ulong)-1)? - getnewport(&cd->o_cf): &cd->o_cf.ports[cd->o_cf.nports - 1]; + + if(cd->o_cf.nports == 0 || cd->o_cf.ports[cd->o_cf.nports-1].port != (ulong)-1) + p = getnewport(&cd->o_cf); + else + p = &cd->o_cf.ports[cd->o_cf.nports-1]; p->port = strtol(option, &e, 0); - if (e == nil || *e != '\0') + if(e == nil || *e != '\0') error(Ebadarg); } static void -parse_size(confdata_t *cd, char *option) +parse_size(confdata_t* cd, char* option) { char *e; port_t *p; - p = (cd->o_cf.nports == 0 || cd->o_cf.ports[cd->o_cf.nports -1].size != -1)? - getnewport(&cd->o_cf): &cd->o_cf.ports[cd->o_cf.nports - 1]; - p->size = (int)strtol(option, &e, 0); - if (e == nil || *e != '\0') + if(cd->o_cf.nports == 0 || cd->o_cf.ports[cd->o_cf.nports-1].size != -1) + p = getnewport(&cd->o_cf); + else + p = &cd->o_cf.ports[cd->o_cf.nports-1]; + p->size = (int)strtol(option, &e, 0); + if(e == nil || *e != '\0') error(Ebadarg); } static void -parse_irq(confdata_t *cd, char *option) +parse_irq(confdata_t* cd, char* option) { char *e; cd->o_cf.interrupt = strtoul(option, &e, 0); - if (e == nil || *e != '\0') + if(e == nil || *e != '\0') error(Ebadarg); } static void -parse_type(confdata_t *cd, char *option) +parse_type(confdata_t* cd, char* option) { cd->o_cf.type = option; } static struct { - char *option; - void (*parse)(confdata_t *, char *); + char *option; + void (*parse)(confdata_t*, char*); } options[] = { - { "switch", parse_switch, }, + { "switch", parse_switch, }, { "spec", parse_spec, }, { "port", parse_port, }, { "size", parse_size, }, - { "irq", parse_irq, }, + { "irq", parse_irq, }, { "type", parse_type, }, }; static long -sdwrite(Chan *c, void *a, long n, vlong off) +sdwrite(Chan* c, void* a, long n, vlong off) { Cmdbuf *cb; SDreq *req; @@ -1101,33 +1103,33 @@ sdwrite(Chan *c, void *a, long n, vlong off) memset(&cd.o_cf, 0, sizeof(DevConf)); nf = tokenize(buf, field, Ncmd); - for (i = 0; i < nf; i++) { + for(i = 0; i < nf; i++){ char *opt = field[i++]; - if (i >= nf) + if(i >= nf) error(Ebadarg); - for (j = 0; j != nelem(options); j++) - if (!strcmp(opt, options[j].option)) + for(j = 0; j != nelem(options); j++) + if(!strcmp(opt, options[j].option)) break; - if (j == nelem(options)) + if(j == nelem(options)) error(Ebadarg); options[j].parse(&cd, field[i]); } - if (cd.o_on < 0) + if(cd.o_on < 0) error(Ebadarg); - if (cd.o_on) { - if (cd.o_spec == '\0' || cd.o_cf.nports == 0 || + if(cd.o_on){ + if(cd.o_spec == '\0' || cd.o_cf.nports == 0 || cd.o_cf.interrupt == 0 || cd.o_cf.type == nil) error(Ebadarg); } - else { - if (cd.o_spec == '\0') + else{ + if(cd.o_spec == '\0') error(Ebadarg); } - if (sddevtab.config == nil) + if(sddevtab.config == nil) error("No configuration function"); sddevtab.config(cd.o_on, cd.o_spec, &cd.o_cf); break; @@ -1177,7 +1179,7 @@ sdwrite(Chan *c, void *a, long n, vlong off) case Qraw: sdev = sdgetdev(DEV(c->qid)); - if (sdev == nil) + if(sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; qlock(&unit->raw); @@ -1291,15 +1293,15 @@ sdwstat(Chan* c, uchar* dp, int n) static char getspec(char base) { - while (1) { + while(1){ int i; SDev *sdev; - for (i = 0; i != ndevs; i++) - if ((sdev = devs[i].dt_dev) != nil && (char)sdev->idno == base) + for(i = 0; i != ndevs; i++) + if((sdev = devs[i].dt_dev) != nil && (char)sdev->idno == base) break; - if (i == ndevs) + if(i == ndevs) return base; base++; } @@ -1307,73 +1309,73 @@ getspec(char base) } static int -configure(char *spec, DevConf *cf) +configure(char* spec, DevConf* cf) { ISAConf isa; dev_t *_devs; - SDev *tail, *sdev, *(*probe)(DevConf *); + SDev *tail, *sdev, *(*probe)(DevConf*); char *p, name[32]; int i, added_devs; - if ((p = strchr(cf->type, '/')) != nil) + if((p = strchr(cf->type, '/')) != nil) *p++ = '\0'; for(i = 0; sdifc[i] != nil; i++) if(!strcmp(sdifc[i]->name, cf->type)) break; - if (sdifc[i] == nil) + if(sdifc[i] == nil) error("type not found"); - if ((probe = sdifc[i]->probe) == nil) + if((probe = sdifc[i]->probe) == nil) error("No probe function"); - if (p) { + if(p){ /* Try to find the card on the ISA bus. This code really belongs in sdata and I'll move it later. Really! */ memset(&isa, 0, sizeof(isa)); isa.port = cf->ports[0].port; isa.irq = cf->interrupt; - if (pcmspecial(p, &isa) < 0) + if(pcmspecial(p, &isa) < 0) error("Cannot find controller"); } qlock(&devslock); - if (waserror()) { + if(waserror()){ qunlock(&devslock); nexterror(); } - for (i = 0; i != ndevs; i++) - if ((sdev = devs[i].dt_dev) != nil && sdev->idno == *spec) + for(i = 0; i != ndevs; i++) + if((sdev = devs[i].dt_dev) != nil && sdev->idno == *spec) break; - if (i != ndevs) + if(i != ndevs) error(Eexist); - if ((sdev = (*probe)(cf)) == nil) + if((sdev = (*probe)(cf)) == nil) error("Cannot probe controller"); poperror(); added_devs = 0; tail = sdev; - while (tail) { + while(tail){ added_devs++; tail = tail->next; } - _devs = (dev_t *)malloc((ndevs + added_devs) * sizeof(dev_t)); + _devs = (dev_t*)malloc((ndevs + added_devs) * sizeof(dev_t)); memmove(_devs, devs, ndevs * sizeof(dev_t)); free(devs); devs = _devs; - while (sdev) { + while(sdev){ /* Assign `spec' to the device */ *spec = getspec(*spec); snprint(name, sizeof(name), "sd%c", *spec); kstrdup(&sdev->name, name); sdev->idno = *spec; - sdev->unit = (SDunit **)malloc(sdev->nunit * sizeof(SDunit *)); + sdev->unit = (SDunit **)malloc(sdev->nunit * sizeof(SDunit*)); sdev->unitflg = (int *)malloc(sdev->nunit * sizeof(int)); assert(sdev->unit && sdev->unitflg); @@ -1389,29 +1391,30 @@ configure(char *spec, DevConf *cf) } static int -unconfigure(char *spec) +unconfigure(char* spec) { int i; SDev *sdev; qlock(&devslock); - if (waserror()) { + if(waserror()){ qunlock(&devslock); nexterror(); } - for (sdev = nil, i = 0; i != ndevs; i++) - if ((sdev = devs[i].dt_dev) != nil && sdev->idno == *spec) + sdev = nil; + for(i = 0; i != ndevs; i++) + if((sdev = devs[i].dt_dev) != nil && sdev->idno == *spec) break; - if (i == ndevs) + if(i == ndevs) error(Enonexist); - if (sdev->r.ref) + if(sdev->r.ref) error(Einuse); /* make sure no interrupts arrive anymore before removing resources */ - if (sdev->enabled && sdev->ifc->disable) + if(sdev->enabled && sdev->ifc->disable) sdev->ifc->disable(sdev); /* we're alone and the device tab is locked; make the device unavailable */ @@ -1422,8 +1425,8 @@ unconfigure(char *spec) qunlock(&devslock); poperror(); - for (i = 0; i != sdev->nunit; i++) - if (sdev->unit[i]) { + for(i = 0; i != sdev->nunit; i++) + if(sdev->unit[i]){ SDunit *unit = sdev->unit[i]; free(unit->name); @@ -1431,15 +1434,17 @@ unconfigure(char *spec) free(unit); } - if (sdev->ifc->clear) + if(sdev->ifc->clear) sdev->ifc->clear(sdev); return 0; } static int -sdconfig(int on, char *spec, DevConf *cf) +sdconfig(int on, char* spec, DevConf* cf) { - return on? configure(spec, cf): unconfigure(spec); + if(on) + return configure(spec, cf); + return unconfigure(spec); } Dev sddevtab = { diff --git a/port/edf.c b/port/edf.c index 1e146d30791e4ba5924000f8de5c02ab6bad08c7..56ea4fd41912da268cbaaffe24979ac70c03be56 100644 --- a/port/edf.c +++ b/port/edf.c @@ -5,7 +5,7 @@ #include "dat.h" #include "fns.h" #include "../port/error.h" -#include "../port/devsched.h" +#include "../port/devrealtime.h" #include "../port/edf.h" /* debugging */ @@ -68,7 +68,7 @@ Taskq qadmit; /* Running/Preempted EDF tasks, head running, one stack per processor */ Taskq edfstack[MAXMACH]; -void (*devsched)(Task*, Ticks, int); +void (*devrt)(Task*, Ticks, int); static void edf_intr(Ureg*, Cycintr*); static void edf_resched(Task *t); @@ -115,16 +115,16 @@ edfpush(Task *t) { Taskq *q; - DENTER("%.*sedfpush, %s, %d\n", ind, tabs, edf_statename[t->state], t->runq.n); + DENTER("%.*s%d edfpush, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n); q = edfstack + m->machno; assert(t->runq.n || (up && up->task == t)); if (q->head){ assert(q->head->state == EdfRunning); q->head->state = EdfPreempted; - if(devsched) devsched(q->head, now, SPreempt); + if(devrt) devrt(q->head, now, SPreempt); } t->rnext = q->head; - if(devsched) devsched(t, now, SRun); + if(devrt) devrt(t, now, SRun); q->head = t; DLEAVE; } @@ -135,7 +135,7 @@ edfpop(void) Task *t; Taskq *q; - DENTER("%.*sedfpop\n", ind, tabs); + DENTER("%.*s%d edfpop\n", ind, tabs, m->machno); q = edfstack + m->machno; if (t = q->head){ assert(t->state == EdfRunning); @@ -144,7 +144,7 @@ edfpop(void) if (q->head){ assert(q->head->state == EdfPreempted); q->head->state = EdfRunning; - if(devsched) devsched(q->head, now, SRun); + if(devrt) devrt(q->head, now, SRun); } } DLEAVE; @@ -157,7 +157,7 @@ edfenqueue(Taskq *q, Task *t) Task *tt, **ttp; ilock(q); - DENTER("%.*sedfenqueue, %s, %d\n", ind, tabs, edf_statename[t->state], t->runq.n); + DENTER("%.*s%d edfenqueue, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n); t->rnext = nil; if (q->head == nil) { q->head = t; @@ -188,7 +188,7 @@ edfdequeue(Taskq *q) { Task *t; - DENTER("%.*sedfdequeue\n", ind, tabs); + DENTER("%.*s%d edfdequeue\n", ind, tabs, m->machno); ilock(q); if (t = q->head){ q->head = t->rnext; @@ -205,7 +205,7 @@ edfqremove(Taskq *q, Task *t) Task **tp; ilock(q); - DENTER("%.*sedfqremove, %s, %d\n", ind, tabs, edf_statename[t->state], t->runq.n); + DENTER("%.*s%d edfqremove, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n); for (tp = &q->head; *tp; tp = &(*tp)->rnext){ if (*tp == t){ *tp = t->rnext; @@ -226,7 +226,7 @@ edf_block(Proc *p) /* The current proc has blocked */ ilock(&edflock); t = p->task; - DENTER("%.*sedf_block, %s, %d\n", ind, tabs, edf_statename[t->state], t->runq.n); + 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); @@ -239,7 +239,7 @@ edf_block(Proc *p) pt = edfpop(); assert(pt == t); t->state = EdfBlocked; - if(devsched) devsched(t, now, SBlock); + if(devrt) devrt(t, now, SBlock); DLEAVE; iunlock(&edflock); } @@ -250,7 +250,7 @@ edfdeadline(Proc *p, SEvent why) Task *t, *nt; /* Task has reached its deadline, lock must be held */ - DENTER("%.*sedfdeadline, %s, %d\n", ind, tabs, edf_statename[p->task->state], p->task->runq.n); + DENTER("%.*s%d edfdeadline, %s, %d\n", ind, tabs, m->machno, edf_statename[p->task->state], p->task->runq.n); SET(nt); if (p){ nt = p->task; @@ -260,14 +260,14 @@ edfdeadline(Proc *p, SEvent why) t = edfpop(); if(p != nil && nt != t){ - DPRINT("%.*sedfdeadline, %s, %d\n", ind, tabs, edf_statename[p->task->state], p->task->runq.n); + DPRINT("%.*s%d edfdeadline, %s, %d\n", ind, tabs, m->machno, edf_statename[p->task->state], p->task->runq.n); iunlock(&edflock); assert(0 && p == nil || nt == t); } t->d = now; t->state = EdfDeadline; - if(devsched) devsched(t, now, why); + if(devrt) devrt(t, now, why); edf_resched(t); DLEAVE; } @@ -275,7 +275,7 @@ edfdeadline(Proc *p, SEvent why) void edf_deadline(Proc *p) { - DENTER("%.*sedf_deadline\n", ind, tabs); + DENTER("%.*s%d edf_deadline\n", ind, tabs, m->machno); /* Task has reached its deadline */ ilock(&edflock); now = fastticks(nil); @@ -291,27 +291,41 @@ edf_admit(Task *t) if (t->state != EdfExpelled) return "task state"; /* should never happen */ + + /* simple sanity checks */ + if (t->T == 0) + return "T not set"; + if (t->C == 0) + return "C not set"; + if (t->D > t->T) + return "D > T"; + if (t->D == 0) /* if D is not set, set it to T */ + t->D = t->T; + if (t->C > t->D) + return "C > D"; + qlock(&edfschedlock); if (err = edf_testschedulability(t)){ qunlock(&edfschedlock); return err; } ilock(&edflock); - DENTER("%.*sedf_admit, %s, %d\n", ind, tabs, edf_statename[t->state], t->runq.n); + DENTER("%.*s%d edf_admit, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n); now = fastticks(nil); t->state = EdfAdmitted; + if(devrt) devrt(t, t->d, SAdmit); if (up->task == t){ - DPRINT("%.*sedf_admitting self\n", ind, tabs); + DPRINT("%.*s%d edf_admitting self\n", ind, tabs, m->machno); /* Admitting self, fake reaching deadline */ t->r = now; t->t = now + t->T; t->d = now + t->D; - if(devsched) devsched(t, t->d, SDeadline); + if(devrt) devrt(t, t->d, SDeadline); t->S = t->C; t->scheduled = now; t->state = EdfRunning; - if(devsched) devsched(t, now, SRun); + if(devrt) devrt(t, now, SRun); setΔ(); assert(t->runq.n > 0 || (up && up->task == t)); edfpush(t); @@ -342,7 +356,7 @@ edf_expel(Task *t) qlock(&edfschedlock); ilock(&edflock); - DENTER("%.*sedf_expel, %s, %d\n", ind, tabs, edf_statename[t->state], t->runq.n); + DENTER("%.*s%d edf_expel, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n); now = fastticks(nil); switch(t->state){ case EdfUnused: @@ -378,7 +392,7 @@ edf_expel(Task *t) break; } t->state = EdfExpelled; - if(devsched) devsched(t, now, SExpel); + if(devrt) devrt(t, now, SExpel); setΔ(); DLEAVE; iunlock(&edflock); @@ -432,7 +446,7 @@ edf_setclock(void) Ticks ticks; Task *t; - DENTER("%.*sedf_setclock\n", ind, tabs); + DENTER("%.*s%d edf_setclock\n", ind, tabs, m->machno); ticks = ~0ULL; if ((t = qwaitrelease.head) && t->r < ticks) ticks = t->r; @@ -447,19 +461,19 @@ edf_setclock(void) return; } if (schedpoint.when){ - DPRINT("%.*scycintrdel %T\n", ind, tabs, ticks2time(schedpoint.when)); + DPRINT("%.*s%d cycintrdel %T\n", ind, tabs, m->machno, ticks2time(schedpoint.when)); cycintrdel(&schedpoint); schedpoint.when = 0; } if (ticks <= now){ - DPRINT("%.*sedf_timer: %T too late\n", ind, tabs, ticks2time(now-ticks)); + DPRINT("%.*s%d edf_timer: %T too late\n", ind, tabs, m->machno, ticks2time(now-ticks)); ticks = now; } if (ticks != ~0ULL) { - DPRINT("%.*sprogram timer in %T\n", ind, tabs, ticks2time(ticks-now)); + DPRINT("%.*s%d program timer in %T\n", ind, tabs, m->machno, ticks2time(ticks-now)); schedpoint.when = ticks; cycintradd(&schedpoint); - DPRINT("%.*scycintradd %T\n", ind, tabs, ticks2time(schedpoint.when-now)); + DPRINT("%.*s%d cycintradd %T\n", ind, tabs, m->machno, ticks2time(schedpoint.when-now)); } clockintrsched(); DLEAVE; @@ -469,7 +483,7 @@ static void edf_intr(Ureg *, Cycintr *cy) { - DENTER("%.*sedf_intr\n", ind, tabs); + DENTER("%.*s%d edf_intr\n", ind, tabs, m->machno); /* Timer interrupt * Timed events are: * 1. release a task (look in qwaitrelease) @@ -497,13 +511,13 @@ edf_bury(Proc *p) Task *t; Proc **pp; - DPRINT("%.*sedf_bury\n", ind, tabs); + DPRINT("%.*s%d edf_bury\n", ind, tabs, m->machno); ilock(&edflock); now = fastticks(nil); if ((t = p->task) == nil){ /* race condition? */ iunlock(&edflock); - DPRINT("%.*sedf bury race, pid %lud\n", ind, tabs, p->pid); + DPRINT("%.*s%d edf bury race, pid %lud\n", ind, tabs, m->machno, p->pid); return; } assert(edfstack[m->machno].head == t); @@ -520,7 +534,7 @@ edf_bury(Proc *p) assert(t->runq.head == nil); t->state = EdfIdle; } - if(devsched) devsched(t, now, SBlock); + if(devrt) devrt(t, now, SBlock); p->task = nil; iunlock(&edflock); } @@ -531,11 +545,11 @@ edf_ready(Proc *p) Task *t; ilock(&edflock); - DENTER("%.*sedf_ready, %s, %d\n", ind, tabs, edf_statename[p->task->state], p->task->runq.n); + DENTER("%.*s%d edf_ready, %s, %d\n", ind, tabs, m->machno, edf_statename[p->task->state], p->task->runq.n); if ((t = p->task) == nil){ /* Must be a race */ iunlock(&edflock); - DPRINT("%.*sedf ready race, pid %lud\n", ind, tabs, p->pid); + DPRINT("%.*s%d edf ready race, pid %lud\n", ind, tabs, m->machno, p->pid); return; } p->rnext = 0; @@ -562,25 +576,25 @@ edf_resched(Task *t) { Task *xt; - DENTER("%.*sedf_resched, %s, %d\n", ind, tabs, edf_statename[t->state], t->runq.n); + DENTER("%.*s%d edf_resched, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n); if (t->nproc == 0){ /* No member processes */ if (t->state > EdfIdle){ t->state = EdfIdle; - if(devsched) devsched(t, now, SBlock); + if(devrt) devrt(t, now, SBlock); } DLEAVE; return; } if (t->runq.n == 0 && (up == nil || up->task != t)){ /* Member processes but none runnable */ - DPRINT("%.*sedf_resched, nothing runnable\n", ind, tabs); + DPRINT("%.*s%d edf_resched, nothing runnable\n", ind, tabs, m->machno); if (t->state == EdfRunning) edfpop(); if (t->state >= EdfIdle && t->state != EdfBlocked){ t->state = EdfBlocked; - if(devsched) devsched(t, now, SBlock); + if(devrt) devrt(t, now, SBlock); } DLEAVE; return; @@ -590,7 +604,7 @@ edf_resched(Task *t) switch (t->state){ case EdfUnused: - iprint("%.*sattempt to schedule unused task\n", ind, tabs); + iprint("%.*s%d attempt to schedule unused task\n", ind, tabs, m->machno); case EdfExpelled: DLEAVE; return; /* Not admitted */ @@ -619,7 +633,7 @@ edf_resched(Task *t) case EdfRunning: if (t->r <= now){ if (t->t < now){ - DPRINT("%.*sedf_resched, rerelease\n", ind, tabs); + DPRINT("%.*s%d edf_resched, rerelease\n", ind, tabs, m->machno); /* Period passed, rerelease */ t->r = now; xt = edfpop(); @@ -630,7 +644,7 @@ edf_resched(Task *t) } if (now < t->d){ if (t->S > 0){ - DPRINT("%.*sedf_resched, resume\n", ind, tabs); + DPRINT("%.*s%d edf_resched, resume\n", ind, tabs, m->machno); /* Running, not yet at deadline, leave it */ DLEAVE; return; @@ -640,7 +654,7 @@ edf_resched(Task *t) /* Released, but deadline is past, release at t->t */ t->r = t->t; } - DPRINT("%.*sedf_resched, schedule release\n", ind, tabs); + DPRINT("%.*s%d edf_resched, schedule release\n", ind, tabs, m->machno); xt = edfpop(); assert(xt == t); edfenqueue(&qwaitrelease, t); @@ -651,7 +665,7 @@ edf_resched(Task *t) case EdfDeadline: if (t->r <= now){ if (t->t < now){ - DPRINT("%.*sedf_resched, rerelease\n", ind, tabs); + DPRINT("%.*s%d edf_resched, rerelease\n", ind, tabs, m->machno); /* Period passed, rerelease */ t->r = now; edf_release(t); @@ -660,11 +674,11 @@ edf_resched(Task *t) } if (now < t->d && (t->flags & Useblocking) == 0){ if (t->S > 0){ - DPRINT("%.*sedf_resched, resume\n", ind, tabs); + DPRINT("%.*s%d edf_resched, resume\n", ind, tabs, m->machno); /* Released, not yet at deadline, release (again) */ t->state = EdfReleased; edfenqueue(&qreleased, t); - if(devsched) devsched(t, now, SResume); + if(devrt) devrt(t, now, SResume); DLEAVE; return; }else @@ -673,7 +687,7 @@ edf_resched(Task *t) /* Released, but deadline is past, release at t->t */ t->r = t->t; } - DPRINT("%.*sedf_resched, schedule release\n", ind, tabs); + DPRINT("%.*s%d edf_resched, schedule release\n", ind, tabs, m->machno); edfenqueue(&qwaitrelease, t); t->state = EdfAwaitrelease; edf_setclock(); @@ -685,15 +699,15 @@ edf_resched(Task *t) void edf_release(Task *t) { - DENTER("%.*sedf_release, %s, %d\n", ind, tabs, edf_statename[t->state], t->runq.n); + DENTER("%.*s%d edf_release, %s, %d\n", ind, tabs, m->machno, edf_statename[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(devsched) devsched(t, t->d, SDeadline); + if(devrt) devrt(t, t->d, SDeadline); t->S = t->C; t->state = EdfReleased; edfenqueue(&qreleased, t); - if(devsched) devsched(t, now, SRelease); + if(devrt) devrt(t, now, SRelease); edf_setclock(); DLEAVE; } @@ -727,7 +741,7 @@ edf_runproc(void) DENTER("edf_runproc %lud\n", nilcount); if (nt && (t == nil || (nt->D < t->Δ && nt->d < t->d))){ /* released task is better than current */ - DPRINT("%.*sedf_runproc: released\n", ind, tabs); + DPRINT("%.*s%d edf_runproc: released\n", ind, tabs, m->machno); edfdequeue(&qreleased); assert(nt->runq.n >= 1); edfpush(nt); @@ -735,7 +749,7 @@ edf_runproc(void) t = nt; t->scheduled = now; }else{ - DPRINT("%.*sedf_runproc: current\n", ind, tabs); + DPRINT("%.*s%d edf_runproc: current\n", ind, tabs, m->machno); } assert (t->runq.n); diff --git a/port/edf.h b/port/edf.h index 593401b058ce036c5257256623cc7fd4c0e68e7b..4a69176bd70264d2092716b450b5f95fcde1e5b3 100644 --- a/port/edf.h +++ b/port/edf.h @@ -11,6 +11,7 @@ enum { Useblocking = 0x2, }; +typedef vlong Time; typedef uvlong Ticks; typedef struct Task Task; @@ -97,7 +98,7 @@ extern Taskq qreleased; extern Taskq qextratime; extern Taskq edfstack[]; extern int edf_stateupdate; -extern void (*devsched)(Task *, Ticks, int); +extern void (*devrt)(Task *, Ticks, int); extern char * edf_statename[]; #pragma varargck type "T" Time