| plan 9 kernel history: overview | file list | diff list |
2002/0316/port/edf.c (diff list | history)
| 2002/0315/sys/src/9/port/edf.c:5,11 – 2002/0316/sys/src/9/port/edf.c:5,11 (short | long | prev | next) | ||
| 2002/0315 | #include "dat.h" #include "fns.h" #include "../port/error.h" | |
| 2002/0316 | #include "../port/devrealtime.h" | |
| 2002/0315 | #include "../port/edf.h" /* debugging */ | |
| 2002/0315/sys/src/9/port/edf.c:68,74 – 2002/0316/sys/src/9/port/edf.c:68,74 | ||
| 2002/0315 | /* Running/Preempted EDF tasks, head running, one stack per processor */ Taskq edfstack[MAXMACH]; | |
| 2002/0316 | void (*devrt)(Task*, Ticks, int); | |
| 2002/0315 | static void edf_intr(Ureg*, Cycintr*); static void edf_resched(Task *t); | |
| 2002/0315/sys/src/9/port/edf.c:115,130 – 2002/0316/sys/src/9/port/edf.c:115,130 | ||
| 2002/0315 | { Taskq *q; | |
| 2002/0316 | DENTER("%.*s%d edfpush, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n); | |
| 2002/0315 | q = edfstack + m->machno; assert(t->runq.n || (up && up->task == t)); if (q->head){ assert(q->head->state == EdfRunning); q->head->state = EdfPreempted; | |
| 2002/0316 | if(devrt) devrt(q->head, now, SPreempt); | |
| 2002/0315 | } t->rnext = q->head; | |
| 2002/0316 | if(devrt) devrt(t, now, SRun); | |
| 2002/0315 | q->head = t; DLEAVE; } | |
| 2002/0315/sys/src/9/port/edf.c:135,141 – 2002/0316/sys/src/9/port/edf.c:135,141 | ||
| 2002/0315 | Task *t; Taskq *q; | |
| 2002/0316 | DENTER("%.*s%d edfpop\n", ind, tabs, m->machno); | |
| 2002/0315 | q = edfstack + m->machno; if (t = q->head){ assert(t->state == EdfRunning); | |
| 2002/0315/sys/src/9/port/edf.c:144,150 – 2002/0316/sys/src/9/port/edf.c:144,150 | ||
| 2002/0315 | if (q->head){ assert(q->head->state == EdfPreempted); q->head->state = EdfRunning; | |
| 2002/0316 | if(devrt) devrt(q->head, now, SRun); | |
| 2002/0315 | } } DLEAVE; | |
| 2002/0315/sys/src/9/port/edf.c:157,163 – 2002/0316/sys/src/9/port/edf.c:157,163 | ||
| 2002/0315 | Task *tt, **ttp; ilock(q); | |
| 2002/0316 | DENTER("%.*s%d edfenqueue, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n); | |
| 2002/0315 | t->rnext = nil; if (q->head == nil) { q->head = t; | |
| 2002/0315/sys/src/9/port/edf.c:188,194 – 2002/0316/sys/src/9/port/edf.c:188,194 | ||
| 2002/0315 | { Task *t; | |
| 2002/0316 | DENTER("%.*s%d edfdequeue\n", ind, tabs, m->machno); | |
| 2002/0315 | ilock(q); if (t = q->head){ q->head = t->rnext; | |
| 2002/0315/sys/src/9/port/edf.c:205,211 – 2002/0316/sys/src/9/port/edf.c:205,211 | ||
| 2002/0315 | Task **tp; ilock(q); | |
| 2002/0316 | DENTER("%.*s%d edfqremove, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n); | |
| 2002/0315 | for (tp = &q->head; *tp; tp = &(*tp)->rnext){ if (*tp == t){ *tp = t->rnext; | |
| 2002/0315/sys/src/9/port/edf.c:226,232 – 2002/0316/sys/src/9/port/edf.c:226,232 | ||
| 2002/0315 | /* The current proc has blocked */ ilock(&edflock); t = p->task; | |
| 2002/0316 | DENTER("%.*s%d edf_block, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n); | |
| 2002/0315 | assert(t); assert(t->state == EdfRunning); | |
| 2002/0315/sys/src/9/port/edf.c:239,245 – 2002/0316/sys/src/9/port/edf.c:239,245 | ||
| 2002/0315 | pt = edfpop(); assert(pt == t); t->state = EdfBlocked; | |
| 2002/0316 | if(devrt) devrt(t, now, SBlock); | |
| 2002/0315 | DLEAVE; iunlock(&edflock); } | |
| 2002/0315/sys/src/9/port/edf.c:250,256 – 2002/0316/sys/src/9/port/edf.c:250,256 | ||
| 2002/0315 | Task *t, *nt; /* Task has reached its deadline, lock must be held */ | |
| 2002/0316 | DENTER("%.*s%d edfdeadline, %s, %d\n", ind, tabs, m->machno, edf_statename[p->task->state], p->task->runq.n); | |
| 2002/0315 | SET(nt); if (p){ nt = p->task; | |
| 2002/0315/sys/src/9/port/edf.c:260,266 – 2002/0316/sys/src/9/port/edf.c:260,266 | ||
| 2002/0315 | t = edfpop(); if(p != nil && nt != t){ | |
| 2002/0316 | DPRINT("%.*s%d edfdeadline, %s, %d\n", ind, tabs, m->machno, edf_statename[p->task->state], p->task->runq.n); | |
| 2002/0315 | iunlock(&edflock); assert(0 && p == nil || nt == t); } | |
| 2002/0315/sys/src/9/port/edf.c:267,273 – 2002/0316/sys/src/9/port/edf.c:267,273 | ||
| 2002/0315 | t->d = now; t->state = EdfDeadline; | |
| 2002/0316 | if(devrt) devrt(t, now, why); | |
| 2002/0315 | edf_resched(t); DLEAVE; } | |
| 2002/0315/sys/src/9/port/edf.c:275,281 – 2002/0316/sys/src/9/port/edf.c:275,281 | ||
| 2002/0315 | void edf_deadline(Proc *p) { | |
| 2002/0316 | DENTER("%.*s%d edf_deadline\n", ind, tabs, m->machno); | |
| 2002/0315 | /* Task has reached its deadline */ ilock(&edflock); now = fastticks(nil); | |
| 2002/0315/sys/src/9/port/edf.c:291,296 – 2002/0316/sys/src/9/port/edf.c:291,309 | ||
| 2002/0315 | if (t->state != EdfExpelled) return "task state"; /* should never happen */ | |
| 2002/0316 | /* 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"; | |
| 2002/0315 | qlock(&edfschedlock); if (err = edf_testschedulability(t)){ qunlock(&edfschedlock); | |
| 2002/0315/sys/src/9/port/edf.c:297,317 – 2002/0316/sys/src/9/port/edf.c:310,331 | ||
| 2002/0315 | return err; } ilock(&edflock); | |
| 2002/0316 | DENTER("%.*s%d edf_admit, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n); | |
| 2002/0315 | now = fastticks(nil); t->state = EdfAdmitted; | |
| 2002/0316 | if(devrt) devrt(t, t->d, SAdmit); | |
| 2002/0315 | if (up->task == t){ | |
| 2002/0316 | DPRINT("%.*s%d edf_admitting self\n", ind, tabs, m->machno); | |
| 2002/0315 | /* Admitting self, fake reaching deadline */ t->r = now; t->t = now + t->T; t->d = now + t->D; | |
| 2002/0316 | if(devrt) devrt(t, t->d, SDeadline); | |
| 2002/0315 | t->S = t->C; t->scheduled = now; t->state = EdfRunning; | |
| 2002/0316 | if(devrt) devrt(t, now, SRun); | |
| 2002/0315 | setΔ(); assert(t->runq.n > 0 || (up && up->task == t)); edfpush(t); | |
| 2002/0315/sys/src/9/port/edf.c:342,348 – 2002/0316/sys/src/9/port/edf.c:356,362 | ||
| 2002/0315 | qlock(&edfschedlock); ilock(&edflock); | |
| 2002/0316 | DENTER("%.*s%d edf_expel, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n); | |
| 2002/0315 | now = fastticks(nil); switch(t->state){ case EdfUnused: | |
| 2002/0315/sys/src/9/port/edf.c:378,384 – 2002/0316/sys/src/9/port/edf.c:392,398 | ||
| 2002/0315 | break; } t->state = EdfExpelled; | |
| 2002/0316 | if(devrt) devrt(t, now, SExpel); | |
| 2002/0315 | setΔ(); DLEAVE; iunlock(&edflock); | |
| 2002/0315/sys/src/9/port/edf.c:432,438 – 2002/0316/sys/src/9/port/edf.c:446,452 | ||
| 2002/0315 | Ticks ticks; Task *t; | |
| 2002/0316 | DENTER("%.*s%d edf_setclock\n", ind, tabs, m->machno); | |
| 2002/0315 | ticks = ~0ULL; if ((t = qwaitrelease.head) && t->r < ticks) ticks = t->r; | |
| 2002/0315/sys/src/9/port/edf.c:447,465 – 2002/0316/sys/src/9/port/edf.c:461,479 | ||
| 2002/0315 | return; } if (schedpoint.when){ | |
| 2002/0316 | DPRINT("%.*s%d cycintrdel %T\n", ind, tabs, m->machno, ticks2time(schedpoint.when)); | |
| 2002/0315 | cycintrdel(&schedpoint); schedpoint.when = 0; } if (ticks <= now){ | |
| 2002/0316 | DPRINT("%.*s%d edf_timer: %T too late\n", ind, tabs, m->machno, ticks2time(now-ticks)); | |
| 2002/0315 | ticks = now; } if (ticks != ~0ULL) { | |
| 2002/0316 | DPRINT("%.*s%d program timer in %T\n", ind, tabs, m->machno, ticks2time(ticks-now)); | |
| 2002/0315 | schedpoint.when = ticks; cycintradd(&schedpoint); | |
| 2002/0316 | DPRINT("%.*s%d cycintradd %T\n", ind, tabs, m->machno, ticks2time(schedpoint.when-now)); | |
| 2002/0315 | } clockintrsched(); DLEAVE; | |
| 2002/0315/sys/src/9/port/edf.c:469,475 – 2002/0316/sys/src/9/port/edf.c:483,489 | ||
| 2002/0315 | edf_intr(Ureg *, Cycintr *cy) { | |
| 2002/0316 | DENTER("%.*s%d edf_intr\n", ind, tabs, m->machno); | |
| 2002/0315 | /* Timer interrupt * Timed events are: * 1. release a task (look in qwaitrelease) | |
| 2002/0315/sys/src/9/port/edf.c:497,509 – 2002/0316/sys/src/9/port/edf.c:511,523 | ||
| 2002/0315 | Task *t; Proc **pp; | |
| 2002/0316 | DPRINT("%.*s%d edf_bury\n", ind, tabs, m->machno); | |
| 2002/0315 | ilock(&edflock); now = fastticks(nil); if ((t = p->task) == nil){ /* race condition? */ iunlock(&edflock); | |
| 2002/0316 | DPRINT("%.*s%d edf bury race, pid %lud\n", ind, tabs, m->machno, p->pid); | |
| 2002/0315 | return; } assert(edfstack[m->machno].head == t); | |
| 2002/0315/sys/src/9/port/edf.c:520,526 – 2002/0316/sys/src/9/port/edf.c:534,540 | ||
| 2002/0315 | assert(t->runq.head == nil); t->state = EdfIdle; } | |
| 2002/0316 | if(devrt) devrt(t, now, SBlock); | |
| 2002/0315 | p->task = nil; iunlock(&edflock); } | |
| 2002/0315/sys/src/9/port/edf.c:531,541 – 2002/0316/sys/src/9/port/edf.c:545,555 | ||
| 2002/0315 | Task *t; ilock(&edflock); | |
| 2002/0316 | DENTER("%.*s%d edf_ready, %s, %d\n", ind, tabs, m->machno, edf_statename[p->task->state], p->task->runq.n); | |
| 2002/0315 | if ((t = p->task) == nil){ /* Must be a race */ iunlock(&edflock); | |
| 2002/0316 | DPRINT("%.*s%d edf ready race, pid %lud\n", ind, tabs, m->machno, p->pid); | |
| 2002/0315 | return; } p->rnext = 0; | |
| 2002/0315/sys/src/9/port/edf.c:562,573 – 2002/0316/sys/src/9/port/edf.c:576,587 | ||
| 2002/0315 | { Task *xt; | |
| 2002/0316 | DENTER("%.*s%d edf_resched, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n); | |
| 2002/0315 | if (t->nproc == 0){ /* No member processes */ if (t->state > EdfIdle){ t->state = EdfIdle; | |
| 2002/0316 | if(devrt) devrt(t, now, SBlock); | |
| 2002/0315 | } DLEAVE; return; | |
| 2002/0315/sys/src/9/port/edf.c:574,586 – 2002/0316/sys/src/9/port/edf.c:588,600 | ||
| 2002/0315 | } if (t->runq.n == 0 && (up == nil || up->task != t)){ /* Member processes but none runnable */ | |
| 2002/0316 | DPRINT("%.*s%d edf_resched, nothing runnable\n", ind, tabs, m->machno); | |
| 2002/0315 | if (t->state == EdfRunning) edfpop(); if (t->state >= EdfIdle && t->state != EdfBlocked){ t->state = EdfBlocked; | |
| 2002/0316 | if(devrt) devrt(t, now, SBlock); | |
| 2002/0315 | } DLEAVE; return; | |
| 2002/0315/sys/src/9/port/edf.c:590,596 – 2002/0316/sys/src/9/port/edf.c:604,610 | ||
| 2002/0315 | switch (t->state){ case EdfUnused: | |
| 2002/0316 | iprint("%.*s%d attempt to schedule unused task\n", ind, tabs, m->machno); | |
| 2002/0315 | case EdfExpelled: DLEAVE; return; /* Not admitted */ | |
| 2002/0315/sys/src/9/port/edf.c:619,625 – 2002/0316/sys/src/9/port/edf.c:633,639 | ||
| 2002/0315 | case EdfRunning: if (t->r <= now){ if (t->t < now){ | |
| 2002/0316 | DPRINT("%.*s%d edf_resched, rerelease\n", ind, tabs, m->machno); | |
| 2002/0315 | /* Period passed, rerelease */ t->r = now; xt = edfpop(); | |
| 2002/0315/sys/src/9/port/edf.c:630,636 – 2002/0316/sys/src/9/port/edf.c:644,650 | ||
| 2002/0315 | } if (now < t->d){ if (t->S > 0){ | |
| 2002/0316 | DPRINT("%.*s%d edf_resched, resume\n", ind, tabs, m->machno); | |
| 2002/0315 | /* Running, not yet at deadline, leave it */ DLEAVE; return; | |
| 2002/0315/sys/src/9/port/edf.c:640,646 – 2002/0316/sys/src/9/port/edf.c:654,660 | ||
| 2002/0315 | /* Released, but deadline is past, release at t->t */ t->r = t->t; } | |
| 2002/0316 | DPRINT("%.*s%d edf_resched, schedule release\n", ind, tabs, m->machno); | |
| 2002/0315 | xt = edfpop(); assert(xt == t); edfenqueue(&qwaitrelease, t); | |
| 2002/0315/sys/src/9/port/edf.c:651,657 – 2002/0316/sys/src/9/port/edf.c:665,671 | ||
| 2002/0315 | case EdfDeadline: if (t->r <= now){ if (t->t < now){ | |
| 2002/0316 | DPRINT("%.*s%d edf_resched, rerelease\n", ind, tabs, m->machno); | |
| 2002/0315 | /* Period passed, rerelease */ t->r = now; edf_release(t); | |
| 2002/0315/sys/src/9/port/edf.c:660,670 – 2002/0316/sys/src/9/port/edf.c:674,684 | ||
| 2002/0315 | } if (now < t->d && (t->flags & Useblocking) == 0){ if (t->S > 0){ | |
| 2002/0316 | DPRINT("%.*s%d edf_resched, resume\n", ind, tabs, m->machno); | |
| 2002/0315 | /* Released, not yet at deadline, release (again) */ t->state = EdfReleased; edfenqueue(&qreleased, t); | |
| 2002/0316 | if(devrt) devrt(t, now, SResume); | |
| 2002/0315 | DLEAVE; return; }else | |
| 2002/0315/sys/src/9/port/edf.c:673,679 – 2002/0316/sys/src/9/port/edf.c:687,693 | ||
| 2002/0315 | /* Released, but deadline is past, release at t->t */ t->r = t->t; } | |
| 2002/0316 | DPRINT("%.*s%d edf_resched, schedule release\n", ind, tabs, m->machno); | |
| 2002/0315 | edfenqueue(&qwaitrelease, t); t->state = EdfAwaitrelease; edf_setclock(); | |
| 2002/0315/sys/src/9/port/edf.c:685,699 – 2002/0316/sys/src/9/port/edf.c:699,713 | ||
| 2002/0315 | void edf_release(Task *t) { | |
| 2002/0316 | DENTER("%.*s%d edf_release, %s, %d\n", ind, tabs, m->machno, edf_statename[t->state], t->runq.n); | |
| 2002/0315 | assert(t->runq.n > 0 || (up && up->task == t)); t->t = t->r + t->T; t->d = t->r + t->D; | |
| 2002/0316 | if(devrt) devrt(t, t->d, SDeadline); | |
| 2002/0315 | t->S = t->C; t->state = EdfReleased; edfenqueue(&qreleased, t); | |
| 2002/0316 | if(devrt) devrt(t, now, SRelease); | |
| 2002/0315 | edf_setclock(); DLEAVE; } | |
| 2002/0315/sys/src/9/port/edf.c:727,733 – 2002/0316/sys/src/9/port/edf.c:741,747 | ||
| 2002/0315 | DENTER("edf_runproc %lud\n", nilcount); if (nt && (t == nil || (nt->D < t->Δ && nt->d < t->d))){ /* released task is better than current */ | |
| 2002/0316 | DPRINT("%.*s%d edf_runproc: released\n", ind, tabs, m->machno); | |
| 2002/0315 | edfdequeue(&qreleased); assert(nt->runq.n >= 1); edfpush(nt); | |
| 2002/0315/sys/src/9/port/edf.c:735,741 – 2002/0316/sys/src/9/port/edf.c:749,755 | ||
| 2002/0315 | t = nt; t->scheduled = now; }else{ | |
| 2002/0316 | DPRINT("%.*s%d edf_runproc: current\n", ind, tabs, m->machno); | |
| 2002/0315 | } assert (t->runq.n); | |