edf.c 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130
  1. /* EDF scheduling */
  2. #include "u.h"
  3. #include "../port/lib.h"
  4. #include "mem.h"
  5. #include "dat.h"
  6. #include "fns.h"
  7. #include "../port/error.h"
  8. #include "realtime.h"
  9. #include "../port/edf.h"
  10. /* debugging */
  11. int edfprint = 0;
  12. #define DPRINT if(edfprint)iprint
  13. char *edfstatename[] = {
  14. [EdfUnused] = "Unused",
  15. [EdfExpelled] = "Expelled",
  16. [EdfAdmitted] = "Admitted",
  17. [EdfIdle] = "Idle",
  18. [EdfAwaitrelease] = "Awaitrelease",
  19. [EdfReleased] = "Released",
  20. [EdfRunning] = "Running",
  21. [EdfExtra] = "Extra",
  22. [EdfPreempted] = "Preempted",
  23. [EdfBlocked] = "Blocked",
  24. [EdfDeadline] = "Deadline",
  25. };
  26. static Timer deadlinetimer[MAXMACH]; /* Time of next deadline */
  27. static Timer releasetimer[MAXMACH]; /* Time of next release */
  28. static int initialized;
  29. static Ticks now;
  30. /* Edfschedlock protects modification of sched params, including resources */
  31. QLock edfschedlock;
  32. Lock edflock;
  33. Head tasks;
  34. Head resources;
  35. int edfstateupdate;
  36. int misseddeadlines;
  37. enum{
  38. Deadline, /* Invariant for schedulability test: Deadline < Release */
  39. Release,
  40. };
  41. static int earlierrelease(Task *t1, Task *t2) {return t1->r < t2->r;}
  42. static int earlierdeadline(Task *t1, Task *t2) {return t1->d < t2->d;}
  43. static void edfrelease(Task *t);
  44. /* Tasks waiting for release, head earliest release time */
  45. Taskq qwaitrelease = {{0}, nil, earlierrelease};
  46. /* Released tasks waiting to run, head earliest deadline */
  47. Taskq qreleased = {{0}, nil, earlierdeadline};
  48. /* Exhausted EDF tasks, append at end */
  49. Taskq qextratime;
  50. /* Running/Preempted EDF tasks, head running, one stack per processor */
  51. Taskq edfstack[MAXMACH];
  52. static Task *qschedulability;
  53. void (*devrt)(Task*, Ticks, int);
  54. static void edfresched(Task*);
  55. static void setdelta(void);
  56. static void testdelta(Task*);
  57. static void edfreleaseintr(Ureg*, Timer*);
  58. static void edfdeadlineintr(Ureg*, Timer*);
  59. static char * edftestschedulability(Task*);
  60. static void resrelease(Task*);
  61. static void
  62. edfinit(void)
  63. {
  64. int i;
  65. if (initialized)
  66. return;
  67. ilock(&edflock);
  68. if (initialized){
  69. iunlock(&edflock);
  70. return;
  71. }
  72. for (i = 0; i < conf.nmach; i++){
  73. deadlinetimer[i].f = edfdeadlineintr;
  74. deadlinetimer[i].a = &deadlinetimer[i];
  75. deadlinetimer[i].when = 0;
  76. releasetimer[i].f = edfreleaseintr;
  77. releasetimer[i].a = &releasetimer[i];
  78. releasetimer[i].when = 0;
  79. }
  80. initialized = 1;
  81. iunlock(&edflock);
  82. }
  83. static int
  84. isedf(Proc *p)
  85. {
  86. return p && p->task && p->task->state >= EdfIdle;
  87. }
  88. static int
  89. edfanyready(void)
  90. {
  91. return edfstack[m->machno].head || qreleased.head;
  92. }
  93. static void
  94. edfpush(Task *t)
  95. {
  96. Taskq *q;
  97. DPRINT("%d edfpush, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
  98. q = edfstack + m->machno;
  99. assert(t->runq.n || (up && up->task == t));
  100. if (q->head){
  101. assert(q->head->state == EdfRunning);
  102. q->head->state = EdfPreempted;
  103. if(devrt) devrt(q->head, now, SPreempt);
  104. }
  105. t->rnext = q->head;
  106. if(devrt) devrt(t, now, SRun);
  107. q->head = t;
  108. }
  109. static Task*
  110. edfpop(void)
  111. {
  112. Task *t;
  113. Taskq *q;
  114. DPRINT("%d edfpop\n", m->machno);
  115. q = edfstack + m->machno;
  116. if (t = q->head){
  117. assert(t->state == EdfRunning);
  118. q->head = t->rnext;
  119. t->rnext = nil;
  120. if (q->head){
  121. assert(q->head->state == EdfPreempted);
  122. q->head->state = EdfRunning;
  123. if(devrt) devrt(q->head, now, SRun);
  124. }
  125. }
  126. return t;
  127. }
  128. static Task*
  129. edfenqueue(Taskq *q, Task *t)
  130. {
  131. Task *tt, **ttp;
  132. DPRINT("%d edfenqueue, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
  133. t->rnext = nil;
  134. if (q->head == nil) {
  135. q->head = t;
  136. return t;
  137. }
  138. SET(tt);
  139. for (ttp = &q->head; *ttp; ttp = &tt->rnext) {
  140. tt = *ttp;
  141. if (q->before && q->before(t, tt)) {
  142. t->rnext = tt;
  143. *ttp = t;
  144. break;
  145. }
  146. }
  147. if (*ttp == nil)
  148. tt->rnext = t;
  149. if (t != q->head)
  150. t = nil;
  151. return t;
  152. }
  153. static Task*
  154. edfdequeue(Taskq *q)
  155. {
  156. Task *t;
  157. DPRINT("%d edfdequeue\n", m->machno);
  158. if (t = q->head){
  159. q->head = t->rnext;
  160. t->rnext = nil;
  161. }
  162. return t;
  163. }
  164. static Task*
  165. edfqremove(Taskq *q, Task *t)
  166. {
  167. Task **tp;
  168. DPRINT("%d edfqremove, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
  169. for (tp = &q->head; *tp; tp = &(*tp)->rnext){
  170. if (*tp == t){
  171. *tp = t->rnext;
  172. t = (tp == &q->head) ? q->head : nil;
  173. return t;
  174. }
  175. }
  176. return nil;
  177. }
  178. void
  179. edfreleasetimer(void)
  180. {
  181. Task *t;
  182. if ((t = qwaitrelease.head) == nil)
  183. return;
  184. DPRINT("edfreleasetimer clock\n");
  185. releasetimer[m->machno].when = t->r;
  186. if (releasetimer[m->machno].when <= now)
  187. releasetimer[m->machno].when = now;
  188. timeradd(&releasetimer[m->machno]);
  189. }
  190. static void
  191. edfblock(Proc *p)
  192. {
  193. Task *t, *pt;
  194. /* The current proc has blocked */
  195. ilock(&edflock);
  196. t = p->task;
  197. assert(t);
  198. if (t->state != EdfRunning){
  199. /* called by a proc just joining the task */
  200. iunlock(&edflock);
  201. return;
  202. }
  203. DPRINT("%d edfblock, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
  204. if (t->runq.n){
  205. /* There's another runnable proc in the running task, leave task where it is */
  206. iunlock(&edflock);
  207. return;
  208. }
  209. pt = edfpop();
  210. assert(pt == t);
  211. t->state = EdfBlocked;
  212. if(devrt) devrt(t, now, SBlock);
  213. iunlock(&edflock);
  214. }
  215. static void
  216. deadline(Proc *p, SEvent why)
  217. {
  218. Task *t, *nt;
  219. Ticks used;
  220. /* Task has reached its deadline, lock must be held */
  221. DPRINT("%d deadline, %s, %d\n", m->machno, edfstatename[p->task->state], p->task->runq.n);
  222. SET(nt);
  223. if (p){
  224. nt = p->task;
  225. if (nt == nil || nt->state != EdfRunning)
  226. return;
  227. }
  228. t = edfpop();
  229. if(p != nil && nt != t){
  230. iprint("deadline, %s, %d\n", edfstatename[p->task->state], p->task->runq.n);
  231. iunlock(&edflock);
  232. assert(0 && p == nil || nt == t);
  233. }
  234. if (deadlinetimer[m->machno].when){
  235. timerdel(&deadlinetimer[m->machno]);
  236. deadlinetimer[m->machno].when = 0;
  237. }
  238. used = now - t->scheduled;
  239. t->S -= used;
  240. t->scheduled = now;
  241. t->total += used;
  242. t->aged = (t->aged*31 + t->C - t->S) >> 5;
  243. t->d = now;
  244. t->state = EdfDeadline;
  245. if(devrt) devrt(t, now, why);
  246. edfresched(t);
  247. }
  248. static void
  249. edfdeadline(Proc *p)
  250. {
  251. DPRINT("%d edfdeadline\n", m->machno);
  252. /* Task has reached its deadline */
  253. ilock(&edflock);
  254. now = fastticks(nil);
  255. deadline(p, SYield);
  256. iunlock(&edflock);
  257. }
  258. static char *
  259. edfadmit(Task *t)
  260. {
  261. char *err, *p;
  262. static char csndump[512];
  263. CSN *c;
  264. /* Called with edfschedlock held */
  265. if (t->state != EdfExpelled)
  266. return "task state"; /* should never happen */
  267. /* simple sanity checks */
  268. if (t->T == 0)
  269. return "T not set";
  270. if (t->C == 0)
  271. return "C not set";
  272. if (t->D > t->T)
  273. return "D > T";
  274. if (t->D == 0) /* if D is not set, set it to T */
  275. t->D = t->T;
  276. if (t->C > t->D)
  277. return "C > D";
  278. resourcetimes(t, &t->csns);
  279. DEBUG("task %d: T %T, C %T, D %T, tΔ %T\n",
  280. t->taskno, ticks2time(t->T), ticks2time(t->C),
  281. ticks2time(t->D), ticks2time(t->testDelta));
  282. p = seprintresources(csndump, csndump+sizeof csndump);
  283. seprintcsn(p, csndump+sizeof csndump, &t->csns);
  284. DEBUG("%s\n", csndump);
  285. if (err = edftestschedulability(t)){
  286. return err;
  287. }
  288. ilock(&edflock);
  289. DPRINT("%d edfadmit, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
  290. now = fastticks(nil);
  291. t->state = EdfAdmitted;
  292. if(devrt) devrt(t, t->d, SAdmit);
  293. if (up->task == t){
  294. DPRINT("%d edfadmitting self\n", m->machno);
  295. /* Admitting self, fake reaching deadline */
  296. t->r = now;
  297. t->t = now + t->T;
  298. t->d = now + t->D;
  299. if(devrt) devrt(t, t->d, SDeadline);
  300. t->S = t->C;
  301. t->scheduled = now;
  302. t->state = EdfRunning;
  303. t->periods++;
  304. if(devrt) devrt(t, now, SRun);
  305. setdelta();
  306. for (c = (CSN*)t->csns.next; c; c = (CSN*)c->next){
  307. DEBUG("admit csn: C=%T\n", ticks2time(c->C));
  308. c->S = c->C;
  309. }
  310. assert(t->runq.n > 0 || (up && up->task == t));
  311. edfpush(t);
  312. deadlinetimer[m->machno].when = t->d;
  313. timeradd(&deadlinetimer[m->machno]);
  314. }else{
  315. if (t->runq.n){
  316. if (edfstack[m->machno].head == nil){
  317. t->state = EdfAdmitted;
  318. t->r = now;
  319. edfrelease(t);
  320. setdelta();
  321. edfresched(t);
  322. }
  323. }
  324. }
  325. iunlock(&edflock);
  326. return nil;
  327. }
  328. static void
  329. edfexpel(Task *t)
  330. {
  331. Task *tt;
  332. /* Called with edfschedlock held */
  333. ilock(&edflock);
  334. DPRINT("%d edfexpel, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
  335. now = fastticks(nil);
  336. switch(t->state){
  337. case EdfUnused:
  338. case EdfExpelled:
  339. /* That was easy */
  340. iunlock(&edflock);
  341. return;
  342. case EdfAdmitted:
  343. case EdfIdle:
  344. /* Just reset state */
  345. break;
  346. case EdfAwaitrelease:
  347. if (edfqremove(&qwaitrelease, t))
  348. edfreleasetimer();
  349. break;
  350. case EdfReleased:
  351. edfqremove(&qreleased, t);
  352. break;
  353. case EdfRunning:
  354. /* Task must be expelling itself */
  355. tt = edfpop();
  356. assert(t == tt);
  357. break;
  358. case EdfExtra:
  359. edfqremove(&qextratime, t);
  360. break;
  361. case EdfPreempted:
  362. edfqremove(edfstack + m->machno, t);
  363. break;
  364. case EdfBlocked:
  365. case EdfDeadline:
  366. break;
  367. }
  368. t->state = EdfExpelled;
  369. if(devrt) devrt(t, now, SExpel);
  370. setdelta();
  371. iunlock(&edflock);
  372. return;
  373. }
  374. static void
  375. edfreleaseintr(Ureg*, Timer*)
  376. {
  377. Task *t;
  378. extern int panicking;
  379. DPRINT("%d edfreleaseintr\n", m->machno);
  380. if(panicking || active.exiting)
  381. return;
  382. now = fastticks(nil);
  383. ilock(&edflock);
  384. while((t = qwaitrelease.head) && t->r <= now){
  385. /* There's something waiting to be released and its time has come */
  386. edfdequeue(&qwaitrelease);
  387. edfreleasetimer();
  388. edfrelease(t);
  389. }
  390. iunlock(&edflock);
  391. sched();
  392. splhi();
  393. }
  394. static void
  395. edfdeadlineintr(Ureg*, Timer *)
  396. {
  397. /* Task reached deadline */
  398. Ticks used;
  399. Task *t;
  400. Resource *r;
  401. char buf[128];
  402. int noted;
  403. extern int panicking;
  404. DPRINT("%d edfdeadlineintr\n", m->machno);
  405. if(panicking || active.exiting)
  406. return;
  407. now = fastticks(nil);
  408. ilock(&edflock);
  409. // If up is not set, we're running inside the scheduler
  410. // for non-real-time processes.
  411. noted = 0;
  412. if (up && isedf(up)) {
  413. t = up->task;
  414. assert(t->state == EdfRunning);
  415. assert(t->scheduled > 0);
  416. used = now - t->scheduled;
  417. t->scheduled = now;
  418. t->total += used;
  419. if (t->r < now){
  420. if (t->curcsn){
  421. if (t->curcsn->S <= used){
  422. t->curcsn->S = 0LL;
  423. resrelease(t);
  424. r = t->curcsn->i;
  425. noted++;
  426. snprint(buf, sizeof buf, "sys: deadline miss: resource %s", r->name);
  427. }else
  428. t->curcsn->S -= used;
  429. }
  430. if (t->S <= used){
  431. t->S = 0LL;
  432. if (!noted){
  433. noted++;
  434. snprint(buf, sizeof buf, "sys: deadline miss: runtime");
  435. }
  436. }else
  437. t->S -= used;
  438. if (t->d <= now || t->S == 0LL || t->curcsn == 0LL){
  439. /* Task has reached its deadline/slice, remove from queue */
  440. if (t->d <= now){
  441. t->missed++;
  442. misseddeadlines++;
  443. }
  444. deadline(up, SSlice);
  445. while (t = edfstack[m->machno].head){
  446. if (now < t->d)
  447. break;
  448. deadline(nil, SSlice);
  449. }
  450. }
  451. }
  452. }
  453. iunlock(&edflock);
  454. if (noted)
  455. postnote(up, 0, buf, NUser);
  456. sched();
  457. splhi();
  458. }
  459. static void
  460. edfbury(Proc *p)
  461. {
  462. Task *t;
  463. DPRINT("%d edfbury\n", m->machno);
  464. ilock(&edflock);
  465. now = fastticks(nil);
  466. if ((t = p->task) == nil){
  467. /* race condition? */
  468. iunlock(&edflock);
  469. DPRINT("%d edf bury race, pid %lud\n", m->machno, p->pid);
  470. return;
  471. }
  472. assert(edfstack[m->machno].head == t);
  473. delist(&t->procs, p);
  474. if (t->runq.head == nil){
  475. edfpop();
  476. t->state = EdfBlocked;
  477. }
  478. if (t->procs.n == 0){
  479. assert(t->runq.head == nil);
  480. t->state = EdfIdle;
  481. }
  482. if(devrt) devrt(t, now, SBlock);
  483. p->task = nil;
  484. iunlock(&edflock);
  485. }
  486. static void
  487. edfready(Proc *p)
  488. {
  489. Task *t;
  490. ilock(&edflock);
  491. DPRINT("%d edfready, %s, %d\n", m->machno, edfstatename[p->task->state], p->task->runq.n);
  492. if ((t = p->task) == nil){
  493. /* Must be a race */
  494. iunlock(&edflock);
  495. DPRINT("%d edf ready race, pid %lud\n", m->machno, p->pid);
  496. return;
  497. }
  498. p->rnext = 0;
  499. p->readytime = m->ticks;
  500. p->state = Ready;
  501. t->runq.n++;
  502. if(t->runq.tail){
  503. t->runq.tail->rnext = p;
  504. t->runq.tail = p;
  505. }else{
  506. t->runq.head = p;
  507. t->runq.tail = p;
  508. /* first proc to become runnable in this task */
  509. now = fastticks(nil);
  510. edfresched(t);
  511. }
  512. iunlock(&edflock);
  513. }
  514. static void
  515. edfresched(Task *t)
  516. {
  517. Task *xt;
  518. DPRINT("%d edfresched, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
  519. if (t->procs.n == 0){
  520. /* No member processes */
  521. if (t->state > EdfIdle){
  522. t->state = EdfIdle;
  523. if(devrt) devrt(t, now, SBlock);
  524. }
  525. return;
  526. }
  527. if (t->runq.n == 0 && (up == nil || up->task != t)){
  528. /* Member processes but none runnable */
  529. DPRINT("%d edfresched, nothing runnable\n", m->machno);
  530. if (t->state == EdfRunning)
  531. edfpop();
  532. if (t->state >= EdfIdle && t->state != EdfBlocked){
  533. t->state = EdfBlocked;
  534. if(devrt) devrt(t, now, SBlock);
  535. }
  536. return;
  537. }
  538. /* There are runnable processes */
  539. switch (t->state){
  540. case EdfUnused:
  541. iprint("%d attempt to schedule unused task\n", m->machno);
  542. case EdfExpelled:
  543. return; /* Not admitted */
  544. case EdfIdle:
  545. /* task was idle, schedule release now or later */
  546. if (t->r < now){
  547. if (t->t < now)
  548. t->t = now + t->T;
  549. t->r = t->t;
  550. }
  551. edfrelease(t);
  552. break;
  553. case EdfAwaitrelease:
  554. case EdfReleased:
  555. case EdfExtra:
  556. case EdfPreempted:
  557. /* dealt with by timer */
  558. break;
  559. case EdfAdmitted:
  560. /* test whether task can be started */
  561. if (edfstack[m->machno].head != nil){
  562. return;
  563. }
  564. /* fall through */
  565. case EdfRunning:
  566. if (t->r <= now){
  567. if (t->t < now){
  568. DPRINT("%d edfresched, rerelease\n", m->machno);
  569. /* Period passed, rerelease */
  570. t->r = now;
  571. xt = edfpop();
  572. assert(xt == t);
  573. edfrelease(t);
  574. return;
  575. }
  576. if (now < t->d){
  577. if (t->S > 0){
  578. DPRINT("%d edfresched, resume\n", m->machno);
  579. /* Running, not yet at deadline, leave it */
  580. return;
  581. }else
  582. t->d = now;
  583. }
  584. /* Released, but deadline is past, release at t->t */
  585. t->r = t->t;
  586. }
  587. xt = edfpop();
  588. assert(xt == t);
  589. t->state = EdfAwaitrelease;
  590. if (edfenqueue(&qwaitrelease, t))
  591. edfreleasetimer();
  592. break;
  593. case EdfBlocked:
  594. case EdfDeadline:
  595. if (t->r <= now){
  596. if (t->t < now){
  597. DPRINT("%d edfresched, rerelease\n", m->machno);
  598. /* Period passed, rerelease */
  599. t->r = now;
  600. edfrelease(t);
  601. return;
  602. }
  603. if (now < t->d && (t->flags & Useblocking) == 0){
  604. if (t->S > 0){
  605. DPRINT("%d edfresched, resume\n", m->machno);
  606. /* Released, not yet at deadline, release (again) */
  607. t->state = EdfReleased;
  608. edfenqueue(&qreleased, t);
  609. if(devrt) devrt(t, now, SResume);
  610. return;
  611. }else
  612. t->d = now;
  613. }
  614. /* Released, but deadline is past, release at t->t */
  615. t->r = t->t;
  616. }
  617. t->state = EdfAwaitrelease;
  618. if (edfenqueue(&qwaitrelease, t))
  619. edfreleasetimer();
  620. break;
  621. }
  622. }
  623. static void
  624. edfrelease(Task *t)
  625. {
  626. CSN *c;
  627. DPRINT("%d edfrelease, %s, %d\n", m->machno, edfstatename[t->state], t->runq.n);
  628. assert(t->runq.n > 0 || (up && up->task == t));
  629. t->t = t->r + t->T;
  630. t->d = t->r + t->D;
  631. if(devrt) devrt(t, t->d, SDeadline);
  632. t->S = t->C;
  633. for (c = (CSN*)t->csns.next; c; c = (CSN*)c->next){
  634. DEBUG("release csn: C=%T\n", ticks2time(c->C));
  635. c->S = c->C;
  636. }
  637. t->state = EdfReleased;
  638. edfenqueue(&qreleased, t);
  639. if(devrt) devrt(t, now, SRelease);
  640. }
  641. static Proc *
  642. edfrunproc(void)
  643. {
  644. /* Return an edf proc to run or nil */
  645. Task *t, *nt, *xt;
  646. Proc *p;
  647. Ticks when;
  648. static ulong nilcount;
  649. int i;
  650. if (edfstack[m->machno].head == nil && qreleased.head== nil){
  651. // quick way out
  652. nilcount++;
  653. return nil;
  654. }
  655. /* Figure out if the current proc should be preempted*/
  656. ilock(&edflock);
  657. now = fastticks(nil);
  658. /* first candidate is at the top of the stack of running procs */
  659. t = edfstack[m->machno].head;
  660. /* check out head of the release queue for a proc with a better deadline */
  661. nt = qreleased.head;
  662. if (t == nil && nt == nil){
  663. nilcount++;
  664. iunlock(&edflock);
  665. return nil;
  666. }
  667. DPRINT("edfrunproc %lud\n", nilcount);
  668. if (nt && (t == nil || (nt->d < t->d && nt->D < t->Delta))){
  669. if (conf.nmach > 1){
  670. for (i = 0; i < conf.nmach; i++){
  671. if (i == m->machno)
  672. continue;
  673. xt = edfstack[i].head;
  674. if (xt && xt->Delta <= nt->D){
  675. DPRINT("%d edfrunproc: interprocessor conflict, run current\n", m->machno);
  676. if (t)
  677. goto runt;
  678. nilcount++;
  679. iunlock(&edflock);
  680. return nil;
  681. }
  682. }
  683. }
  684. /* released task is better than current */
  685. DPRINT("%d edfrunproc: released\n", m->machno);
  686. edfdequeue(&qreleased);
  687. assert(nt->runq.n >= 1 || (up && up->task == nt));
  688. edfpush(nt);
  689. t = nt;
  690. t->scheduled = now;
  691. }else{
  692. DPRINT("%d edfrunproc: current\n", m->machno);
  693. }
  694. runt:
  695. assert (t->runq.n);
  696. /* Get first proc off t's run queue
  697. * No need to lock runq, edflock always held to access runq
  698. */
  699. t->state = EdfRunning;
  700. t->periods++;
  701. p = t->runq.head;
  702. if ((t->runq.head = p->rnext) == nil)
  703. t->runq.tail = nil;
  704. t->runq.n--;
  705. p->state = Scheding;
  706. if(p->mp != MACHP(m->machno))
  707. p->movetime = MACHP(0)->ticks + HZ/10;
  708. p->mp = MACHP(m->machno);
  709. when = now + t->S;
  710. if (t->d < when)
  711. when = t->d;
  712. if (when < now){
  713. DPRINT("%d edftimer: %T too late\n", m->machno, ticks2time(now-when));
  714. when = now;
  715. }
  716. if(deadlinetimer[m->machno].when == when){
  717. iunlock(&edflock);
  718. return p;
  719. }
  720. deadlinetimer[m->machno].when = when;
  721. timeradd(&deadlinetimer[m->machno]);
  722. iunlock(&edflock);
  723. return p;
  724. }
  725. /* Schedulability testing and its supporting routines */
  726. static void
  727. setdelta(void)
  728. {
  729. Resource *r;
  730. Task *t;
  731. int R;
  732. List *lr, *l;
  733. TaskLink *lt;
  734. CSN *c;
  735. for (lr = resources.next; lr; lr = lr->next){
  736. r = lr->i;
  737. assert(r);
  738. r->Delta = Infinity;
  739. R = 1;
  740. for (lt = (TaskLink*)r->tasks.next; lt; lt = (TaskLink*)lt->next){
  741. t = lt->i;
  742. assert(t);
  743. if (t->D < r->Delta){
  744. r->Delta = t->D;
  745. }
  746. if (lt->R == 0){
  747. R = 0;
  748. }
  749. }
  750. if (R)
  751. r->Delta = Infinity; /* Read-only resource, no exclusion */
  752. }
  753. /* Enumerate the critical sections */
  754. for (l = tasks.next; l ; l = l->next){
  755. t = l->i;
  756. assert(t);
  757. if (t->state <= EdfExpelled)
  758. continue;
  759. t->Delta = Infinity;
  760. for (c = (CSN*)t->csns.next; c; c = (CSN*)c->next){
  761. r = c->i;
  762. assert(r);
  763. c->Delta = r->Delta;
  764. if (c->p && c->p->Delta < c->Delta)
  765. c->Delta = c->p->Delta;
  766. if (c->C == t->C && r->Delta < t->Delta)
  767. t->Delta = r->Delta;
  768. }
  769. }
  770. }
  771. static void
  772. testdelta(Task *thetask)
  773. {
  774. Resource *r;
  775. Task *t;
  776. int R;
  777. List *lr, *l;
  778. TaskLink *lt;
  779. CSN *c;
  780. for (lr = resources.next; lr; lr = lr->next){
  781. r = lr->i;
  782. assert(r);
  783. DEBUG("Resource %s: ", r->name);
  784. r->testDelta = Infinity;
  785. R = 1;
  786. for (lt = (TaskLink*)r->tasks.next; lt; lt = (TaskLink*)lt->next){
  787. t = lt->i;
  788. assert(t);
  789. if (t->D < r->testDelta){
  790. r->testDelta = t->D;
  791. DEBUG("%d→%T ", t->taskno, ticks2time(t->D));
  792. }
  793. if (lt->R == 0){
  794. DEBUG("%d→X ", t->taskno);
  795. R = 0;
  796. }
  797. }
  798. if (R)
  799. r->testDelta = Infinity; /* Read-only resource, no exclusion */
  800. DEBUG("tΔ = %T\n", ticks2time(r->testDelta));
  801. }
  802. /* Enumerate the critical sections */
  803. for (l = tasks.next; l ; l = l->next){
  804. t = l->i;
  805. assert(t);
  806. if (t->state <= EdfExpelled && t != thetask)
  807. continue;
  808. t->testDelta = Infinity;
  809. for (c = (CSN*)t->csns.next; c; c = (CSN*)c->next){
  810. r = c->i;
  811. assert(r);
  812. c->testDelta = r->testDelta;
  813. if (c->p && c->p->testDelta < c->testDelta)
  814. c->testDelta = c->p->testDelta;
  815. if (c->C == t->C && r->testDelta < t->testDelta)
  816. t->testDelta = r->testDelta;
  817. DEBUG("Task %d Resource %s: tΔ = %T\n",
  818. t->taskno, r->name, ticks2time(r->testDelta));
  819. }
  820. }
  821. }
  822. static Ticks
  823. blockcost(Ticks ticks, Task *task, Task *thetask)
  824. {
  825. Ticks Cb, Cbt;
  826. List *l;
  827. Resource *r;
  828. CSN *c, *lc;
  829. int R;
  830. Task *t;
  831. Cb = 0;
  832. /* for each resource in task t, find all CSNs that refer to the
  833. * resource. If their Δ <= ticks < D and c->C > current CB
  834. * Cb = c->C
  835. */
  836. DEBUG("blockcost task %d: ", task->taskno);
  837. for (c = (CSN*)task->csns.next; c; c = (CSN*)c->next){
  838. r = c->i;
  839. assert(r);
  840. DEBUG("%s ", r->name);
  841. Cbt = Cb;
  842. R = 1; /* R == 1: resource is only used in read-only mode */
  843. for (l = tasks.next; l; l = l->next){
  844. t = l->i;
  845. if (t->state <= EdfExpelled && t != thetask)
  846. continue; /* csn belongs to an irrelevant task */
  847. for (lc = (CSN*)t->csns.next; lc; lc = (CSN*)lc->next){
  848. if (lc->i != r)
  849. continue; /* wrong resource */
  850. if (lc->R == 0)
  851. R = 0; /* Resource is used in exclusive mode */
  852. DEBUG("(%T≤%T<%T: %T) ",
  853. ticks2time(lc->testDelta), ticks2time(ticks), ticks2time(t->D),
  854. ticks2time(lc->C));
  855. if (lc->testDelta <= ticks && ticks < t->D && Cbt < lc->C)
  856. Cbt = lc->C;
  857. }
  858. }
  859. if (R == 0){
  860. DEBUG("%T, ", ticks2time(Cbt));
  861. Cb = Cbt;
  862. }
  863. DEBUG("ro, ");
  864. }
  865. DEBUG("Cb = %T\n", ticks2time(Cb));
  866. return Cb;
  867. }
  868. static void
  869. testenq(Task *t)
  870. {
  871. Task *tt, **ttp;
  872. t->testnext = nil;
  873. if (qschedulability == nil) {
  874. qschedulability = t;
  875. return;
  876. }
  877. SET(tt);
  878. for (ttp = &qschedulability; *ttp; ttp = &tt->testnext) {
  879. tt = *ttp;
  880. if (t->testtime < tt->testtime
  881. || (t->testtime == tt->testtime && t->testtype < tt->testtype)){
  882. t->testnext = tt;
  883. *ttp = t;
  884. return;
  885. }
  886. }
  887. assert(tt->testnext == nil);
  888. tt->testnext = t;
  889. }
  890. static char *
  891. edftestschedulability(Task *thetask)
  892. {
  893. Task *t;
  894. Ticks H, G, Cb, ticks;
  895. int steps;
  896. List *l;
  897. /* initialize */
  898. testdelta(thetask);
  899. if (thetask && (thetask->flags & Verbose))
  900. pprint("schedulability test for task %d\n", thetask->taskno);
  901. qschedulability = nil;
  902. for (l = tasks.next; l; l = l->next){
  903. t = l->i;
  904. assert(t);
  905. if (t->state <= EdfExpelled && t != thetask)
  906. continue;
  907. t->testtype = Release;
  908. t->testtime = 0;
  909. if (thetask && (thetask->flags & Verbose))
  910. pprint("\tInit: enqueue task %d\n", t->taskno);
  911. testenq(t);
  912. }
  913. H=0;
  914. G=0;
  915. for(steps = 0; steps < Maxsteps; steps++){
  916. t = qschedulability;
  917. qschedulability = t->testnext;
  918. ticks = t->testtime;
  919. switch (t->testtype){
  920. case Deadline:
  921. H += t->C;
  922. Cb = blockcost(ticks, t, thetask);
  923. if (thetask && (thetask->flags & Verbose))
  924. pprint("\tStep %3d, Ticks %T, task %d, deadline, H += %T → %T, Cb = %T\n",
  925. steps, ticks2time(ticks), t->taskno,
  926. ticks2time(t->C), ticks2time(H), ticks2time(Cb));
  927. if (H+Cb>ticks){
  928. if (thetask && (thetask->flags & Verbose))
  929. pprint("task %d not schedulable: H=%T + Cb=%T > ticks=%T\n",
  930. thetask->taskno, ticks2time(H), ticks2time(Cb), ticks2time(ticks));
  931. return "not schedulable";
  932. }
  933. t->testtime += t->T - t->D;
  934. t->testtype = Release;
  935. testenq(t);
  936. break;
  937. case Release:
  938. if (thetask && (thetask->flags & Verbose))
  939. pprint("\tStep %3d, Ticks %T, task %d, release, G %T, C%T\n",
  940. steps, ticks2time(ticks), t->taskno,
  941. ticks2time(t->C), ticks2time(G));
  942. if(ticks && G <= ticks){
  943. if (thetask && (thetask->flags & Verbose))
  944. pprint("task %d schedulable: G=%T <= ticks=%T\n",
  945. thetask->taskno, ticks2time(G), ticks2time(ticks));
  946. return nil;
  947. }
  948. G += t->C;
  949. t->testtime += t->D;
  950. t->testtype = Deadline;
  951. testenq(t);
  952. break;
  953. default:
  954. assert(0);
  955. }
  956. }
  957. return "probably not schedulable";
  958. }
  959. static void
  960. resacquire(Task *t, CSN *c)
  961. {
  962. Ticks now, when, used;
  963. now = fastticks(nil);
  964. used = now - t->scheduled;
  965. t->scheduled = now;
  966. t->total += used;
  967. t->S -= used;
  968. if (t->curcsn)
  969. t->curcsn->S -= used;
  970. when = now + c->S;
  971. if (deadlinetimer[m->machno].when == 0 || when < deadlinetimer[m->machno].when){
  972. deadlinetimer[m->machno].when = when;
  973. timeradd(&deadlinetimer[m->machno]);
  974. }
  975. t->Delta = c->Delta;
  976. t->curcsn = c;
  977. if(devrt) devrt(t, now, SResacq);
  978. /* priority is going up, no need to reschedule */
  979. }
  980. static void
  981. resrelease(Task *t)
  982. {
  983. Ticks now, when, used;
  984. CSN *c;
  985. c = t->curcsn;
  986. assert(c);
  987. t->curcsn = c->p;
  988. now = fastticks(nil);
  989. used = now - t->scheduled;
  990. t->scheduled = now;
  991. t->total += used;
  992. t->S -= used;
  993. c->S -= used;
  994. if (now + t->S > t->d)
  995. when = t->d;
  996. else
  997. when = now + t->S;
  998. if (t->curcsn){
  999. t->curcsn->S -= c->S; /* the sins of the fathers shall be visited upon the children */
  1000. t->Delta = t->curcsn->Delta;
  1001. if (when > now + t->curcsn->S)
  1002. when = now + t->curcsn->S;
  1003. }else
  1004. t->Delta = Infinity;
  1005. c->S = 0LL; /* don't allow reuse */
  1006. if(devrt) devrt(t, now, SResrel);
  1007. deadlinetimer[m->machno].when = when;
  1008. timeradd(&deadlinetimer[m->machno]);
  1009. qunlock(&edfschedlock);
  1010. sched(); /* reschedule */
  1011. qlock(&edfschedlock);
  1012. }
  1013. Edfinterface realedf = {
  1014. .isedf = isedf,
  1015. .edfbury = edfbury,
  1016. .edfanyready = edfanyready,
  1017. .edfready = edfready,
  1018. .edfrunproc = edfrunproc,
  1019. .edfblock = edfblock,
  1020. .edfinit = edfinit,
  1021. .edfexpel = edfexpel,
  1022. .edfadmit = edfadmit,
  1023. .edfdeadline = edfdeadline,
  1024. .resacquire = resacquire,
  1025. .resrelease = resrelease,
  1026. };