## diffname port/edf.c 2002/0315
## diff -e /dev/null /n/emeliedump/2002/0315/sys/src/9/port/edf.c
0a
/* EDF scheduling */
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "../port/devsched.h"
#include "../port/edf.h"
/* debugging */
int edfprint = 0;
char tabs[16] = " ";
int ind;
#define DPRINT if(edfprint)iprint
#define DENTER ind++;if(edfprint)iprint
#define DLEAVE ind--
char *edf_statename[] = {
[EdfUnused] = "Unused",
[EdfExpelled] = "Expelled",
[EdfAdmitted] = "Admitted",
[EdfIdle] = "Idle",
[EdfAwaitrelease] = "Awaitrelease",
[EdfReleased] = "Released",
[EdfRunning] = "Running",
[EdfExtra] = "Extra",
[EdfPreempted] = "Preempted",
[EdfBlocked] = "Blocked",
[EdfDeadline] = "Deadline",
};
static Cycintr schedpoint; /* First scheduling point */
static Ticks utilization; /* Current utilization */
static int initialized;
static uvlong fasthz;
static Ticks now;
QLock edfschedlock; /* schedulability, held for
*/
Lock edflock;
Task tasks[Maxtasks];
int ntasks;
Resource resources[Maxresources];
int nresources;
int edf_stateupdate;
enum{
Deadline, /* Invariant for schedulability test: Deadline < Release */
Release,
};
static int earlierrelease(Task *t1, Task *t2) {return t1->r < t2->r;}
static int earlierdeadline(Task *t1, Task *t2) {return t1->d < t2->d;}
/* Tasks waiting for release, head earliest release time */
Taskq qwaitrelease = {{0}, nil, earlierrelease};
/* Released tasks waiting to run, head earliest deadline */
Taskq qreleased = {{0}, nil, earlierdeadline};
/* Exhausted EDF tasks, append at end */
Taskq qextratime;
/* Tasks admitted waiting for first release */
Taskq qadmit;
/* Running/Preempted EDF tasks, head running, one stack per processor */
Taskq edfstack[MAXMACH];
void (*devsched)(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 char * edf_testschedulability(Task *thetask);
static void edf_setclock(void);
void
edf_init(void)
{
if (initialized)
return;
ilock(&edflock);
if (initialized){
iunlock(&edflock);
return;
}
fastticks(&fasthz);
schedpoint.f = edf_intr;
schedpoint.a = &schedpoint;
schedpoint.when = 0;
initialized = 1;
iunlock(&edflock);
}
int
isedf(Proc *p)
{
return p && p->task && p->task->state >= EdfIdle;
}
int
edf_anyready(void)
{
/* If any edf tasks (with runnable procs in them) are released,
* at least one of them must be on the stack
*/
return edfstack[m->machno].head != nil;
}
static void
edfpush(Task *t)
{
Taskq *q;
DENTER("%.*sedfpush, %s, %d\n", ind, tabs, 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);
}
t->rnext = q->head;
if(devsched) devsched(t, now, SRun);
q->head = t;
DLEAVE;
}
static Task*
edfpop(void)
{
Task *t;
Taskq *q;
DENTER("%.*sedfpop\n", ind, tabs);
q = edfstack + m->machno;
if (t = q->head){
assert(t->state == EdfRunning);
q->head = t->rnext;
t->rnext = nil;
if (q->head){
assert(q->head->state == EdfPreempted);
q->head->state = EdfRunning;
if(devsched) devsched(q->head, now, SRun);
}
}
DLEAVE;
return t;
}
static Task*
edfenqueue(Taskq *q, Task *t)
{
Task *tt, **ttp;
ilock(q);
DENTER("%.*sedfenqueue, %s, %d\n", ind, tabs, edf_statename[t->state], t->runq.n);
t->rnext = nil;
if (q->head == nil) {
q->head = t;
DLEAVE;
iunlock(q);
return t;
}
SET(tt);
for (ttp = &q->head; *ttp; ttp = &tt->rnext) {
tt = *ttp;
if (q->before && q->before(t, tt)) {
t->rnext = tt;
*ttp = t;
break;
}
}
if (*ttp == nil)
tt->rnext = t;
if (t != q->head)
t = nil;
DLEAVE;
iunlock(q);
return t;
}
static Task*
edfdequeue(Taskq *q)
{
Task *t;
DENTER("%.*sedfdequeue\n", ind, tabs);
ilock(q);
if (t = q->head){
q->head = t->rnext;
t->rnext = nil;
}
iunlock(q);
DLEAVE;
return t;
}
static void
edfqremove(Taskq *q, Task *t)
{
Task **tp;
ilock(q);
DENTER("%.*sedfqremove, %s, %d\n", ind, tabs, edf_statename[t->state], t->runq.n);
for (tp = &q->head; *tp; tp = &(*tp)->rnext){
if (*tp == t){
*tp = t->rnext;
DLEAVE;
iunlock(q);
return;
}
}
DLEAVE;
iunlock(q);
}
void
edf_block(Proc *p)
{
Task *t, *pt;
/* 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);
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);
DLEAVE;
return;
}
pt = edfpop();
assert(pt == t);
t->state = EdfBlocked;
if(devsched) devsched(t, now, SBlock);
DLEAVE;
iunlock(&edflock);
}
static void
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);
SET(nt);
if (p){
nt = p->task;
assert(nt);
assert(nt->state == EdfRunning);
}
t = edfpop();
if(p != nil && nt != t){
DPRINT("%.*sedfdeadline, %s, %d\n", ind, tabs, 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);
edf_resched(t);
DLEAVE;
}
void
edf_deadline(Proc *p)
{
DENTER("%.*sedf_deadline\n", ind, tabs);
/* Task has reached its deadline */
ilock(&edflock);
now = fastticks(nil);
edfdeadline(p, SYield);
iunlock(&edflock);
DLEAVE;
}
char *
edf_admit(Task *t)
{
char *err;
if (t->state != EdfExpelled)
return "task state"; /* should never happen */
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);
now = fastticks(nil);
t->state = EdfAdmitted;
if (up->task == t){
DPRINT("%.*sedf_admitting self\n", ind, tabs);
/* 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);
t->S = t->C;
t->scheduled = now;
t->state = EdfRunning;
if(devsched) devsched(t, now, SRun);
setΔ();
assert(t->runq.n > 0 || (up && up->task == t));
edfpush(t);
edf_setclock();
}else{
if (t->runq.n){
if (edfstack[m->machno].head == nil){
t->state = EdfAdmitted;
t->r = now;
edf_release(t);
setΔ();
edf_resched(t);
}else{
edfenqueue(&qadmit, t);
}
}
}
DLEAVE;
iunlock(&edflock);
qunlock(&edfschedlock);
return nil;
}
void
edf_expel(Task *t)
{
Task *tt;
qlock(&edfschedlock);
ilock(&edflock);
DENTER("%.*sedf_expel, %s, %d\n", ind, tabs, edf_statename[t->state], t->runq.n);
now = fastticks(nil);
switch(t->state){
case EdfUnused:
case EdfExpelled:
/* That was easy */
DLEAVE;
iunlock(&edflock);
qunlock(&edfschedlock);
return;
case EdfAdmitted:
case EdfIdle:
/* Just reset state */
break;
case EdfAwaitrelease:
edfqremove(&qwaitrelease, t);
break;
case EdfReleased:
edfqremove(&qreleased, t);
break;
case EdfRunning:
/* Task must be expelling itself */
tt = edfpop();
assert(t == tt);
break;
case EdfExtra:
edfqremove(&qextratime, t);
break;
case EdfPreempted:
edfqremove(edfstack + m->machno, t);
break;
case EdfBlocked:
case EdfDeadline:
break;
}
t->state = EdfExpelled;
if(devsched) devsched(t, now, SExpel);
setΔ();
DLEAVE;
iunlock(&edflock);
qunlock(&edfschedlock);
return;
}
static void
edf_timer(void)
{
Ticks used;
Task *t;
// If up is not set, we're running inside the scheduler
// for non-real-time processes.
if (up && isedf(up)) {
t = up->task;
assert(t->scheduled > 0);
used = now - t->scheduled;
t->scheduled = now;
if (t->r < now){
if (t->S <= used)
t->S = 0LL;
else
t->S -= used;
if (t->d <= now || t->S == 0LL){
/* Task has reached its deadline/slice, remove from queue */
edfdeadline(up, SSlice);
while (t = edfstack[m->machno].head){
if (now < t->d)
break;
edfdeadline(nil, SSlice);
}
}
}
}
while((t = qwaitrelease.head) && t->r <= now){
/* There's something waiting to be released and its time has come */
edfdequeue(&qwaitrelease);
edf_release(t);
}
}
static void
edf_setclock(void)
{
Ticks ticks;
Task *t;
DENTER("%.*sedf_setclock\n", ind, tabs);
ticks = ~0ULL;
if ((t = qwaitrelease.head) && t->r < ticks)
ticks = t->r;
if (t = edfstack[m->machno].head){
if (t->d < ticks)
ticks = t->d;
if (now + t->S < ticks)
ticks = now + t->S;
}
if (schedpoint.when > now && schedpoint.when <= ticks){
DLEAVE;
return;
}
if (schedpoint.when){
DPRINT("%.*scycintrdel %T\n", ind, tabs, ticks2time(schedpoint.when));
cycintrdel(&schedpoint);
schedpoint.when = 0;
}
if (ticks <= now){
DPRINT("%.*sedf_timer: %T too late\n", ind, tabs, ticks2time(now-ticks));
ticks = now;
}
if (ticks != ~0ULL) {
DPRINT("%.*sprogram timer in %T\n", ind, tabs, ticks2time(ticks-now));
schedpoint.when = ticks;
cycintradd(&schedpoint);
DPRINT("%.*scycintradd %T\n", ind, tabs, ticks2time(schedpoint.when-now));
}
clockintrsched();
DLEAVE;
}
static void
edf_intr(Ureg *, Cycintr *cy)
{
DENTER("%.*sedf_intr\n", ind, tabs);
/* Timer interrupt
* Timed events are:
* 1. release a task (look in qwaitrelease)
* 2. task reaches deadline
*/
now = fastticks(nil);
assert(cy == &schedpoint && schedpoint.when <= now);
if(active.exiting)
return;
ilock(&edflock);
edf_timer();
edf_setclock();
iunlock(&edflock);
DLEAVE;
sched();
splhi();
}
void
edf_bury(Proc *p)
{
Task *t;
Proc **pp;
DPRINT("%.*sedf_bury\n", ind, tabs);
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);
return;
}
assert(edfstack[m->machno].head == t);
for (pp = t->procs; pp < t->procs + nelem(t->procs); pp++)
if (*pp == p){
t->nproc--;
*pp = nil;
}
if (t->runq.head == nil){
edfpop();
t->state = EdfBlocked;
}
if (t->nproc == 0){
assert(t->runq.head == nil);
t->state = EdfIdle;
}
if(devsched) devsched(t, now, SBlock);
p->task = nil;
iunlock(&edflock);
}
void
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);
if ((t = p->task) == nil){
/* Must be a race */
iunlock(&edflock);
DPRINT("%.*sedf ready race, pid %lud\n", ind, tabs, p->pid);
return;
}
p->rnext = 0;
p->readytime = m->ticks;
p->state = Ready;
t->runq.n++;
if(t->runq.tail){
t->runq.tail->rnext = p;
t->runq.tail = p;
}else{
t->runq.head = p;
t->runq.tail = p;
/* first proc to become runnable in this task */
now = fastticks(nil);
edf_resched(t);
}
DLEAVE;
iunlock(&edflock);
}
static void
edf_resched(Task *t)
{
Task *xt;
DENTER("%.*sedf_resched, %s, %d\n", ind, tabs, 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);
}
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);
if (t->state == EdfRunning)
edfpop();
if (t->state >= EdfIdle && t->state != EdfBlocked){
t->state = EdfBlocked;
if(devsched) devsched(t, now, SBlock);
}
DLEAVE;
return;
}
/* There are runnable processes */
switch (t->state){
case EdfUnused:
iprint("%.*sattempt to schedule unused task\n", ind, tabs);
case EdfExpelled:
DLEAVE;
return; /* Not admitted */
case EdfIdle:
/* task was idle, schedule release now or later */
if (t->r < now){
if (t->t < now)
t->t = now + t->T;
t->r = t->t;
}
edf_release(t);
break;
case EdfAwaitrelease:
case EdfReleased:
case EdfExtra:
case EdfPreempted:
/* dealt with by timer */
break;
case EdfAdmitted:
/* test whether task can be started */
if (edfstack[m->machno].head != nil){
DLEAVE;
return;
}
/* fall through */
case EdfRunning:
if (t->r <= now){
if (t->t < now){
DPRINT("%.*sedf_resched, rerelease\n", ind, tabs);
/* Period passed, rerelease */
t->r = now;
xt = edfpop();
assert(xt == t);
edf_release(t);
DLEAVE;
return;
}
if (now < t->d){
if (t->S > 0){
DPRINT("%.*sedf_resched, resume\n", ind, tabs);
/* Running, not yet at deadline, leave it */
DLEAVE;
return;
}else
t->d = now;
}
/* Released, but deadline is past, release at t->t */
t->r = t->t;
}
DPRINT("%.*sedf_resched, schedule release\n", ind, tabs);
xt = edfpop();
assert(xt == t);
edfenqueue(&qwaitrelease, t);
t->state = EdfAwaitrelease;
edf_setclock();
break;
case EdfBlocked:
case EdfDeadline:
if (t->r <= now){
if (t->t < now){
DPRINT("%.*sedf_resched, rerelease\n", ind, tabs);
/* Period passed, rerelease */
t->r = now;
edf_release(t);
DLEAVE;
return;
}
if (now < t->d && (t->flags & Useblocking) == 0){
if (t->S > 0){
DPRINT("%.*sedf_resched, resume\n", ind, tabs);
/* Released, not yet at deadline, release (again) */
t->state = EdfReleased;
edfenqueue(&qreleased, t);
if(devsched) devsched(t, now, SResume);
DLEAVE;
return;
}else
t->d = now;
}
/* Released, but deadline is past, release at t->t */
t->r = t->t;
}
DPRINT("%.*sedf_resched, schedule release\n", ind, tabs);
edfenqueue(&qwaitrelease, t);
t->state = EdfAwaitrelease;
edf_setclock();
break;
}
DLEAVE;
}
void
edf_release(Task *t)
{
DENTER("%.*sedf_release, %s, %d\n", ind, tabs, 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);
t->S = t->C;
t->state = EdfReleased;
edfenqueue(&qreleased, t);
if(devsched) devsched(t, now, SRelease);
edf_setclock();
DLEAVE;
}
Proc *
edf_runproc(void)
{
/* Return an edf proc to run or nil */
Task *t, *nt;
Proc *p;
// Ticks when;
static ulong nilcount;
/* Figure out if the current proc should be preempted*/
ilock(&edflock);
assert(ind < nelem(tabs));
now = fastticks(nil);
/* first candidate is at the top of the stack of running procs */
t = edfstack[m->machno].head;
/* check out head of the release queue for a proc with a better deadline */
nt = qreleased.head;
if (t == nil && nt == nil){
nilcount++;
iunlock(&edflock);
return nil;
}
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);
edfdequeue(&qreleased);
assert(nt->runq.n >= 1);
edfpush(nt);
nt->state = EdfRunning;
t = nt;
t->scheduled = now;
}else{
DPRINT("%.*sedf_runproc: current\n", ind, tabs);
}
assert (t->runq.n);
/* Get first proc off t's run queue
* No need to lock runq, edflock always held to access runq
*/
t->state = EdfRunning;
p = t->runq.head;
if ((t->runq.head = p->rnext) == nil)
t->runq.tail = nil;
t->runq.n--;
p->state = Scheding;
if(p->mp != MACHP(m->machno))
p->movetime = MACHP(0)->ticks + HZ/10;
p->mp = MACHP(m->machno);
edf_setclock();
DLEAVE;
iunlock(&edflock);
return p;
}
static Lock waitlock;
int
edf_waitlock(Lock *l)
{
iprint("edf_waitlock\n");
ilock(&waitlock); /* can't afford normal locks here */
if (l->key == 0){
/* race on lock, don't block, just return */
iunlock(&waitlock);
return 0;
}
edf_block(up);
up->rnext = l->edfwaiting; /* enqueue on lock */
l->edfwaiting = up;
up->state = Scheding;
up->lockwait = l;
iunlock(&waitlock);
return 1;
}
void
edf_releaselock(Lock *l)
{
Proc *p;
iprint("edf_releaselock\n");
ilock(&waitlock); /* can't afford normal locks here */
if(l->edfwaiting == nil){
iunlock(&waitlock);
return;
}
p = l->edfwaiting;
l->edfwaiting = p->rnext;
assert(p->lockwait == l);
if(p->state != Scheding)
print("edf_releaselock: %s %lud %s\n", p->text, p->pid, statename[p->state]);
p->lockwait = nil;
iunlock(&waitlock);
edf_ready(p);
}
/* Schedulability testing and its supporting routines */
static void
setΔ(void)
{
Resource *r, **rr;
Task **tt, *t;
for (r = resources; r < resources + nelem(resources); r++){
if (r->name == nil)
continue;
r->Δ = ~0LL;
for (tt = r->tasks; tt < r->tasks + nelem(r->tasks); tt++)
if (*tt && (*tt)->D < r->Δ)
r->Δ = (*tt)->D;
}
for (t = tasks; t < tasks + nelem(tasks); t++){
if (t->state < EdfIdle)
continue;
t->Δ = t->D;
for (rr = t->res; rr < t->res + nelem(t->res); rr++)
if (*rr && (*rr)->Δ < t->Δ)
t->Δ = (*rr)->Δ;
}
}
static void
testΔ(Task *thetask)
{
Resource *r, **rr;
Task **tt, *t;
for (r = resources; r < resources + nelem(resources); r++){
if (r->name == nil)
continue;
r->testΔ = ~0ULL;
for (tt = r->tasks; tt < r->tasks + nelem(r->tasks); tt++)
if (*tt && (*tt)->D < r->testΔ)
r->testΔ = (*tt)->D;
}
for (t = tasks; t < tasks + nelem(tasks); t++){
if (t->state <= EdfExpelled && t != thetask)
continue;
t->testΔ = t->D;
for (rr = t->res; rr < t->res + nelem(t->res); rr++)
if (*rr && (*rr)->testΔ < t->testΔ)
t->testΔ = (*rr)->testΔ;
}
}
static Ticks
blockcost(Ticks ticks, Task *thetask)
{
Task *t;
Ticks Cb;
Cb = 0;
for (t = tasks; t < tasks + Maxtasks; t++){
if (t->state <= EdfExpelled && t != thetask)
continue;
if (t->testΔ <= ticks && ticks < t->D && Cb < t->C)
Cb = t->C;
}
return Cb;
}
static Task *qschedulability;
static void
testenq(Task *t)
{
Task *tt, **ttp;
t->testnext = nil;
if (qschedulability == nil) {
qschedulability = t;
return;
}
SET(tt);
for (ttp = &qschedulability; *ttp; ttp = &tt->testnext) {
tt = *ttp;
if (t->testtime < tt->testtime
|| (t->testtime == tt->testtime && t->testtype < tt->testtype)){
t->testnext = tt;
*ttp = t;
return;
}
}
assert(tt->testnext == nil);
tt->testnext = t;
}
static char *
edf_testschedulability(Task *thetask)
{
Task *t;
Ticks H, G, Cb, ticks;
int steps;
/* initialize */
testΔ(thetask);
if (thetask && (thetask->flags & Verbose))
pprint("schedulability test\n");
qschedulability = nil;
for (t = tasks; t < tasks + Maxtasks; t++){
if (t->state <= EdfExpelled && t != thetask)
continue;
t->testtype = Release;
t->testtime = 0;
if (thetask && (thetask->flags & Verbose))
pprint("\tInit: enqueue task %lud\n", t - tasks);
testenq(t);
}
H=0;
G=0;
ticks = 0;
for(steps = 0; steps < Maxsteps; steps++){
t = qschedulability;
qschedulability = t->testnext;
ticks = t->testtime;
switch (t->testtype){
case Deadline:
H += t->C;
Cb = blockcost(ticks, thetask);
if (thetask && (thetask->flags & Verbose))
pprint("\tStep %3d, Ticks %T, task %lud, deadline, H += %T → %T, Cb = %T\n",
steps, ticks2time(ticks), t - tasks,
ticks2time(t->C), ticks2time(H), ticks2time(Cb));
if (H+Cb>ticks)
return "not schedulable";
t->testtime += t->T - t->D;
t->testtype = Release;
testenq(t);
break;
case Release:
if (thetask && (thetask->flags & Verbose))
pprint("\tStep %3d, Ticks %T, task %lud, release, G %T, C%T\n",
steps, ticks2time(ticks), t - tasks,
ticks2time(t->C), ticks2time(G));
if(ticks && G <= ticks)
return nil;
G += t->C;
t->testtime += t->D;
t->testtype = Deadline;
testenq(t);
break;
default:
assert(0);
}
}
return "probably not schedulable";
}
static uvlong
uvmuldiv(uvlong x, ulong num, ulong den)
{
/* multiply, then divide, avoiding overflow */
uvlong hi;
hi = (x & 0xffffffff00000000LL) >> 32;
x &= 0xffffffffLL;
hi *= num;
return (x*num + (hi%den << 32)) / den + (hi/den << 32);
}
Time
ticks2time(Ticks ticks)
{
assert(ticks >= 0);
return uvmuldiv(ticks, Onesecond, fasthz);
}
Ticks
time2ticks(Time time)
{
assert(time >= 0);
return uvmuldiv(time, fasthz, Onesecond);
}
.
## diffname port/edf.c 2002/0316
## diff -e /n/emeliedump/2002/0315/sys/src/9/port/edf.c /n/emeliedump/2002/0316/sys/src/9/port/edf.c
738c
DPRINT("%.*s%d edf_runproc: current\n", ind, tabs, m->machno);
.
730c
DPRINT("%.*s%d edf_runproc: released\n", ind, tabs, m->machno);
.
696c
if(devrt) devrt(t, now, SRelease);
.
692c
if(devrt) devrt(t, t->d, SDeadline);
.
688c
DENTER("%.*s%d edf_release, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n);
.
676c
DPRINT("%.*s%d edf_resched, schedule release\n", ind, tabs, m->machno);
.
667c
if(devrt) devrt(t, now, SResume);
.
663c
DPRINT("%.*s%d edf_resched, resume\n", ind, tabs, m->machno);
.
654c
DPRINT("%.*s%d edf_resched, rerelease\n", ind, tabs, m->machno);
.
643c
DPRINT("%.*s%d edf_resched, schedule release\n", ind, tabs, m->machno);
.
633c
DPRINT("%.*s%d edf_resched, resume\n", ind, tabs, m->machno);
.
622c
DPRINT("%.*s%d edf_resched, rerelease\n", ind, tabs, m->machno);
.
593c
iprint("%.*s%d attempt to schedule unused task\n", ind, tabs, m->machno);
.
583c
if(devrt) devrt(t, now, SBlock);
.
577c
DPRINT("%.*s%d edf_resched, nothing runnable\n", ind, tabs, m->machno);
.
570c
if(devrt) devrt(t, now, SBlock);
.
565c
DENTER("%.*s%d edf_resched, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n);
.
538c
DPRINT("%.*s%d edf ready race, pid %lud\n", ind, tabs, m->machno, p->pid);
.
534c
DENTER("%.*s%d edf_ready, %s, %d\n", ind, tabs, m->machno, edf_statename[p->task->state], p->task->runq.n);
.
523c
if(devrt) devrt(t, now, SBlock);
.
506c
DPRINT("%.*s%d edf bury race, pid %lud\n", ind, tabs, m->machno, p->pid);
.
500c
DPRINT("%.*s%d edf_bury\n", ind, tabs, m->machno);
.
472c
DENTER("%.*s%d edf_intr\n", ind, tabs, m->machno);
.
462c
DPRINT("%.*s%d cycintradd %T\n", ind, tabs, m->machno, ticks2time(schedpoint.when-now));
.
459c
DPRINT("%.*s%d program timer in %T\n", ind, tabs, m->machno, ticks2time(ticks-now));
.
455c
DPRINT("%.*s%d edf_timer: %T too late\n", ind, tabs, m->machno, ticks2time(now-ticks));
.
450c
DPRINT("%.*s%d cycintrdel %T\n", ind, tabs, m->machno, ticks2time(schedpoint.when));
.
435c
DENTER("%.*s%d edf_setclock\n", ind, tabs, m->machno);
.
381c
if(devrt) devrt(t, now, SExpel);
.
345c
DENTER("%.*s%d edf_expel, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n);
.
314c
if(devrt) devrt(t, now, SRun);
.
310c
if(devrt) devrt(t, t->d, SDeadline);
.
305c
DPRINT("%.*s%d edf_admitting self\n", ind, tabs, m->machno);
.
303a
if(devrt) devrt(t, t->d, SAdmit);
.
300c
DENTER("%.*s%d edf_admit, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n);
.
293a
/* 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";
.
278c
DENTER("%.*s%d edf_deadline\n", ind, tabs, m->machno);
.
270c
if(devrt) devrt(t, now, why);
.
263c
DPRINT("%.*s%d edfdeadline, %s, %d\n", ind, tabs, m->machno, edf_statename[p->task->state], p->task->runq.n);
.
253c
DENTER("%.*s%d edfdeadline, %s, %d\n", ind, tabs, m->machno, edf_statename[p->task->state], p->task->runq.n);
.
242c
if(devrt) devrt(t, now, SBlock);
.
229c
DENTER("%.*s%d edf_block, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n);
.
208c
DENTER("%.*s%d edfqremove, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n);
.
191c
DENTER("%.*s%d edfdequeue\n", ind, tabs, m->machno);
.
160c
DENTER("%.*s%d edfenqueue, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n);
.
147c
if(devrt) devrt(q->head, now, SRun);
.
138c
DENTER("%.*s%d edfpop\n", ind, tabs, m->machno);
.
127c
if(devrt) devrt(t, now, SRun);
.
124c
if(devrt) devrt(q->head, now, SPreempt);
.
118c
DENTER("%.*s%d edfpush, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n);
.
71c
void (*devrt)(Task*, Ticks, int);
.
8c
#include "../port/devrealtime.h"
.
## diffname port/edf.c 2002/0319
## diff -e /n/emeliedump/2002/0316/sys/src/9/port/edf.c /n/emeliedump/2002/0319/sys/src/9/port/edf.c
779a
Task *t;
.
## diffname port/edf.c 2002/0320
## diff -e /n/emeliedump/2002/0319/sys/src/9/port/edf.c /n/emeliedump/2002/0320/sys/src/9/port/edf.c
988a
if (fasthz == 0)
fastticks(&fasthz);
.
920c
testdelta(thetask);
.
880c
if (t->testDelta <= ticks && ticks < t->D && Cb < t->C)
.
865,866c
if (*rr && (*rr)->testDelta < t->testDelta)
t->testDelta = (*rr)->testDelta;
.
863c
t->testDelta = t->D;
.
857,858c
if (*tt && (*tt)->D < r->testDelta)
r->testDelta = (*tt)->D;
.
855c
r->testDelta = ~0ULL;
.
847c
testdelta(Task *thetask)
.
841,842c
if (*rr && (*rr)->Delta < t->Delta)
t->Delta = (*rr)->Delta;
.
839c
t->Delta = t->D;
.
833,834c
if (*tt && (*tt)->D < r->Delta)
r->Delta = (*tt)->D;
.
831c
r->Delta = ~0LL;
.
823c
setdelta(void)
.
780,781d
742c
if (nt && (t == nil || (nt->d < t->d && nt->D < t->Delta))){
.
396c
setdelta();
.
339c
setdelta();
.
329c
setdelta();
.
263c
iprint("edfdeadline, %s, %d\n", edf_statename[p->task->state], p->task->runq.n);
.
258d
231,232d
228a
assert(t);
if (t->state != EdfRunning){
/* called by a proc just joining the task */
iunlock(&edflock);
return;
}
.
75,76c
static void setdelta(void);
static void testdelta(Task *thetask);
.
## diffname port/edf.c 2002/0321
## diff -e /n/emeliedump/2002/0320/sys/src/9/port/edf.c /n/emeliedump/2002/0321/sys/src/9/port/edf.c
261c
if (nt == nil || nt->state != EdfRunning)
return;
.
## diffname port/edf.c 2002/0322
## diff -e /n/emeliedump/2002/0321/sys/src/9/port/edf.c /n/emeliedump/2002/0322/sys/src/9/port/edf.c
805d
784d
774d
756c
DPRINT("%d edf_runproc: current\n", m->machno);
.
748c
DPRINT("%d edf_runproc: released\n", m->machno);
.
745c
DPRINT("edf_runproc %lud\n", nilcount);
.
731d
716d
706c
DPRINT("%d edf_release, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n);
.
700d
694c
DPRINT("%d edf_resched, schedule release\n", m->machno);
.
686d
681c
DPRINT("%d edf_resched, resume\n", m->machno);
.
676d
672c
DPRINT("%d edf_resched, rerelease\n", m->machno);
.
661c
DPRINT("%d edf_resched, schedule release\n", m->machno);
.
653d
651c
DPRINT("%d edf_resched, resume\n", m->machno);
.
646d
640c
DPRINT("%d edf_resched, rerelease\n", m->machno);
.
633d
613d
611c
iprint("%d attempt to schedule unused task\n", m->machno);
.
603d
595c
DPRINT("%d edf_resched, nothing runnable\n", m->machno);
.
590d
583c
DPRINT("%d edf_resched, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n);
.
574d
556c
DPRINT("%d edf ready race, pid %lud\n", m->machno, p->pid);
.
552c
DPRINT("%d edf_ready, %s, %d\n", m->machno, edf_statename[p->task->state], p->task->runq.n);
.
524c
DPRINT("%d edf bury race, pid %lud\n", m->machno, p->pid);
.
518c
DPRINT("%d edf_bury\n", m->machno);
.
507d
490c
DPRINT("%d edf_intr\n", m->machno);
.
483d
480c
DPRINT("%d cycintradd %T\n", m->machno, ticks2time(schedpoint.when-now));
.
477c
DPRINT("%d program timer in %T\n", m->machno, ticks2time(ticks-now));
.
473c
DPRINT("%d edf_timer: %T too late\n", m->machno, ticks2time(now-ticks));
.
468c
DPRINT("%d cycintrdel %T\n", m->machno, ticks2time(schedpoint.when));
.
464d
453c
DPRINT("%d edf_setclock\n", m->machno);
.
401d
369d
363c
DPRINT("%d edf_expel, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n);
.
350d
323c
DPRINT("%d edf_admitting self\n", m->machno);
.
317c
DPRINT("%d edf_admit, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n);
.
288d
282c
DPRINT("%d edf_deadline\n", m->machno);
.
276d
257c
DPRINT("%d edfdeadline, %s, %d\n", m->machno, edf_statename[p->task->state], p->task->runq.n);
.
247d
240d
235c
DPRINT("%d edf_block, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n);
.
217d
212d
208c
DPRINT("%d edfqremove, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n);
.
198d
191c
DPRINT("%d edfdequeue\n", m->machno);
.
181d
164d
160c
DPRINT("%d edfenqueue, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n);
.
150d
138c
DPRINT("%d edfpop\n", m->machno);
.
129d
118c
DPRINT("%d edfpush, %s, %d\n", m->machno, edf_statename[t->state], t->runq.n);
.
16,17d
13,14d
## diffname port/edf.c 2002/0327
## diff -e /n/emeliedump/2002/0322/sys/src/9/port/edf.c /n/emeliedump/2002/0327/sys/src/9/port/edf.c
740c
when = now + t->S;
if (t->d < when)
when = t->d;
if (cycdeadline.when){
if(cycdeadline.when == when){
iunlock(&edflock);
return p;
}
DPRINT("%d cycintrdel %T\n", m->machno, ticks2time(cycdeadline.when));
cycintrdel(&cycdeadline);
}
if (when <= now){
DPRINT("%d edf_timer: %T too late\n", m->machno, ticks2time(now-when));
when = now;
}
DPRINT("%d program timer in %T\n", m->machno, ticks2time(when-now));
cycdeadline.when = when;
cycintradd(&cycdeadline);
DPRINT("%d cycintradd %T\n", m->machno, ticks2time(cycdeadline.when-now));
clockintrsched();
.
694c
Ticks when;
.
684d
664,667c
schedrelease(t);
.
636,638c
schedrelease(t);
.
633d
421,485d
394a
DPRINT("%d edfdeadlineintr\n", m->machno);
/* Task reached deadline
*/
now = fastticks(nil);
if(active.exiting)
return;
ilock(&edflock);
.
391a
Task *t;
now = fastticks(nil);
if(active.exiting)
return;
ilock(&edflock);
while((t = qwaitrelease.head) && t->r <= now){
/* There's something waiting to be released and its time has come */
edfdequeue(&qwaitrelease);
edf_release(t);
}
iunlock(&edflock);
sched();
splhi();
}
static void
edfdeadlineintr(Ureg *, Cycintr *cy)
{
.
390c
edfreleaseintr(void)
.
361c
if (edfqremove(&qwaitrelease, t))
edfreleasetimer();
.
321d
258c
if (cycdeadline.when){
cycintrdel(&cycdeadline);
cycdeadline.when = 0;
clockintrsched();
}
.
210a
edfreleasetimer(void)
{
Task *t;
t = qwaitrelease.head;
DPRINT("edf_schedrelease clock\n");
if (cycrelease.when == t->r)
return;
if (cycrelease.when){
DPRINT("%d cycintrdel %T\n", m->machno, ticks2time(cycrelease.when));
cycintrdel(&cycrelease);
}
cycrelease.when = t->r;
if (cycrelease.when <= now){
DPRINT("%d edf_timer: %T too late\n", m->machno, ticks2time(now-ticks));
cycrelease.when = now;
}
DPRINT("%d program timer in %T\n", m->machno, ticks2time(ticks-now));
cycintradd(&cycrelease);
DPRINT("%d cycintradd %T\n", m->machno, ticks2time(cycrelease.when-now));
clockintrsched();
}
void
edf_schedrelease(Task *t)
{
Ticks ticks;
DPRINT("%d edf_schedrelease\n", m->machno);
/* Schedule a task for release */
t->state = EdfAwaitrelease;
if (edfenqueue(&qwaitrelease, t))
edfreleasetimer();
}
void
.
209a
.
204c
return t;
.
202a
t = (tp == &q->head) ? q->head : nil;
.
193c
static Task*
.
87,89c
cycdeadline.f = edfdeadlineintr;
cycdeadline.a = &cycdeadline;
cycdeadline.when = 0;
cycrelease.f = edfreleaseintr;
cycrelease.a = &cycrelease;
cycrelease.when = 0;
.
74c
static void edfreleaseintr(void);
.
69c
static void edfdeadlineintr(Ureg*, Cycintr*);
.
29c
static Cycintr cycdeadline; /* Time of next deadline */
static Cycintr cycrelease; /* Time of next release */
.
## diffname port/edf.c 2002/0328
## diff -e /n/emeliedump/2002/0327/sys/src/9/port/edf.c /n/emeliedump/2002/0328/sys/src/9/port/edf.c
770,810d
765d
758,762d
755d
749a
if (when < now){
DPRINT("%d edf_timer: %T too late\n", m->machno, ticks2time(now-when));
when = now;
}
.
673c
t->state = EdfAwaitrelease;
if (edfenqueue(&qwaitrelease, t))
edfreleasetimer();
.
647c
t->state = EdfAwaitrelease;
if (edfenqueue(&qwaitrelease, t))
edfreleasetimer();
.
474a
now = fastticks(nil);
.
467a
cycdeadline.when = 0;
.
464,466d
459a
/* Task reached deadline */
.
458c
edfdeadlineintr(Ureg*, Cycintr*)
.
449a
edfreleasetimer();
.
446a
now = fastticks(nil);
.
442a
cycrelease.when = 0;
.
441c
DPRINT("%d edfreleaseintr\n", m->machno);
.
437c
edfreleaseintr(Ureg*, Cycintr*)
.
242,253d
237d
234,235d
231,232c
if (cycrelease.when <= now)
.
229d
226,227c
DPRINT("edfreleasetimer clock\n");
if (cycrelease.when)
.
222,224c
if ((t = qwaitrelease.head) == nil)
.
213a
return nil;
.
76c
static void edfreleaseintr(Ureg *, Cycintr *cy);
static void edfdeadlineintr(Ureg*, Cycintr*);
.
71d
36,37c
QLock edfschedlock;
.
## diffname port/edf.c 2002/0329
## diff -e /n/emeliedump/2002/0328/sys/src/9/port/edf.c /n/emeliedump/2002/0329/sys/src/9/port/edf.c
484a
if (up->nlocks)
iprint("have %lud locks at deadline\n", up->nlocks);
.
212d
208d
202d
193d
188d
178d
162d
157d
32d
## diffname port/edf.c 2002/0330
## diff -e /n/emeliedump/2002/0329/sys/src/9/port/edf.c /n/emeliedump/2002/0330/sys/src/9/port/edf.c
443a
clockintrsched();
.
442a
cycintrdel(&cycdeadline);
.
415a
clockintrsched();
.
414a
cycintrdel(&cycrelease);
.
## diffname port/edf.c 2002/0404
## diff -e /n/emeliedump/2002/0330/sys/src/9/port/edf.c /n/emeliedump/2002/0404/sys/src/9/port/edf.c
872d
480,481d
## diffname port/edf.c 2002/0405
## diff -e /n/emeliedump/2002/0404/sys/src/9/port/edf.c /n/emeliedump/2002/0405/sys/src/9/port/edf.c
749c
timeradd(&cycdeadline);
.
746c
timerdel(&cycdeadline);
.
445c
timerdel(&cycdeadline);
.
436c
edfdeadlineintr(Ureg*, Timer*)
.
415c
timerdel(&cycrelease);
.
409c
edfreleaseintr(Ureg*, Timer*)
.
274c
timerdel(&cycdeadline);
.
221c
timeradd(&cycrelease);
.
217c
timerdel(&cycrelease);
.
73,74c
static void edfreleaseintr(Ureg *, Timer *cy);
static void edfdeadlineintr(Ureg*, Timer*);
.
29,30c
static Timer cycdeadline; /* Time of next deadline */
static Timer cycrelease; /* Time of next release */
.
## diffname port/edf.c 2002/0410
## diff -e /n/emeliedump/2002/0405/sys/src/9/port/edf.c /n/emeliedump/2002/0410/sys/src/9/port/edf.c
848c
edftestschedulability(Task *thetask)
.
748,750c
deadlinetimer[m->machno].when = when;
timeradd(&deadlinetimer[m->machno]);
.
746c
timerdel(&deadlinetimer[m->machno]);
.
741,742c
if (deadlinetimer[m->machno].when){
if(deadlinetimer[m->machno].when == when){
.
738c
DPRINT("%d edftimer: %T too late\n", m->machno, ticks2time(now-when));
.
717c
runt:
.
715c
DPRINT("%d edfrunproc: current\n", m->machno);
.
707c
DPRINT("%d edfrunproc: released\n", m->machno);
.
705a
if (conf.nmach > 1){
for (i = 0; i < conf.nmach; i++){
if (i == m->machno)
continue;
xt = edfstack[i].head;
if (xt && xt->Delta <= nt->D){
DPRINT("%d edfrunproc: interprocessor conflict, run current\n", m->machno);
if (t)
goto runt;
nilcount++;
iunlock(&edflock);
return nil;
}
}
}
.
704c
DPRINT("edfrunproc %lud\n", nilcount);
.
687a
int i;
.
684c
Task *t, *nt, *xt;
.
680c
edfrunproc(void)
.
668c
DPRINT("%d edfrelease, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
.
666c
edfrelease(Task *t)
.
646c
DPRINT("%d edfresched, resume\n", m->machno);
.
641c
edfrelease(t);
.
638c
DPRINT("%d edfresched, rerelease\n", m->machno);
.
619c
DPRINT("%d edfresched, resume\n", m->machno);
.
614c
edfrelease(t);
.
609c
DPRINT("%d edfresched, rerelease\n", m->machno);
.
592c
edfrelease(t);
.
567c
DPRINT("%d edfresched, nothing runnable\n", m->machno);
.
556c
DPRINT("%d edfresched, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
.
552c
edfresched(Task *t)
.
546c
edfresched(t);
.
526c
DPRINT("%d edfready, %s, %d\n", m->machno, edfstatename[p->task->state], p->task->runq.n);
.
521c
edfready(Proc *p)
.
492c
DPRINT("%d edfbury\n", m->machno);
.
487c
edfbury(Proc *p)
.
476c
deadline(nil, SSlice);
.
472c
deadline(up, SSlice);
.
445,447c
timerdel(&deadlinetimer[m->machno]);
deadlinetimer[m->machno].when = 0;
.
428c
edfrelease(t);
.
415,417c
timerdel(&releasetimer[m->machno]);
releasetimer[m->machno].when = 0;
.
365c
DPRINT("%d edfexpel, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
.
359c
edfexpel(Task *t)
.
347,349c
edfresched(t);
.
345c
edfrelease(t);
.
339a
if (deadlinetimer[m->machno].when)
timerdel(&deadlinetimer[m->machno]);
deadlinetimer[m->machno].when = t->d;
timeradd(&deadlinetimer[m->machno]);
.
327c
DPRINT("%d edfadmitting self\n", m->machno);
.
321c
DPRINT("%d edfadmit, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
.
316c
if (err = edftestschedulability(t)){
.
296c
edfadmit(Task *t)
.
291c
deadline(p, SYield);
.
287c
DPRINT("%d edfdeadline\n", m->machno);
.
285c
edfdeadline(Proc *p)
.
281c
edfresched(t);
.
273,276c
if (deadlinetimer[m->machno].when){
timerdel(&deadlinetimer[m->machno]);
deadlinetimer[m->machno].when = 0;
.
269c
iprint("deadline, %s, %d\n", edfstatename[p->task->state], p->task->runq.n);
.
259c
DPRINT("%d deadline, %s, %d\n", m->machno, edfstatename[p->task->state], p->task->runq.n);
.
254c
deadline(Proc *p, SEvent why)
.
239c
DPRINT("%d edfblock, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
.
226c
edfblock(Proc *p)
.
216,222c
if (releasetimer[m->machno].when)
timerdel(&releasetimer[m->machno]);
releasetimer[m->machno].when = t->r;
if (releasetimer[m->machno].when <= now)
releasetimer[m->machno].when = now;
timeradd(&releasetimer[m->machno]);
.
196c
DPRINT("%d edfqremove, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
.
156c
DPRINT("%d edfenqueue, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
.
117c
DPRINT("%d edfpush, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
.
104c
edfanyready(void)
.
87,92c
for (i = 0; i < conf.nmach; i++){
deadlinetimer[i].f = edfdeadlineintr;
deadlinetimer[i].a = &deadlinetimer[i];
deadlinetimer[i].when = 0;
releasetimer[i].f = edfreleaseintr;
releasetimer[i].a = &releasetimer[i];
releasetimer[i].when = 0;
}
.
78a
int i;
.
77c
edfinit(void)
.
74a
static char * edftestschedulability(Task *thetask);
.
72d
69c
static void edfresched(Task *t);
.
61,63d
42c
int edfstateupdate;
.
29,30c
static Timer deadlinetimer[MAXMACH]; /* Time of next deadline */
static Timer releasetimer[MAXMACH]; /* Time of next release */
.
15c
char *edfstatename[] = {
.
## diffname port/edf.c 2002/0411
## diff -e /n/emeliedump/2002/0410/sys/src/9/port/edf.c /n/emeliedump/2002/0411/sys/src/9/port/edf.c
688a
if (edfstack[m->machno].head == nil && qreleased.head== nil){
// quick way out
nilcount++;
return nil;
}
.
107,110c
return edfstack[m->machno].head || qreleased.head;
.
## diffname port/edf.c 2002/0420
## diff -e /n/emeliedump/2002/0411/sys/src/9/port/edf.c /n/emeliedump/2002/0420/sys/src/9/port/edf.c
467a
if (t->S > 0LL)
misseddeadlines++;
.
42a
int misseddeadlines;
.
## diffname port/edf.c 2002/0503
## diff -e /n/emeliedump/2002/0420/sys/src/9/port/edf.c /n/emeliedump/2002/0503/sys/src/9/port/edf.c
743a
t->periods++;
.
733a
t->periods++;
.
731d
470a
}
.
469c
if (t->d <= now){
t->missed++;
.
459a
t->total += used;
.
332a
t->periods++;
.
274a
used = now - t->scheduled;
t->S -= used;
t->scheduled = now;
t->total += used;
t->aged = (t->aged*31 + t->C - t->S) >> 5;
.
254a
Ticks used;
.
## diffname port/edf.c 2002/0704
## diff -e /n/emeliedump/2002/0503/sys/src/9/port/edf.c /n/emeliedump/2002/0704/sys/src/9/port/edf.c
963a
Edfinterface realedf = {
.isedf = isedf,
.edfbury = edfbury,
.edfanyready = edfanyready,
.edfready = edfready,
.edfrunproc = edfrunproc,
.edfblock = edfblock,
.edfinit = edfinit,
.edfexpel = edfexpel,
.edfadmit = edfadmit,
.edfdeadline = edfdeadline,
};
.
688c
static Proc *
.
674c
static void
.
529c
static void
.
495c
static void
.
364c
static void
.
298c
static char *
.
287c
static void
.
223c
static void
.
105c
static int
.
99c
static int
.
74c
static void
.
51a
static void edfrelease(Task *t);
.
## diffname port/edf.c 2002/0831
## diff -e /n/emeliedump/2002/0704/sys/src/9/port/edf.c /n/emeliedump/2002/0831/sys/src/9/port/edf.c
922c
steps, ticks2time(ticks), t->taskno,
.
911c
steps, ticks2time(ticks), t->taskno,
.
896c
pprint("\tInit: enqueue task %lud\n", t->taskno);
.
890c
for (l = tasks.next; l; l = l->next){
t = l->i;
assert(t);
.
883a
List *l;
.
843c
for (lt = tasks.next; lt ; lt = lt->next){
t = lt->i;
assert(t);
.
840a
List *lt;
.
830,832c
for (lr = t->res.next; lr; lr = lr->next){
r = lr->i;
assert(r);
if (r->testDelta < t->testDelta)
t->testDelta = r->testDelta;
}
.
826c
for (lt = tasks.next; lt ; lt = lt->next){
t = lt->i;
assert(t);
.
822,824c
for (lt = r->tasks.next; lt; lt = lt->next){
t = lt->i;
assert(t);
if (t->D < r->testDelta)
r->testDelta = t->D;
}
.
818,820c
for (lr = resources.next; lr; lr = lr->next){
r = lr->i;
assert(r);
.
815,816c
Resource *r;
Task *t;
List *lr, *lt;
.
806,808c
for (lr = t->res.next; lr; lr = lr->next){
r = lr->i;
assert(r);
if (r->Delta < t->Delta)
t->Delta = r->Delta;
}
.
802c
for (lt = tasks.next; lt ; lt = lt->next){
t = lt->i;
assert(t);
.
798,800c
for (lt = r->tasks.next; lt; lt = lt->next){
t = lt->i;
assert(t);
if (t->D < r->Delta)
r->Delta = t->D;
}
.
794,796c
for (lr = resources.next; lr; lr = lr->next){
r = lr->i;
assert(r);
.
791,792c
Resource *r;
Task *t;
List *lr, *lt;
.
567c
if (t->procs.n == 0){
.
521c
if (t->procs.n == 0){
.
512,516c
delist(&t->procs, p);
.
500d
411d
379d
370c
/* Called with edfschedlock held */
.
361c
qlock(&edfschedlock);
.
324a
qunlock(&edfschedlock);
.
321d
319d
303a
/* Called with edfschedlock held */
.
38,41c
Head tasks;
Head resources;
.
34a
/* Edfschedlock protects modification of sched params, including resources */
.
## diffname port/edf.c 2002/0912
## diff -e /n/emeliedump/2002/0831/sys/src/9/port/edf.c /n/emeliedump/2002/0912/sys/src/9/port/edf.c
736d
## diffname port/edf.c 2002/0927
## diff -e /n/emeliedump/2002/0912/sys/src/9/port/edf.c /n/emeliedump/2002/0927/sys/src/9/port/edf.c
991a
.resacquire = resacquire,
.resrelease = resrelease,
.
974,978c
c = t->curcsn;
assert(c);
t->curcsn = c->p;
now = fastticks(nil);
used = now - t->scheduled;
t->scheduled = now;
t->total += used;
t->S -= used;
c->S -= used;
if (now + t->S > t->d)
when = t->d;
else
when = now + t->S;
if (t->curcsn){
t->curcsn->S -= c->S; /* the sins of the fathers shall be visited upon the children */
t->Delta = t->curcsn->Delta;
if (when > now + t->curcsn->S)
when = now + t->curcsn->S;
}else
t->Delta = Infinity;
c->S = 0LL; /* don't allow reuse */
if (deadlinetimer[m->machno].when)
timerdel(&deadlinetimer[m->machno]);
deadlinetimer[m->machno].when = when;
timeradd(&deadlinetimer[m->machno]);
qunlock(&edfschedlock);
sched(); /* reschedule */
qlock(&edfschedlock);
.
968,972c
Ticks now, when, used;
CSN *c;
.
965,966c
static void
resrelease(Task *t)
.
959,962c
now = fastticks(nil);
used = now - t->scheduled;
t->scheduled = now;
t->total += used;
t->S -= used;
if (t->curcsn)
t->curcsn->S -= used;
when = now + c->S;
if (when < deadlinetimer[m->machno].when){
timerdel(&deadlinetimer[m->machno]);
deadlinetimer[m->machno].when = when;
timeradd(&deadlinetimer[m->machno]);
}
t->Delta = c->Delta;
t->curcsn = c;
/* priority is going up, no need to reschedule */
.
956,957c
Ticks now, when, used;
.
953,954c
static void
resacquire(Task *t, CSN *c)
.
940a
}
.
939c
if(ticks && G <= ticks){
if (thetask && (thetask->flags & Verbose))
pprint("task %d schedulable: G=%T <= ticks=%T\n",
thetask->taskno, ticks2time(G), ticks2time(ticks));
.
936c
pprint("\tStep %3d, Ticks %T, task %d, release, G %T, C%T\n",
.
929a
}
.
928c
if (H+Cb>ticks){
if (thetask && (thetask->flags & Verbose))
pprint("task %d not schedulable: H=%T + Cb=%T > ticks=%T\n",
thetask->taskno, ticks2time(H), ticks2time(Cb), ticks2time(ticks));
.
925c
pprint("\tStep %3d, Ticks %T, task %d, deadline, H += %T → %T, Cb = %T\n",
.
923c
Cb = blockcost(ticks, t, thetask);
.
911c
pprint("\tInit: enqueue task %d\n", t->taskno);
.
901c
pprint("schedulability test for task %d\n", thetask->taskno);
.
864,865d
860a
DEBUG("Cb = %T\n", ticks2time(Cb));
.
853,859c
/* for each resource in task t, find all CSNs that refer to the
* resource. If their Δ <= ticks < D and c->C > current CB
* Cb = c->C
*/
DEBUG("blockcost task %d: ", task->taskno);
for (c = (CSN*)task->csns.next; c; c = (CSN*)c->next){
r = c->i;
assert(r);
DEBUG("%s ", r->name);
Cbt = Cb;
R = 1; /* R == 1: resource is only used in read-only mode */
for (l = tasks.next; l; l = l->next){
t = l->i;
if (t->state <= EdfExpelled && t != thetask)
continue; /* csn belongs to an irrelevant task */
for (lc = (CSN*)t->csns.next; lc; lc = (CSN*)lc->next){
if (lc->i != r)
continue; /* wrong resource */
if (lc->R == 0)
R = 0; /* Resource is used in exclusive mode */
DEBUG("(%T≤%T<%T: %T) ",
ticks2time(lc->testDelta), ticks2time(ticks), ticks2time(t->D),
ticks2time(lc->C));
if (lc->testDelta <= ticks && ticks < t->D && Cbt < lc->C)
Cbt = lc->C;
}
}
if (R == 0){
DEBUG("%T, ", ticks2time(Cbt));
Cb = Cbt;
}
DEBUG("ro, ");
.
849,850d
847a
Ticks Cb, Cbt;
List *l;
Resource *r;
CSN *c, *lc;
int R;
.
846c
blockcost(Ticks ticks, Task *task, Task *thetask)
.
840a
DEBUG("Task %d Resource %s: tΔ = %T\n",
t->taskno, r->name, ticks2time(r->testDelta));
.
839c
c->testDelta = r->testDelta;
if (c->p && c->p->testDelta < c->testDelta)
c->testDelta = c->p->testDelta;
if (c->C == t->C && r->testDelta < t->testDelta)
.
835,837c
t->testDelta = Infinity;
for (c = (CSN*)t->csns.next; c; c = (CSN*)c->next){
r = c->i;
.
830,831c
/* Enumerate the critical sections */
for (l = tasks.next; l ; l = l->next){
t = l->i;
.
828a
if (R)
r->testDelta = Infinity; /* Read-only resource, no exclusion */
DEBUG("tΔ = %T\n", ticks2time(r->testDelta));
.
827a
DEBUG("%d→%T ", t->taskno, ticks2time(t->D));
}
if (lt->R == 0){
DEBUG("%d→X ", t->taskno);
R = 0;
}
.
826c
if (t->D < r->testDelta){
.
822,823c
DEBUG("Resource %s: ", r->name);
r->testDelta = Infinity;
R = 1;
for (lt = (TaskLink*)r->tasks.next; lt; lt = (TaskLink*)lt->next){
.
817c
int R;
List *lr, *l;
TaskLink *lt;
CSN *c;
.
806c
c->Delta = r->Delta;
if (c->p && c->p->Delta < c->Delta)
c->Delta = c->p->Delta;
if (c->C == t->C && r->Delta < t->Delta)
.
802,804c
t->Delta = Infinity;
for (c = (CSN*)t->csns.next; c; c = (CSN*)c->next){
r = c->i;
.
800c
if (t->state <= EdfExpelled)
.
797,798c
/* Enumerate the critical sections */
for (l = tasks.next; l ; l = l->next){
t = l->i;
.
795a
if (R)
r->Delta = Infinity; /* Read-only resource, no exclusion */
.
794a
}
if (lt->R == 0){
R = 0;
}
.
793c
if (t->D < r->Delta){
.
789,790c
r->Delta = Infinity;
R = 1;
for (lt = (TaskLink*)r->tasks.next; lt; lt = (TaskLink*)lt->next){
.
784c
int R;
List *lr, *l;
TaskLink *lt;
CSN *c;
.
675a
for (c = (CSN*)t->csns.next; c; c = (CSN*)c->next){
DEBUG("release csn: C=%T\n", ticks2time(c->C));
c->S = c->C;
}
.
669a
CSN *c;
.
488a
if (noted)
postnote(up, 1, buf, NUser);
.
479a
.
472,473c
if (t->d <= now || t->S == 0LL || t->curcsn == 0LL){
.
470c
if (!noted){
noted++;
snprint(buf, sizeof buf, "sys: deadline miss: runtime");
}
}else
.
468c
if (t->curcsn){
if (t->curcsn->S <= used){
t->curcsn->S = 0LL;
r = t->curcsn->i;
noted++;
snprint(buf, sizeof buf, "sys: deadline miss: resource %s", r->name);
}else
t->curcsn->S -= used;
}
if (t->S <= used){
.
456c
// for non-real-time processes.
noted = 0;
.
451c
if(panicking || active.exiting)
.
444a
Resource *r;
char buf[128];
int noted;
extern int panicking;
.
422c
if(panicking || active.exiting)
.
415a
extern int panicking;
.
360d
341a
for (c = (CSN*)t->csns.next; c; c = (CSN*)c->next){
DEBUG("admit csn: C=%T\n", ticks2time(c->C));
c->S = c->C;
}
.
323d
318a
resourcetimes(t, &t->csns);
DEBUG("task %d: T %T, C %T, D %T, tΔ %T\n",
t->taskno, ticks2time(t->T), ticks2time(t->C),
ticks2time(t->D), ticks2time(t->testDelta));
p = seprintresources(csndump, csndump+sizeof csndump);
seprintcsn(p, csndump+sizeof csndump, &t->csns);
DEBUG("%s\n", csndump);
.
301c
char *err, *p;
static char csndump[512];
CSN *c;
.
86d
64a
static Task *qschedulability;
.
33d
8,9c
#include "../port/realtime.h"
.
## diffname port/edf.c 2002/1001
## diff -e /n/emeliedump/2002/0927/sys/src/9/port/edf.c /n/emeliedump/2002/1001/sys/src/9/port/edf.c
1115a
if(devrt) devrt(t, now, SResrel);
.
1085a
if(devrt) devrt(t, now, SResacq);
.
488a
resrelease(t);
.
465,466c
if (timer)
timer->when = 0;
.
452c
edfdeadlineintr(Ureg*, Timer *timer)
.
72c
static char * edftestschedulability(Task*);
static void resrelease(Task*);
.
69,70c
static void testdelta(Task*);
static void edfreleaseintr(Ureg*, Timer*);
.
67c
static void edfresched(Task*);
.
## diffname port/edf.c 2002/1119
## diff -e /n/emeliedump/2002/1001/sys/src/9/port/edf.c /n/emeliedump/2002/1119/sys/src/9/port/edf.c
8c
#include "realtime.h"
#include "../port/edf.h"
.
## diffname port/edf.c 2002/1217
## diff -e /n/emeliedump/2002/1119/sys/src/9/port/edf.c /n/emeliedump/2002/1217/sys/src/9/port/edf.c
776c
assert(nt->runq.n >= 1 || (up && up->task == nt));
.
740a
.
## diffname port/edf.c 2002/1218
## diff -e /n/emeliedump/2002/1217/sys/src/9/port/edf.c /n/emeliedump/2002/1218/sys/src/9/port/edf.c
1122,1123d
1084d
809,814c
if(deadlinetimer[m->machno].when == when){
iunlock(&edflock);
return p;
.
480a
assert(t->state == EdfRunning);
.
359,360d
216,217d
## diffname port/edf.c 2002/1219
## diff -e /n/emeliedump/2002/1218/sys/src/9/port/edf.c /n/emeliedump/2002/1219/sys/src/9/port/edf.c
1078c
if (deadlinetimer[m->machno].when == 0 || when < deadlinetimer[m->machno].when){
.
474,475d
468a
now = fastticks(nil);
.
463,465d
450c
edfdeadlineintr(Ureg*, Timer *)
.
437a
ilock(&edflock);
.
436d
430,432d
## diffname port/edf.c 2003/0201
## diff -e /n/emeliedump/2002/1219/sys/src/9/port/edf.c /n/emeliedump/2003/0201/sys/src/9/port/edf.c
517c
postnote(up, 0, buf, NUser);
.
|