|
@@ -1,768 +0,0 @@
|
|
|
-#include "u.h"
|
|
|
-#include "../port/lib.h"
|
|
|
-#include "mem.h"
|
|
|
-#include "dat.h"
|
|
|
-#include "fns.h"
|
|
|
-#include "io.h"
|
|
|
-#include "ureg.h"
|
|
|
-#include "error.h"
|
|
|
-#include "realtime.h"
|
|
|
-#include "edf.h"
|
|
|
-
|
|
|
-#pragma varargck type "T" vlong
|
|
|
-
|
|
|
-/* debugging */
|
|
|
-extern int edfprint;
|
|
|
-extern Edfinterface realedf, *edf;
|
|
|
-
|
|
|
-static Schedevent *events;
|
|
|
-static int nevents, revent, wevent;
|
|
|
-static Rendez eventr;
|
|
|
-static QLock elock;
|
|
|
-static Ref logopens;
|
|
|
-static Ref debugopens;
|
|
|
-static uvlong fasthz;
|
|
|
-
|
|
|
-enum {
|
|
|
- Qistask = 0x10000,
|
|
|
- Qdir = 0,
|
|
|
- Qrealtime,
|
|
|
- Qclone,
|
|
|
- Qdebug,
|
|
|
- Qdump,
|
|
|
- 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,
|
|
|
- "dump", {Qdump}, 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 *schedstatename[] = {
|
|
|
- [SRelease] = "Release",
|
|
|
- [SRun] = "Run",
|
|
|
- [SPreempt] = "Preempt",
|
|
|
- [SBlock] = "Block",
|
|
|
- [SResume] = "Resume",
|
|
|
- [SDeadline] = "Deadline",
|
|
|
- [SYield] = "Yield",
|
|
|
- [SSlice] = "Slice",
|
|
|
- [SExpel] = "Expel",
|
|
|
-};
|
|
|
-
|
|
|
-static int taskno;
|
|
|
-
|
|
|
-static Task *
|
|
|
-taskinit(void)
|
|
|
-{
|
|
|
- Dirtab *d;
|
|
|
- Task *t;
|
|
|
-
|
|
|
- t = malloc(sizeof(Task));
|
|
|
- if (t == nil)
|
|
|
- error("taskinit: malloc");
|
|
|
- d = &t->dir;
|
|
|
- if (up->user)
|
|
|
- kstrdup(&t->user, up->user);
|
|
|
- else
|
|
|
- kstrdup(&t->user, eve);
|
|
|
- t->state = EdfExpelled;
|
|
|
- t->taskno = ++taskno;
|
|
|
- snprint(d->name, sizeof d->name, "%d", t->taskno);
|
|
|
- mkqid(&d->qid, Qistask | t->taskno, 0, QTFILE);
|
|
|
- d->length = 0;
|
|
|
- d->perm = 0600;
|
|
|
- enlist(&tasks, t);
|
|
|
- incref(t);
|
|
|
- return t;
|
|
|
-}
|
|
|
-
|
|
|
-void
|
|
|
-taskfree(Task *t)
|
|
|
-{
|
|
|
- if (decref(t))
|
|
|
- return;
|
|
|
- assert(t->procs.n == 0);
|
|
|
- assert(t->csns.n == 0);
|
|
|
- free(t->user);
|
|
|
- free(t);
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * 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;
|
|
|
- Task *t;
|
|
|
- List *l;
|
|
|
-
|
|
|
- if((ulong)c->qid.path & Qistask){
|
|
|
- qlock(&edfschedlock);
|
|
|
- taskindex = (ulong)c->qid.path & (Qistask-1);
|
|
|
- if ((t = findtask(taskindex)) == nil){
|
|
|
- qunlock(&edfschedlock);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- }else if((ulong)c->qid.path == Qtask){
|
|
|
- qlock(&edfschedlock);
|
|
|
-
|
|
|
- taskindex = i;
|
|
|
- SET(t);
|
|
|
- for (l = tasks.next; l; l = l->next)
|
|
|
- if ((t = l->i) && taskindex-- == 0)
|
|
|
- break;
|
|
|
- if (l == nil){
|
|
|
- qunlock(&edfschedlock);
|
|
|
- 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);
|
|
|
- }else{
|
|
|
- owner = t->user;
|
|
|
- if (owner == nil)
|
|
|
- owner = eve;
|
|
|
- tab = &t->dir;
|
|
|
- devdir(c, tab->qid, tab->name, tab->length, owner, tab->perm, dp);
|
|
|
- }
|
|
|
- qunlock(&edfschedlock);
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-_devrt(Task *t, Ticks t1, SEvent etype)
|
|
|
-{
|
|
|
- if (logopens.ref == 0 || nevents == Nevents)
|
|
|
- return;
|
|
|
-
|
|
|
- if(edfprint)iprint("state %s\n", schedstatename[etype]);
|
|
|
- events[wevent].tid = t->taskno;
|
|
|
- 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("wakesched\n");
|
|
|
- /* 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;
|
|
|
- edf = &realedf;
|
|
|
-}
|
|
|
-
|
|
|
-static Chan *
|
|
|
-devrtattach(char *param)
|
|
|
-{
|
|
|
- return devattach('R', 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 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 Qdump:
|
|
|
- if (mode != OREAD)
|
|
|
- error(Eperm);
|
|
|
- break;
|
|
|
- case Qclone:
|
|
|
- if (mode == OREAD)
|
|
|
- error(Eperm);
|
|
|
- edf->edfinit();
|
|
|
- qlock(&edfschedlock);
|
|
|
- /* open a new task */
|
|
|
- t = taskinit();
|
|
|
- c->qid.vers = t->taskno;
|
|
|
- qunlock(&edfschedlock);
|
|
|
- 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;
|
|
|
- Ticks now;
|
|
|
- Time tim;
|
|
|
- List *l;
|
|
|
-
|
|
|
- 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(Time))
|
|
|
- error(Ebadarg);
|
|
|
- now = fastticks(nil);
|
|
|
- tim = ticks2time(now);
|
|
|
- memmove(v, &tim, sizeof(Time));
|
|
|
- n -= sizeof(Ticks);
|
|
|
- if (n >= sizeof(Ticks)){
|
|
|
- memmove((char*)v + sizeof(Time), &now, sizeof(Ticks));
|
|
|
- n -= sizeof(Ticks);
|
|
|
- }
|
|
|
- if (n >= sizeof(Ticks)){
|
|
|
- memmove((char*)v + sizeof(Time) + sizeof(Ticks), &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:
|
|
|
- qlock(&edfschedlock);
|
|
|
- if(waserror()){
|
|
|
- qunlock(&edfschedlock);
|
|
|
- nexterror();
|
|
|
- }
|
|
|
- seprintresources(buf, buf + sizeof(buf));
|
|
|
- qunlock(&edfschedlock);
|
|
|
- poperror();
|
|
|
- return readstr(offs, v, n, buf);
|
|
|
- break;
|
|
|
- case Qdump:
|
|
|
- p = buf;
|
|
|
- e = p + sizeof(buf);
|
|
|
- qlock(&edfschedlock);
|
|
|
- qunlock(&edfschedlock);
|
|
|
- seprint(p, e, "\n");
|
|
|
- return readstr(offs, v, n, buf);
|
|
|
- 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);
|
|
|
- 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:
|
|
|
- qlock(&edfschedlock);
|
|
|
- t = findtask(s);
|
|
|
- if (t == nil){
|
|
|
- qunlock(&edfschedlock);
|
|
|
- error(Enonexist);
|
|
|
- }
|
|
|
- p = buf;
|
|
|
- e = p + sizeof(buf);
|
|
|
- p = seprint(p, e, "task=%d", s);
|
|
|
- p = seprint(p, e, " state=%s", edfstatename[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->Delta)
|
|
|
- p = seprint(p, e, " Δ=%T", ticks2time(t->Delta));
|
|
|
- else if (t->testDelta)
|
|
|
- p = seprint(p, e, " testΔ=%T", ticks2time(t->testDelta));
|
|
|
- p = seprint(p, e, " yieldonblock=%d", (t->flags & Verbose) != 0);
|
|
|
- if (t->csns.n){
|
|
|
- p = seprint(p, e, " resources='");
|
|
|
- p = seprintcsn(p, e, &t->csns);
|
|
|
- p = seprint(p, e, "'");
|
|
|
- }
|
|
|
- if (t->procs.n){
|
|
|
- p = seprint(p, e, " procs='");
|
|
|
- for (l = t->procs.next; l; l = l->next){
|
|
|
- Proc *pr = l->i;
|
|
|
- assert(pr);
|
|
|
- if (l != t->procs.next)
|
|
|
- p = seprint(p, e, " ");
|
|
|
- p = seprint(p, e, "%lud", pr->pid);
|
|
|
- }
|
|
|
- p = seprint(p, e, "'");
|
|
|
- }
|
|
|
- if (t->periods)
|
|
|
- p = seprint(p, e, " n=%lud", t->periods);
|
|
|
- if (t->missed)
|
|
|
- p = seprint(p, e, " m=%lud", t->missed);
|
|
|
- if (t->preemptions)
|
|
|
- p = seprint(p, e, " p=%lud", t->preemptions);
|
|
|
- if (t->total)
|
|
|
- p = seprint(p, e, " t=%T", ticks2time(t->total));
|
|
|
- if (t->aged)
|
|
|
- p = seprint(p, e, " c=%T", ticks2time(t->aged));
|
|
|
- seprint(p, e, "\n");
|
|
|
- qunlock(&edfschedlock);
|
|
|
- return readstr(offs, v, n, buf);
|
|
|
- }
|
|
|
- return n0 - n;
|
|
|
-}
|
|
|
-
|
|
|
-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 *r;
|
|
|
- Task *t;
|
|
|
- Ticks ticks;
|
|
|
- Time time;
|
|
|
- long pid;
|
|
|
- Proc *p;
|
|
|
- CSN *l;
|
|
|
-
|
|
|
- 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:
|
|
|
- qlock(&edfschedlock);
|
|
|
- if (waserror()){
|
|
|
- qunlock(&edfschedlock);
|
|
|
- nexterror();
|
|
|
- }
|
|
|
- t = findtask(s);
|
|
|
- if (t == nil)
|
|
|
- error(Enonexist);
|
|
|
- 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, '=')){
|
|
|
- *v = '\0';
|
|
|
- if (v != a && v[-1] == '+'){
|
|
|
- add = 1;
|
|
|
- v[-1] = '\0';
|
|
|
- } else if (v != a && v[-1] == '-'){
|
|
|
- add = -1;
|
|
|
- v[-1] = '\0';
|
|
|
- }
|
|
|
- v++;
|
|
|
- }
|
|
|
- if (strcmp(a, "T") == 0){
|
|
|
- if (e=parsetime(&time, v))
|
|
|
- error(e);
|
|
|
- ticks = time2ticks(time);
|
|
|
- edf->edfexpel(t);
|
|
|
- switch(add){
|
|
|
- case -1:
|
|
|
- if (ticks > t->T)
|
|
|
- t->T = 0;
|
|
|
- else
|
|
|
- t->T -= ticks;
|
|
|
- break;
|
|
|
- case 0:
|
|
|
- t->T = ticks;
|
|
|
- break;
|
|
|
- case 1:
|
|
|
- t->T += ticks;
|
|
|
- break;
|
|
|
- }
|
|
|
- if (t->T < time2ticks(10000000/HZ))
|
|
|
- error("period too short");
|
|
|
- DEBUG("Task %d, T=%T\n", t->taskno, ticks2time(t->T));
|
|
|
- }else if (strcmp(a, "D") == 0){
|
|
|
- if (e=parsetime(&time, v))
|
|
|
- error(e);
|
|
|
- ticks = time2ticks(time);
|
|
|
- edf->edfexpel(t);
|
|
|
- switch(add){
|
|
|
- case -1:
|
|
|
- if (ticks > t->D)
|
|
|
- t->D = 0;
|
|
|
- else
|
|
|
- t->D -= ticks;
|
|
|
- break;
|
|
|
- case 0:
|
|
|
- t->D = ticks;
|
|
|
- break;
|
|
|
- case 1:
|
|
|
- t->D += ticks;
|
|
|
- break;
|
|
|
- }
|
|
|
- DEBUG("Task %d, D=%T\n", t->taskno, ticks2time(t->D));
|
|
|
- }else if (strcmp(a, "C") == 0){
|
|
|
- if (e=parsetime(&time, v))
|
|
|
- error(e);
|
|
|
- ticks = time2ticks(time);
|
|
|
- edf->edfexpel(t);
|
|
|
- switch(add){
|
|
|
- case -1:
|
|
|
- if (ticks > t->C)
|
|
|
- t->C = 0;
|
|
|
- else
|
|
|
- t->C -= ticks;
|
|
|
- break;
|
|
|
- case 0:
|
|
|
- t->C = ticks;
|
|
|
- break;
|
|
|
- case 1:
|
|
|
- t->C += ticks;
|
|
|
- break;
|
|
|
- }
|
|
|
- if (t->C < time2ticks(10000000/HZ))
|
|
|
- error("cost too small");
|
|
|
- DEBUG("Task %d, C=%T\n", t->taskno, ticks2time(t->C));
|
|
|
- }else if (strcmp(a, "resources") == 0){
|
|
|
- if (v == nil)
|
|
|
- error("resources: value missing");
|
|
|
- edf->edfexpel(t);
|
|
|
- if (add < 0)
|
|
|
- error("can't remove resources yet");
|
|
|
- if (add == 0){
|
|
|
- List *l;
|
|
|
-
|
|
|
- while (l = t->csns.next) {
|
|
|
- r = l->i;
|
|
|
- assert(r);
|
|
|
- if (delist(&r->tasks, t))
|
|
|
- taskfree(t);
|
|
|
- if (delist(&t->csns, r))
|
|
|
- resourcefree(r);
|
|
|
- }
|
|
|
- assert(t->csns.n == 0);
|
|
|
- add = 1;
|
|
|
- USED(add);
|
|
|
- }
|
|
|
- v = parseresource(&t->csns, nil, v);
|
|
|
- if (v && *v)
|
|
|
- error("resources: parse error");
|
|
|
- }else if (strcmp(a, "acquire") == 0){
|
|
|
- if (v == nil)
|
|
|
- error("acquire: value missing");
|
|
|
- if (up->task != t)
|
|
|
- error("acquire: not for another task");
|
|
|
- if ((r = resource(v, 0)) == nil)
|
|
|
- error("acquire: no such resource");
|
|
|
- for (l = (CSN*)t->csns.next; l; l = (CSN*)l->next){
|
|
|
- if (l->i == r){
|
|
|
-DEBUG("l->p (0x%p) == t->curcsn (0x%p) && l->S (%T) != 0\n", l->p, t->curcsn, ticks2time(l->S));
|
|
|
- if(l->p == t->curcsn && l->S != 0)
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (l == nil)
|
|
|
- error("acquire: no access or resource exhausted");
|
|
|
- edf->resacquire(t, l);
|
|
|
- }else if (strcmp(a, "release") == 0){
|
|
|
- if (v == nil)
|
|
|
- error("release: value missing");
|
|
|
- if (up->task != t)
|
|
|
- error("release: not for another task");
|
|
|
- if ((r = resource(v, 0)) == nil)
|
|
|
- error("release: no such resource");
|
|
|
- if (t->curcsn->i != r)
|
|
|
- error("release: release not held or illegal release order");
|
|
|
- edf->resrelease(t);
|
|
|
- }else if (strcmp(a, "procs") == 0){
|
|
|
- if (v == nil)
|
|
|
- error("procs: value missing");
|
|
|
- if (add <= 0){
|
|
|
- edf->edfexpel(t);
|
|
|
- }
|
|
|
- if (add == 0){
|
|
|
- List *l;
|
|
|
-
|
|
|
- while (l = t->procs.next){
|
|
|
- p = l->i;
|
|
|
- assert(p->task == t);
|
|
|
- delist(&t->procs, p);
|
|
|
- p->task = nil;
|
|
|
- }
|
|
|
- add = 1;
|
|
|
- }
|
|
|
- nrargs = tokenize(v, rargs, nelem(rargs));
|
|
|
- for (j = 0; j < nrargs; j++){
|
|
|
- if (strcmp("self", rargs[j]) == 0){
|
|
|
- p = up;
|
|
|
- }else{
|
|
|
- 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(p->task && p->task != t)
|
|
|
- error("proc belongs to another task");
|
|
|
- if (add > 0){
|
|
|
- enlist(&t->procs, p);
|
|
|
- p->task = t;
|
|
|
- }else{
|
|
|
- delist(&t->procs, p);
|
|
|
- p->task = nil;
|
|
|
- }
|
|
|
- }
|
|
|
- }else if (strcmp(a, "admit") == 0){
|
|
|
- if (e = edf->edfadmit(t))
|
|
|
- error(e);
|
|
|
- }else if (strcmp(a, "besteffort") == 0){
|
|
|
- t->T = Infinity;
|
|
|
- t->D = Infinity;
|
|
|
- t->C = 0;
|
|
|
- t->flags |= BestEffort;
|
|
|
- if (e = edf->edfadmit(t))
|
|
|
- error(e);
|
|
|
- }else if (strcmp(a, "expel") == 0){
|
|
|
- edf->edfexpel(t);
|
|
|
- }else if (strcmp(a, "remove") == 0){
|
|
|
- removetask(t);
|
|
|
- poperror();
|
|
|
- qunlock(&edfschedlock);
|
|
|
- return n; /* Ignore any subsequent commands */
|
|
|
- }else if (strcmp(a, "verbose") == 0){
|
|
|
- if (t->flags & Verbose)
|
|
|
- t->flags &= ~Verbose;
|
|
|
- else
|
|
|
- t->flags |= Verbose;
|
|
|
- }else if (strcmp(a, "yieldonblock") == 0){
|
|
|
- if (v == nil)
|
|
|
- error("yieldonblock: value missing");
|
|
|
- if (add != 0)
|
|
|
- error("yieldonblock: cannot increment/decrement");
|
|
|
- if (atoi(v) == 0)
|
|
|
- t->flags &= ~Useblocking;
|
|
|
- else
|
|
|
- t->flags |= Useblocking;
|
|
|
- }else if (strcmp(a, "yield") == 0){
|
|
|
- if (edf->isedf(up) && up->task == t){
|
|
|
- edf->edfdeadline(up); /* schedule next release */
|
|
|
- qunlock(&edfschedlock);
|
|
|
- sched();
|
|
|
- qlock(&edfschedlock);
|
|
|
- }else
|
|
|
- error("yield outside task");
|
|
|
- }else
|
|
|
- error("unrecognized command");
|
|
|
- }
|
|
|
- poperror();
|
|
|
- qunlock(&edfschedlock);
|
|
|
- }
|
|
|
- return n;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-devrtremove(Chan *c)
|
|
|
-{
|
|
|
- int s;
|
|
|
- Task *t;
|
|
|
-
|
|
|
- if ((c->qid.path & Qistask) == 0)
|
|
|
- error(Eperm);
|
|
|
- s = (ulong)c->qid.path & (Qistask - 1);
|
|
|
- t = findtask(s);
|
|
|
- if (t == nil)
|
|
|
- error(Enonexist);
|
|
|
- qlock(&edfschedlock);
|
|
|
- removetask(t);
|
|
|
- qunlock(&edfschedlock);
|
|
|
-}
|
|
|
-
|
|
|
-Dev realtimedevtab = {
|
|
|
- 'R',
|
|
|
- "scheduler",
|
|
|
-
|
|
|
- devreset,
|
|
|
- devrtinit,
|
|
|
- devshutdown,
|
|
|
- devrtattach,
|
|
|
- devrtwalk,
|
|
|
- devrtstat,
|
|
|
- devrtopen,
|
|
|
- devcreate,
|
|
|
- devrtclose,
|
|
|
- devrtread,
|
|
|
- devbread,
|
|
|
- devrtwrite,
|
|
|
- devbwrite,
|
|
|
- devrtremove,
|
|
|
- devwstat,
|
|
|
-};
|