realtimesub.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "ureg.h"
  8. #include "ctype.h"
  9. #include "../port/error.h"
  10. #include "realtime.h"
  11. #include "../port/edf.h"
  12. static char qsep[] = " \t\r\n{}";
  13. static char tsep[] = " \t\r\n";
  14. static uvlong fasthz;
  15. Task *
  16. findtask(int taskno)
  17. {
  18. List *l;
  19. Task *t;
  20. for (l = tasks.next; l; l = l->next)
  21. if ((t = l->i) && t->taskno == taskno)
  22. return t;
  23. return nil;
  24. }
  25. Resource *
  26. resource(char *name, int add)
  27. {
  28. Resource *r;
  29. List *l;
  30. for (l = resources.next; l; l = l->next)
  31. if ((r = l->i) && strcmp(r->name, name) == 0)
  32. return r;
  33. if (add <= 0)
  34. return nil;
  35. r = mallocz(sizeof(Resource), 1);
  36. if (r == nil)
  37. error("resource: malloc");
  38. kstrdup(&r->name, name);
  39. enlist(&resources, r);
  40. return r;
  41. }
  42. void
  43. resourcefree(Resource *r)
  44. {
  45. if (r == nil)
  46. return;
  47. if (decref(r))
  48. return;
  49. delist(&resources, r);
  50. assert(r->tasks.n == 0);
  51. free(r->name);
  52. free(r);
  53. }
  54. void
  55. removetask(Task *t)
  56. {
  57. Proc *p;
  58. Resource *r;
  59. List *l;
  60. edf->edfexpel(t);
  61. while (l = t->procs.next){
  62. p = l->i;
  63. assert(p);
  64. p->task = nil;
  65. DEBUG("taking proc %lud off task %d\n", p->pid, t->taskno);
  66. delist(&t->procs, p);
  67. }
  68. while (p = t->runq.head){
  69. /* put runnable procs on regular run queue */
  70. t->runq.head = p->rnext;
  71. DEBUG("putting proc %lud on runq\n", p->pid);
  72. ready(p);
  73. t->runq.n--;
  74. }
  75. t->runq.tail = nil;
  76. assert(t->runq.n == 0);
  77. while (l = t->csns.next){
  78. r = l->i;
  79. assert(r);
  80. if (delist(&r->tasks, t)) {
  81. DEBUG("freeing task %d from resource %s\n", t->taskno, r->name);
  82. taskfree(t);
  83. }
  84. if (delist(&t->csns, r)) {
  85. DEBUG("freeing resource %s\n", r->name);
  86. resourcefree(r);
  87. }
  88. }
  89. free(t->user);
  90. t->user = nil;
  91. t->state = EdfUnused;
  92. if (delist(&tasks, t)) {
  93. DEBUG("freeing task %d\n", t->taskno);
  94. taskfree(t);
  95. }
  96. }
  97. char*
  98. parseresource(Head *h, CSN *parent, char *s)
  99. {
  100. CSN *csn, *q;
  101. Resource *r;
  102. char *p, *e, c;
  103. Time T;
  104. int recursed;
  105. csn = nil;
  106. recursed = 1;
  107. while(*s != '\0' && *s != '}'){
  108. /* Start of a token */
  109. while(*s && utfrune(tsep, *s))
  110. *s++ = '\0';
  111. if (*s == '\0' || *s == '}')
  112. return s; /* No token found */
  113. if (*s == '{'){
  114. /* Recursion */
  115. if (recursed)
  116. error("unexpected '{'");
  117. s = parseresource(h, csn, s+1);
  118. if (*s != '}')
  119. error("expected '}'");
  120. recursed = 1;
  121. *s++ = '\0';
  122. }else{
  123. p = s;
  124. /* Normal token */
  125. while(*s && utfrune(qsep, *s) == nil)
  126. s++;
  127. assert(s > p);
  128. c = *s;
  129. *s = '\0';
  130. if (strcmp(p, "R") == 0){
  131. if (csn == nil || csn->R != 0)
  132. error("unexpected R");
  133. csn->R = 1;
  134. }else if (isalpha(*p) || *p == '_'){
  135. r = resource(p, 1);
  136. assert(r);
  137. for (q = parent; q; q = q->p)
  138. if (q->i == r){
  139. resourcefree(r);
  140. error("nested resource");
  141. }
  142. csn = mallocz(sizeof(CSN), 1);
  143. csn->p = parent;
  144. csn->i = r;
  145. incref(r);
  146. DEBUG("Putting resource %s 0x%p in CSN 0x%p on list 0x%p\n",
  147. r->name, r, csn, h);
  148. putlist(h, csn);
  149. recursed = 0;
  150. }else{
  151. if (csn == nil || csn->C != 0)
  152. error("unexpected resource cost");
  153. if (e=parsetime(&T, p))
  154. error(e);
  155. csn->C = time2ticks(T);
  156. }
  157. *s = c;
  158. }
  159. }
  160. return s;
  161. }
  162. void
  163. resourcetimes(Task *task, Head *h)
  164. {
  165. CSN *c;
  166. Resource *r;
  167. TaskLink *p;
  168. Ticks C;
  169. for(c = (CSN*)h->next; c; c = (CSN*)c->next){
  170. c->t = task;
  171. if (c->p)
  172. C = c->p->C;
  173. else
  174. C = task->C;
  175. if (task->flags & BestEffort){
  176. if (c->C == 0)
  177. error("no cost specified for resource");
  178. }else if (c->C > C)
  179. error("resource uses too much time");
  180. else if (c->C == 0)
  181. c->C = C;
  182. r = c->i;
  183. assert(r);
  184. /* Put task on resource's list */
  185. if(p = (TaskLink*)onlist(&r->tasks, task)){
  186. if(c->R == 0)
  187. p->R = 0;
  188. }else{
  189. p = mallocz(sizeof(TaskLink), 1);
  190. p->i = task;
  191. p->R = c->R;
  192. putlist(&r->tasks, p);
  193. incref(task);
  194. }
  195. }
  196. }
  197. char *
  198. seprintresources(char *p, char *e)
  199. {
  200. List *l, *q;
  201. Resource *r;
  202. Task *t;
  203. for (l = resources.next; l; l = l->next){
  204. r = l->i;
  205. assert(r);
  206. p = seprint(p, e, "name=%s", r->name);
  207. if (r->tasks.n){
  208. p = seprint(p, e, " tasks='");
  209. for (q = r->tasks.next; q; q = q->next){
  210. if (q != r->tasks.next)
  211. p = seprint(p, e, " ");
  212. t = q->i;
  213. p = seprint(p, e, "%d", t->taskno);
  214. }
  215. p = seprint(p, e, "'");
  216. }
  217. if (r->Delta)
  218. p = seprint(p, e, " Δ=%T", ticks2time(r->Delta));
  219. else if (r->testDelta)
  220. p = seprint(p, e, " testΔ=%T", ticks2time(r->testDelta));
  221. p = seprint(p, e, "\n");
  222. }
  223. return p;
  224. }
  225. char *
  226. seprintcsn(char *p, char *e, Head *h)
  227. {
  228. CSN *c, *prevc, *parent;
  229. Resource *r;
  230. int opens;
  231. prevc = (CSN*)~0;
  232. parent = nil;
  233. opens = 0;
  234. for(c = (CSN*)h->next; c; c = (CSN*)c->next){
  235. if (c->p == prevc){
  236. /* previous is parent: recurse */
  237. parent = prevc;
  238. p = seprint(p, e, "{ ");
  239. opens++;
  240. }else if (c->p != parent) {
  241. /* unrecurse */
  242. parent = parent->p;
  243. p = seprint(p, e, "} ");
  244. }
  245. if (r = c->i)
  246. p = seprint(p, e, "%s ", r->name);
  247. else
  248. p = seprint(p, e, "orphan ");
  249. if (c->R)
  250. p = seprint(p, e, "R ");
  251. if (c->Delta)
  252. p = seprint(p, e, "Δ=%T ", ticks2time(c->Delta));
  253. if (c->testDelta)
  254. p = seprint(p, e, "tΔ=%T ", ticks2time(c->testDelta));
  255. if (c->C)
  256. p = seprint(p, e, "C=%T ", ticks2time(c->C));
  257. prevc = c;
  258. }
  259. while (opens--)
  260. p = seprint(p, e, "} ");
  261. return p;
  262. }
  263. char*
  264. seprinttask(char *p, char *e, Task *t, Ticks now)
  265. {
  266. vlong n;
  267. char c;
  268. assert(t);
  269. p = seprint(p, e, "{%s, D%U, Δ%U,T%U, C%U, S%U",
  270. edfstatename[t->state], t->D, t->Delta, t->T, t->C, t->S);
  271. n = t->r - now;
  272. if (n >= 0)
  273. c = ' ';
  274. else {
  275. n = -n;
  276. c = '-';
  277. }
  278. p = seprint(p, e, ", r%c%U", c, (uvlong)n);
  279. n = t->d - now;
  280. if (n >= 0)
  281. c = ' ';
  282. else {
  283. n = -n;
  284. c = '-';
  285. }
  286. p = seprint(p, e, ", d%c%U", c, (uvlong)n);
  287. n = t->t - now;
  288. if (n >= 0)
  289. c = ' ';
  290. else {
  291. n = -n;
  292. c = '-';
  293. }
  294. p = seprint(p, e, ", t%c%U}", c, (uvlong)n);
  295. return p;
  296. }
  297. char*
  298. dumpq(char *p, char *e, Taskq *q, Ticks now)
  299. {
  300. Task *t;
  301. t = q->head;
  302. for(;;){
  303. if (t == nil)
  304. return seprint(p, e, "\n");
  305. p = seprinttask(p, e, t, now);
  306. t = t->rnext;
  307. if (t)
  308. seprint(p, e, ", ");
  309. }
  310. return nil;
  311. }
  312. static uvlong
  313. uvmuldiv(uvlong x, ulong num, ulong den)
  314. {
  315. /* multiply, then divide, avoiding overflow */
  316. uvlong hi;
  317. hi = (x & 0xffffffff00000000LL) >> 32;
  318. x &= 0xffffffffLL;
  319. hi *= num;
  320. return (x*num + (hi%den << 32)) / den + (hi/den << 32);
  321. }
  322. Time
  323. ticks2time(Ticks ticks)
  324. {
  325. if (ticks == Infinity)
  326. return Infinity;
  327. assert(ticks >= 0);
  328. if (fasthz == 0)
  329. fastticks(&fasthz);
  330. return uvmuldiv(ticks, Onesecond, fasthz);
  331. }
  332. Ticks
  333. time2ticks(Time time)
  334. {
  335. if (time == Infinity)
  336. return Infinity;
  337. assert(time >= 0);
  338. if (fasthz == 0)
  339. fastticks(&fasthz);
  340. return uvmuldiv(time, fasthz, Onesecond);
  341. }
  342. char *
  343. parsetime(Time *rt, char *s)
  344. {
  345. uvlong ticks;
  346. ulong l;
  347. char *e, *p;
  348. static int p10[] = {100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
  349. if (s == nil)
  350. return("missing value");
  351. ticks=strtoul(s, &e, 10);
  352. if (*e == '.'){
  353. p = e+1;
  354. l = strtoul(p, &e, 10);
  355. if(e-p > nelem(p10))
  356. return "too many digits after decimal point";
  357. if(e-p == 0)
  358. return "ill-formed number";
  359. l *= p10[e-p-1];
  360. }else
  361. l = 0;
  362. if (*e){
  363. if(strcmp(e, "s") == 0)
  364. ticks = 1000000000 * ticks + l;
  365. else if (strcmp(e, "ms") == 0)
  366. ticks = 1000000 * ticks + l/1000;
  367. else if (strcmp(e, "µs") == 0 || strcmp(e, "us") == 0)
  368. ticks = 1000 * ticks + l/1000000;
  369. else if (strcmp(e, "ns") != 0)
  370. return "unrecognized unit";
  371. }
  372. *rt = ticks;
  373. return nil;
  374. }
  375. int
  376. timeconv(Fmt *f)
  377. {
  378. char buf[128], *sign;
  379. Time t;
  380. Ticks ticks;
  381. buf[0] = 0;
  382. switch(f->r) {
  383. case 'U':
  384. ticks = va_arg(f->args, Ticks);
  385. t = ticks2time(ticks);
  386. break;
  387. case 'T': // Time in nanoseconds
  388. t = va_arg(f->args, Time);
  389. break;
  390. default:
  391. return fmtstrcpy(f, "(timeconv)");
  392. }
  393. if (t == Infinity)
  394. return fmtstrcpy(f, "∞");
  395. if (t < 0) {
  396. sign = "-";
  397. t = -t;
  398. }
  399. else
  400. sign = "";
  401. t += 1;
  402. if (t > Onesecond)
  403. sprint(buf, "%s%d.%.3ds", sign, (int)(t / Onesecond), (int)(t % Onesecond)/1000000);
  404. else if (t > Onemillisecond)
  405. sprint(buf, "%s%d.%.3dms", sign, (int)(t / Onemillisecond), (int)(t % Onemillisecond)/1000);
  406. else if (t > Onemicrosecond)
  407. sprint(buf, "%s%d.%.3dµs", sign, (int)(t / Onemicrosecond), (int)(t % Onemicrosecond));
  408. else
  409. sprint(buf, "%s%dns", sign, (int)t);
  410. return fmtstrcpy(f, buf);
  411. }
  412. int
  413. putlist(Head *h, List *l)
  414. {
  415. List **pp, *p;
  416. for(pp = &h->next; p = *pp; pp = &p->next)
  417. ;
  418. l->next = nil;
  419. *pp = l;
  420. h->n++;
  421. return 1;
  422. }
  423. List *
  424. onlist(Head *h, void *i)
  425. {
  426. List *l;
  427. for (l = h->next; l; l = l->next)
  428. if (l->i == i){
  429. /* already on the list */
  430. return l;
  431. }
  432. return nil;
  433. }
  434. int
  435. enlist(Head *h, void *i)
  436. {
  437. List *l;
  438. if(onlist(h, i))
  439. return 0;
  440. l = malloc(sizeof(List));
  441. if(l == nil)
  442. panic("malloc in enlist");
  443. l->i = i;
  444. return putlist(h, l);
  445. }
  446. int
  447. delist(Head *h, void *i)
  448. {
  449. List *l, **p;
  450. for (p = &h->next; l = *p; p = &l->next)
  451. if (l->i == i){
  452. *p = l->next;
  453. free(l);
  454. h->n--;
  455. return 1;
  456. }
  457. return 0;
  458. }
  459. void *
  460. findlist(Head *h, void *i)
  461. {
  462. List *l;
  463. for (l = h->next; l; l = l->next)
  464. if (l->i == i)
  465. return i;
  466. return nil;
  467. }