realtimesub.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  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 (c->C > C)
  176. error("resource uses too much time");
  177. if (c->C == 0)
  178. c->C = C;
  179. r = c->i;
  180. assert(r);
  181. /* Put task on resource's list */
  182. if(p = (TaskLink*)onlist(&r->tasks, task)){
  183. if(c->R == 0)
  184. p->R = 0;
  185. }else{
  186. p = mallocz(sizeof(TaskLink), 1);
  187. p->i = task;
  188. p->R = c->R;
  189. putlist(&r->tasks, p);
  190. incref(task);
  191. }
  192. }
  193. }
  194. char *
  195. seprintresources(char *p, char *e)
  196. {
  197. List *l, *q;
  198. Resource *r;
  199. Task *t;
  200. for (l = resources.next; l; l = l->next){
  201. r = l->i;
  202. assert(r);
  203. p = seprint(p, e, "name=%s", r->name);
  204. if (r->tasks.n){
  205. p = seprint(p, e, " tasks='");
  206. for (q = r->tasks.next; q; q = q->next){
  207. if (q != r->tasks.next)
  208. p = seprint(p, e, " ");
  209. t = q->i;
  210. p = seprint(p, e, "%d", t->taskno);
  211. }
  212. p = seprint(p, e, "'");
  213. }
  214. if (r->Delta)
  215. p = seprint(p, e, " Δ=%T", ticks2time(r->Delta));
  216. else if (r->testDelta)
  217. p = seprint(p, e, " testΔ=%T", ticks2time(r->testDelta));
  218. p = seprint(p, e, "\n");
  219. }
  220. return p;
  221. }
  222. char *
  223. seprintcsn(char *p, char *e, Head *h)
  224. {
  225. CSN *c, *prevc, *parent;
  226. Resource *r;
  227. int opens;
  228. prevc = (CSN*)~0;
  229. parent = nil;
  230. opens = 0;
  231. for(c = (CSN*)h->next; c; c = (CSN*)c->next){
  232. if (c->p == prevc){
  233. /* previous is parent: recurse */
  234. parent = prevc;
  235. p = seprint(p, e, "{ ");
  236. opens++;
  237. }else if (c->p != parent) {
  238. /* unrecurse */
  239. parent = parent->p;
  240. p = seprint(p, e, "} ");
  241. }
  242. if (r = c->i)
  243. p = seprint(p, e, "%s ", r->name);
  244. else
  245. p = seprint(p, e, "orphan ");
  246. if (c->R)
  247. p = seprint(p, e, "R ");
  248. if (c->Delta)
  249. p = seprint(p, e, "Δ=%T ", ticks2time(c->Delta));
  250. if (c->testDelta)
  251. p = seprint(p, e, "tΔ=%T ", ticks2time(c->testDelta));
  252. if (c->C)
  253. p = seprint(p, e, "C=%T ", ticks2time(c->C));
  254. prevc = c;
  255. }
  256. while (opens--)
  257. p = seprint(p, e, "} ");
  258. return p;
  259. }
  260. char*
  261. seprinttask(char *p, char *e, Task *t, Ticks now)
  262. {
  263. vlong n;
  264. char c;
  265. assert(t);
  266. p = seprint(p, e, "{%s, D%U, Δ%U,T%U, C%U, S%U",
  267. edfstatename[t->state], t->D, t->Delta, t->T, t->C, t->S);
  268. n = t->r - now;
  269. if (n >= 0)
  270. c = ' ';
  271. else {
  272. n = -n;
  273. c = '-';
  274. }
  275. p = seprint(p, e, ", r%c%U", c, (uvlong)n);
  276. n = t->d - now;
  277. if (n >= 0)
  278. c = ' ';
  279. else {
  280. n = -n;
  281. c = '-';
  282. }
  283. p = seprint(p, e, ", d%c%U", c, (uvlong)n);
  284. n = t->t - now;
  285. if (n >= 0)
  286. c = ' ';
  287. else {
  288. n = -n;
  289. c = '-';
  290. }
  291. p = seprint(p, e, ", t%c%U}", c, (uvlong)n);
  292. return p;
  293. }
  294. char*
  295. dumpq(char *p, char *e, Taskq *q, Ticks now)
  296. {
  297. Task *t;
  298. t = q->head;
  299. for(;;){
  300. if (t == nil)
  301. return seprint(p, e, "\n");
  302. p = seprinttask(p, e, t, now);
  303. t = t->rnext;
  304. if (t)
  305. seprint(p, e, ", ");
  306. }
  307. return nil;
  308. }
  309. static uvlong
  310. uvmuldiv(uvlong x, ulong num, ulong den)
  311. {
  312. /* multiply, then divide, avoiding overflow */
  313. uvlong hi;
  314. hi = (x & 0xffffffff00000000LL) >> 32;
  315. x &= 0xffffffffLL;
  316. hi *= num;
  317. return (x*num + (hi%den << 32)) / den + (hi/den << 32);
  318. }
  319. Time
  320. ticks2time(Ticks ticks)
  321. {
  322. if (ticks == Infinity)
  323. return Infinity;
  324. assert(ticks >= 0);
  325. if (fasthz == 0)
  326. fastticks(&fasthz);
  327. return uvmuldiv(ticks, Onesecond, fasthz);
  328. }
  329. Ticks
  330. time2ticks(Time time)
  331. {
  332. if (time == Infinity)
  333. return Infinity;
  334. assert(time >= 0);
  335. if (fasthz == 0)
  336. fastticks(&fasthz);
  337. return uvmuldiv(time, fasthz, Onesecond);
  338. }
  339. char *
  340. parsetime(Time *rt, char *s)
  341. {
  342. uvlong ticks;
  343. ulong l;
  344. char *e, *p;
  345. static int p10[] = {100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
  346. if (s == nil)
  347. return("missing value");
  348. ticks=strtoul(s, &e, 10);
  349. if (*e == '.'){
  350. p = e+1;
  351. l = strtoul(p, &e, 10);
  352. if(e-p > nelem(p10))
  353. return "too many digits after decimal point";
  354. if(e-p == 0)
  355. return "ill-formed number";
  356. l *= p10[e-p-1];
  357. }else
  358. l = 0;
  359. if (*e){
  360. if(strcmp(e, "s") == 0)
  361. ticks = 1000000000 * ticks + l;
  362. else if (strcmp(e, "ms") == 0)
  363. ticks = 1000000 * ticks + l/1000;
  364. else if (strcmp(e, "µs") == 0 || strcmp(e, "us") == 0)
  365. ticks = 1000 * ticks + l/1000000;
  366. else if (strcmp(e, "ns") != 0)
  367. return "unrecognized unit";
  368. }
  369. *rt = ticks;
  370. return nil;
  371. }
  372. int
  373. timeconv(Fmt *f)
  374. {
  375. char buf[128], *sign;
  376. Time t;
  377. Ticks ticks;
  378. buf[0] = 0;
  379. switch(f->r) {
  380. case 'U':
  381. ticks = va_arg(f->args, Ticks);
  382. t = ticks2time(ticks);
  383. break;
  384. case 'T': // Time in nanoseconds
  385. t = va_arg(f->args, Time);
  386. break;
  387. default:
  388. return fmtstrcpy(f, "(timeconv)");
  389. }
  390. if (t == Infinity)
  391. return fmtstrcpy(f, "∞");
  392. if (t < 0) {
  393. sign = "-";
  394. t = -t;
  395. }
  396. else
  397. sign = "";
  398. t += 1;
  399. if (t > Onesecond)
  400. sprint(buf, "%s%d.%.3ds", sign, (int)(t / Onesecond), (int)(t % Onesecond)/1000000);
  401. else if (t > Onemillisecond)
  402. sprint(buf, "%s%d.%.3dms", sign, (int)(t / Onemillisecond), (int)(t % Onemillisecond)/1000);
  403. else if (t > Onemicrosecond)
  404. sprint(buf, "%s%d.%.3dµs", sign, (int)(t / Onemicrosecond), (int)(t % Onemicrosecond));
  405. else
  406. sprint(buf, "%s%dns", sign, (int)t);
  407. return fmtstrcpy(f, buf);
  408. }
  409. int
  410. putlist(Head *h, List *l)
  411. {
  412. List **pp, *p;
  413. for(pp = &h->next; p = *pp; pp = &p->next)
  414. ;
  415. l->next = nil;
  416. *pp = l;
  417. h->n++;
  418. return 1;
  419. }
  420. List *
  421. onlist(Head *h, void *i)
  422. {
  423. List *l;
  424. for (l = h->next; l; l = l->next)
  425. if (l->i == i){
  426. /* already on the list */
  427. return l;
  428. }
  429. return nil;
  430. }
  431. int
  432. enlist(Head *h, void *i)
  433. {
  434. List *l;
  435. if(onlist(h, i))
  436. return 0;
  437. l = malloc(sizeof(List));
  438. if(l == nil)
  439. panic("malloc in enlist");
  440. l->i = i;
  441. return putlist(h, l);
  442. }
  443. int
  444. delist(Head *h, void *i)
  445. {
  446. List *l, **p;
  447. for (p = &h->next; l = *p; p = &l->next)
  448. if (l->i == i){
  449. *p = l->next;
  450. free(l);
  451. h->n--;
  452. return 1;
  453. }
  454. return 0;
  455. }
  456. void *
  457. findlist(Head *h, void *i)
  458. {
  459. List *l;
  460. for (l = h->next; l; l = l->next)
  461. if (l->i == i)
  462. return i;
  463. return nil;
  464. }