A port/devrealtime.c => port/devrealtime.c +880 -0
@@ 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;
+}
A port/devrealtime.h => port/devrealtime.h +27 -0
@@ 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
+};
+
M port/devsd.c => port/devsd.c +113 -108
@@ 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)<<DevSHIFT)|((u)<<UnitSHIFT)|\
((p)<<PartSHIFT)|((t)<<TypeSHIFT))
@@ 221,20 221,20 @@ sdinitpart(SDunit* unit)
return 1;
}
-static SDev *
+static SDev*
sdgetdev(int idno)
{
SDev *sdev;
int i;
qlock(&devslock);
- for (i = 0; i != ndevs; i++)
+ for(i = 0; i != ndevs; i++)
if (devs[i].dt_dev->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 = {
M port/edf.c => port/edf.c +64 -50
@@ 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);
M port/edf.h => port/edf.h +2 -1
@@ 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