From 567ca0b09330727481c3858b999efb066df127d0 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Mar 2002 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2002-03-20 --- port/devrealtime.c | 200 ++++++++++++++++++++++++++++++--------------- port/devrealtime.h | 13 +-- port/edf.c | 59 ++++++------- port/edf.h | 8 +- port/qlock.c | 8 +- port/sysproc.c | 2 +- 6 files changed, 183 insertions(+), 107 deletions(-) diff --git a/port/devrealtime.c b/port/devrealtime.c index 1a09d1eb55358bcde9de9f7243792744262de7dc..25fb4336bf62c93a2a274f235614f2481b29d22f 100644 --- a/port/devrealtime.c +++ b/port/devrealtime.c @@ -66,7 +66,7 @@ dumptask(char *p, char *e, Task *t, Ticks now) 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); + edf_statename[t->state], t->D, t->Delta, t->T, t->C, t->S); n = t->r - now; if (n >= 0) c = ' '; @@ -214,7 +214,7 @@ devrtinit(void) static Chan * devrtattach(char *param) { - return devattach(L'⌛', param); + return devattach(L'Σ', param); } static Walkqid * @@ -327,6 +327,7 @@ devrtread(Chan *c, void *v, long n, vlong offs) Task *t; int s, i, fst; Ticks now; + Time tim; n0 = n; // print("schedread 0x%lux\n", (ulong)c->qid.path); @@ -342,13 +343,18 @@ devrtread(Chan *c, void *v, long n, vlong offs) return devdirread(c, v, n, nil, 0, schedgen); case Qtime: - if (n < sizeof(Ticks)) + if (n < sizeof(Time)) error(Ebadarg); now = fastticks(nil); - memmove(v, &now, sizeof(Ticks)); + tim = ticks2time(now); + memmove(v, &tim, sizeof(Time)); n -= sizeof(Ticks); if (n >= sizeof(Ticks)){ - memmove((char*)v + sizeof(Time), &fasthz, 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; @@ -403,10 +409,10 @@ devrtread(Chan *c, void *v, long n, vlong offs) } 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Δ)); + if (resources[i].Delta) + p = seprint(p, e, " Δ=%T", ticks2time(resources[i].Delta)); + else if (resources[i].testDelta) + p = seprint(p, e, " testΔ=%T", ticks2time(resources[i].testDelta)); p = seprint(p, e, "\n"); } return readstr(offs, v, n, buf); @@ -450,10 +456,11 @@ devrtread(Chan *c, void *v, long n, vlong offs) 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->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->nres){ p = seprint(p, e, " resources='"); fst = 0; @@ -603,6 +610,49 @@ proctotask(Task *t, Proc *p, int add) return nil; } +static void +removetask(Task *t) +{ + int s, i; + Proc *p, **pp; + Resource *r; + + 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); +} + static long devrtwrite(Chan *c, void *va, long n, vlong) { @@ -611,6 +661,7 @@ devrtwrite(Chan *c, void *va, long n, vlong) Resource **rp, *r; Proc **pp; Task *t; + Ticks ticks; Time time; long pid; Proc *p; @@ -652,18 +703,60 @@ devrtwrite(Chan *c, void *va, long n, vlong) if (strcmp(a, "T") == 0){ if (e=parsetime(&time, v)) error(e); + ticks = time2ticks(time); edf_expel(t); - t->T = time2ticks(time); + 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; + } }else if (strcmp(a, "D") == 0){ if (e=parsetime(&time, v)) error(e); + ticks = time2ticks(time); edf_expel(t); - t->D = time2ticks(time); + 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; + } }else if (strcmp(a, "C") == 0){ if (e=parsetime(&time, v)) error(e); + ticks = time2ticks(time); edf_expel(t); - t->C = time2ticks(time); + 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; + } }else if (strcmp(a, "resources") == 0){ if (v == nil) error("resources: value missing"); @@ -703,13 +796,17 @@ devrtwrite(Chan *c, void *va, long n, vlong) } 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 (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 (e = proctotask(t, p, add)) error(e); } @@ -717,15 +814,25 @@ devrtwrite(Chan *c, void *va, long n, vlong) /* Do the admission test */ if (e = edf_admit(t)) error(e); + }else if (strcmp(a, "expel") == 0){ + /* Do the admission test */ + edf_expel(t); + }else if (strcmp(a, "remove") == 0){ + /* Do the admission test */ + removetask(t); + return n; /* Ignore any subsequent commands */ }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) + }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; @@ -745,10 +852,8 @@ devrtwrite(Chan *c, void *va, long n, vlong) static void devrtremove(Chan *c) { - int s, i; + int s; Task *t; - Proc *p, **pp; - Resource *r; if ((c->qid.path & Qistask) == 0) error(Eperm); @@ -756,44 +861,11 @@ devrtremove(Chan *c) 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); + removetask(t); } Dev realtimedevtab = { - L'⌛', + L'Σ', "scheduler", devreset, diff --git a/port/devrealtime.h b/port/devrealtime.h index 4691185788cf7c5c67e1261d21936d7bf8d4a0a9..b8279f8bfd4777cc1a80484537145e95ee13547f 100644 --- a/port/devrealtime.h +++ b/port/devrealtime.h @@ -1,10 +1,11 @@ + +typedef vlong Time; +typedef struct Schedevent Schedevent; + #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) */ @@ -20,8 +21,8 @@ enum SEvent { typedef enum SEvent SEvent; struct Schedevent { - ulong tid; // Task ID - Time ts; // Event time - SEvent etype; // Event type + ushort tid; /* Task ID */ + SEvent etype; /* Event type */ + Time ts; /* Event time */ }; diff --git a/port/edf.c b/port/edf.c index 33ed2e605c2cbc3772c5358d1fc185e7d31609ed..2b04d971ea40b005c8470cb8a8ff57ee9dafea46 100644 --- a/port/edf.c +++ b/port/edf.c @@ -72,8 +72,8 @@ void (*devrt)(Task*, Ticks, int); static void edf_intr(Ureg*, Cycintr*); static void edf_resched(Task *t); -static void setΔ(void); -static void testΔ(Task *thetask); +static void setdelta(void); +static void testdelta(Task *thetask); static char * edf_testschedulability(Task *thetask); static void edf_setclock(void); @@ -226,10 +226,14 @@ edf_block(Proc *p) /* The current proc has blocked */ ilock(&edflock); t = p->task; + assert(t); + if (t->state != EdfRunning){ + /* called by a proc just joining the task */ + iunlock(&edflock); + return; + } 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); if (t->runq.n){ /* There's another runnable proc in the running task, leave task where it is */ iunlock(&edflock); @@ -255,12 +259,11 @@ edfdeadline(Proc *p, SEvent why) if (p){ nt = p->task; assert(nt); - assert(nt->state == EdfRunning); } t = edfpop(); if(p != nil && nt != t){ - DPRINT("%.*s%d edfdeadline, %s, %d\n", ind, tabs, m->machno, edf_statename[p->task->state], p->task->runq.n); + iprint("edfdeadline, %s, %d\n", edf_statename[p->task->state], p->task->runq.n); iunlock(&edflock); assert(0 && p == nil || nt == t); } @@ -326,7 +329,7 @@ edf_admit(Task *t) t->scheduled = now; t->state = EdfRunning; if(devrt) devrt(t, now, SRun); - setΔ(); + setdelta(); assert(t->runq.n > 0 || (up && up->task == t)); edfpush(t); edf_setclock(); @@ -336,7 +339,7 @@ edf_admit(Task *t) t->state = EdfAdmitted; t->r = now; edf_release(t); - setΔ(); + setdelta(); edf_resched(t); }else{ edfenqueue(&qadmit, t); @@ -393,7 +396,7 @@ edf_expel(Task *t) } t->state = EdfExpelled; if(devrt) devrt(t, now, SExpel); - setΔ(); + setdelta(); DLEAVE; iunlock(&edflock); qunlock(&edfschedlock); @@ -739,7 +742,7 @@ edf_runproc(void) return nil; } DENTER("edf_runproc %lud\n", nilcount); - if (nt && (t == nil || (nt->D < t->Δ && nt->d < t->d))){ + if (nt && (t == nil || (nt->d < t->d && nt->D < t->Delta))){ /* released task is better than current */ DPRINT("%.*s%d edf_runproc: released\n", ind, tabs, m->machno); edfdequeue(&qreleased); @@ -777,8 +780,6 @@ static Lock waitlock; int edf_waitlock(Lock *l) { - Task *t; - iprint("edf_waitlock\n"); ilock(&waitlock); /* can't afford normal locks here */ if (l->key == 0){ @@ -820,7 +821,7 @@ edf_releaselock(Lock *l) /* Schedulability testing and its supporting routines */ static void -setΔ(void) +setdelta(void) { Resource *r, **rr; Task **tt, *t; @@ -828,23 +829,23 @@ setΔ(void) for (r = resources; r < resources + nelem(resources); r++){ if (r->name == nil) continue; - r->Δ = ~0LL; + r->Delta = ~0LL; for (tt = r->tasks; tt < r->tasks + nelem(r->tasks); tt++) - if (*tt && (*tt)->D < r->Δ) - r->Δ = (*tt)->D; + if (*tt && (*tt)->D < r->Delta) + r->Delta = (*tt)->D; } for (t = tasks; t < tasks + nelem(tasks); t++){ if (t->state < EdfIdle) continue; - t->Δ = t->D; + t->Delta = t->D; for (rr = t->res; rr < t->res + nelem(t->res); rr++) - if (*rr && (*rr)->Δ < t->Δ) - t->Δ = (*rr)->Δ; + if (*rr && (*rr)->Delta < t->Delta) + t->Delta = (*rr)->Delta; } } static void -testΔ(Task *thetask) +testdelta(Task *thetask) { Resource *r, **rr; Task **tt, *t; @@ -852,18 +853,18 @@ testΔ(Task *thetask) for (r = resources; r < resources + nelem(resources); r++){ if (r->name == nil) continue; - r->testΔ = ~0ULL; + r->testDelta = ~0ULL; for (tt = r->tasks; tt < r->tasks + nelem(r->tasks); tt++) - if (*tt && (*tt)->D < r->testΔ) - r->testΔ = (*tt)->D; + if (*tt && (*tt)->D < r->testDelta) + r->testDelta = (*tt)->D; } for (t = tasks; t < tasks + nelem(tasks); t++){ if (t->state <= EdfExpelled && t != thetask) continue; - t->testΔ = t->D; + t->testDelta = t->D; for (rr = t->res; rr < t->res + nelem(t->res); rr++) - if (*rr && (*rr)->testΔ < t->testΔ) - t->testΔ = (*rr)->testΔ; + if (*rr && (*rr)->testDelta < t->testDelta) + t->testDelta = (*rr)->testDelta; } } @@ -877,7 +878,7 @@ blockcost(Ticks ticks, Task *thetask) for (t = tasks; t < tasks + Maxtasks; t++){ if (t->state <= EdfExpelled && t != thetask) continue; - if (t->testΔ <= ticks && ticks < t->D && Cb < t->C) + if (t->testDelta <= ticks && ticks < t->D && Cb < t->C) Cb = t->C; } return Cb; @@ -917,7 +918,7 @@ edf_testschedulability(Task *thetask) int steps; /* initialize */ - testΔ(thetask); + testdelta(thetask); if (thetask && (thetask->flags & Verbose)) pprint("schedulability test\n"); qschedulability = nil; @@ -986,6 +987,8 @@ Time ticks2time(Ticks ticks) { assert(ticks >= 0); + if (fasthz == 0) + fastticks(&fasthz); return uvmuldiv(ticks, Onesecond, fasthz); } diff --git a/port/edf.h b/port/edf.h index 4a69176bd70264d2092716b450b5f95fcde1e5b3..f377f0d22147f93a8f1e8ed9803c6cef5e32d0cd 100644 --- a/port/edf.h +++ b/port/edf.h @@ -38,7 +38,7 @@ typedef enum Edfstate Edfstate; struct Edf { /* time intervals */ Ticks D; /* Deadline */ - Ticks Δ; /* Inherited deadline */ + Ticks Delta; /* Inherited deadline */ Ticks T; /* period */ Ticks C; /* Cost */ Ticks S; /* Slice: time remaining in this period */ @@ -47,7 +47,7 @@ struct Edf { Ticks d; /* (this) deadline */ Ticks t; /* Start of next period, t += T at release */ /* for schedulability testing */ - Ticks testΔ; + Ticks testDelta; int testtype; /* Release or Deadline */ Ticks testtime; Task * testnext; @@ -82,9 +82,9 @@ struct Resource char * name; Task * tasks[Ntask]; /* may contain holes */ int ntasks; - Ticks Δ; + Ticks Delta; /* for schedulability testing */ - Ticks testΔ; + Ticks testDelta; }; extern Lock edftestlock; /* for atomic admitting/expelling */ diff --git a/port/qlock.c b/port/qlock.c index 739df89dc8462562b2e358ea65b766f0cb1c164f..a96f85c4bc6bd28f16e84f4c91dca57d37a883ca 100644 --- a/port/qlock.c +++ b/port/qlock.c @@ -38,10 +38,10 @@ rwstats.qlockq++; q->tail = mp; mp->qnext = 0; mp->state = Queueing; - if (isedf(mp)) - edf_block(mp); up->qpc = getcallerpc(&q); unlock(&q->use); + if (isedf(mp)) + edf_block(mp); sched(); } @@ -104,9 +104,9 @@ rwstats.rlockq++; q->tail = mp; mp->qnext = 0; mp->state = QueueingR; + unlock(&q->use); if (isedf(mp)) edf_block(mp); - unlock(&q->use); sched(); } @@ -162,9 +162,9 @@ rwstats.wlockq++; q->tail = mp; mp->qnext = 0; mp->state = QueueingW; + unlock(&q->use); if (isedf(mp)) edf_block(mp); - unlock(&q->use); sched(); } diff --git a/port/sysproc.c b/port/sysproc.c index e7af822917a0d6f20564bc91803dfc2d95a1407a..4acaacb1ae733b257527768c43ce605ae65b6fc3 100644 --- a/port/sysproc.c +++ b/port/sysproc.c @@ -825,9 +825,9 @@ sysrendezvous(ulong *arg) up->rendhash = *l; *l = up; up->state = Rendezvous; + unlock(up->rgrp); if (isedf(up)) edf_block(up); - unlock(up->rgrp); sched();