sched.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996
  1. /***** spin: sched.c *****/
  2. /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
  3. /* All Rights Reserved. This software is for educational purposes only. */
  4. /* No guarantee whatsoever is expressed or implied by the distribution of */
  5. /* this code. Permission is given to distribute this code provided that */
  6. /* this introductory message is not removed and no monies are exchanged. */
  7. /* Software written by Gerard J. Holzmann. For tool documentation see: */
  8. /* http://spinroot.com/ */
  9. /* Send all bug-reports and/or questions to: bugs@spinroot.com */
  10. #include <stdlib.h>
  11. #include "spin.h"
  12. #ifdef PC
  13. #include "y_tab.h"
  14. #else
  15. #include "y.tab.h"
  16. #endif
  17. extern int verbose, s_trail, analyze, no_wrapup;
  18. extern char *claimproc, *eventmap, Buf[];
  19. extern Ordered *all_names;
  20. extern Symbol *Fname, *context;
  21. extern int lineno, nr_errs, dumptab, xspin, jumpsteps, columns;
  22. extern int u_sync, Elcnt, interactive, TstOnly, cutoff;
  23. extern short has_enabled;
  24. extern int limited_vis;
  25. RunList *X = (RunList *) 0;
  26. RunList *run = (RunList *) 0;
  27. RunList *LastX = (RunList *) 0; /* previous executing proc */
  28. ProcList *rdy = (ProcList *) 0;
  29. Element *LastStep = ZE;
  30. int nproc=0, nstop=0, Tval=0;
  31. int Rvous=0, depth=0, nrRdy=0, MadeChoice;
  32. short Have_claim=0, Skip_claim=0;
  33. static int Priority_Sum = 0;
  34. static void setlocals(RunList *);
  35. static void setparams(RunList *, ProcList *, Lextok *);
  36. static void talk(RunList *);
  37. void
  38. runnable(ProcList *p, int weight, int noparams)
  39. { RunList *r = (RunList *) emalloc(sizeof(RunList));
  40. r->n = p->n;
  41. r->tn = p->tn;
  42. r->pid = nproc++ - nstop + Skip_claim;
  43. if ((verbose&4) || (verbose&32))
  44. printf("Starting %s with pid %d\n", p->n->name, r->pid);
  45. if (!p->s)
  46. fatal("parsing error, no sequence %s", p->n?p->n->name:"--");
  47. r->pc = huntele(p->s->frst, p->s->frst->status, -1);
  48. r->ps = p->s;
  49. if (p->s->last)
  50. p->s->last->status |= ENDSTATE; /* normal end state */
  51. r->nxt = run;
  52. r->prov = p->prov;
  53. r->priority = weight;
  54. if (noparams) setlocals(r);
  55. Priority_Sum += weight;
  56. run = r;
  57. }
  58. ProcList *
  59. ready(Symbol *n, Lextok *p, Sequence *s, int det, Lextok *prov)
  60. /* n=name, p=formals, s=body det=deterministic prov=provided */
  61. { ProcList *r = (ProcList *) emalloc(sizeof(ProcList));
  62. Lextok *fp, *fpt; int j; extern int Npars;
  63. r->n = n;
  64. r->p = p;
  65. r->s = s;
  66. r->prov = prov;
  67. r->tn = nrRdy++;
  68. r->det = (short) det;
  69. r->nxt = rdy;
  70. rdy = r;
  71. for (fp = p, j = 0; fp; fp = fp->rgt)
  72. for (fpt = fp->lft; fpt; fpt = fpt->rgt)
  73. j++; /* count # of parameters */
  74. Npars = max(Npars, j);
  75. return rdy;
  76. }
  77. int
  78. find_maxel(Symbol *s)
  79. { ProcList *p;
  80. for (p = rdy; p; p = p->nxt)
  81. if (p->n == s)
  82. return p->s->maxel++;
  83. return Elcnt++;
  84. }
  85. static void
  86. formdump(void)
  87. { ProcList *p;
  88. Lextok *f, *t;
  89. int cnt;
  90. for (p = rdy; p; p = p->nxt)
  91. { if (!p->p) continue;
  92. cnt = -1;
  93. for (f = p->p; f; f = f->rgt) /* types */
  94. for (t = f->lft; t; t = t->rgt) /* formals */
  95. { if (t->ntyp != ',')
  96. t->sym->Nid = cnt--; /* overload Nid */
  97. else
  98. t->lft->sym->Nid = cnt--;
  99. }
  100. }
  101. }
  102. void
  103. announce(char *w)
  104. {
  105. if (columns)
  106. { extern char Buf[];
  107. extern int firstrow;
  108. firstrow = 1;
  109. if (columns == 2)
  110. { sprintf(Buf, "%d:%s",
  111. run->pid - Have_claim, run->n->name);
  112. pstext(run->pid - Have_claim, Buf);
  113. } else
  114. printf("proc %d = %s\n",
  115. run->pid - Have_claim, run->n->name);
  116. return;
  117. }
  118. if (dumptab
  119. || analyze
  120. || s_trail
  121. || !(verbose&4))
  122. return;
  123. if (w)
  124. printf(" 0: proc - (%s) ", w);
  125. else
  126. whoruns(1);
  127. printf("creates proc %2d (%s)",
  128. run->pid - Have_claim,
  129. run->n->name);
  130. if (run->priority > 1)
  131. printf(" priority %d", run->priority);
  132. printf("\n");
  133. }
  134. #ifndef MAXP
  135. #define MAXP 255 /* matches max nr of processes in verifier */
  136. #endif
  137. int
  138. enable(Lextok *m)
  139. { ProcList *p;
  140. Symbol *s = m->sym; /* proctype name */
  141. Lextok *n = m->lft; /* actual parameters */
  142. if (m->val < 1) m->val = 1; /* minimum priority */
  143. for (p = rdy; p; p = p->nxt)
  144. if (strcmp(s->name, p->n->name) == 0)
  145. { if (nproc-nstop >= MAXP)
  146. { printf("spin: too many processes (%d max)\n", MAXP);
  147. break;
  148. }
  149. runnable(p, m->val, 0);
  150. announce((char *) 0);
  151. setparams(run, p, n);
  152. setlocals(run); /* after setparams */
  153. return run->pid - Have_claim + Skip_claim; /* effective simu pid */
  154. }
  155. return 0; /* process not found */
  156. }
  157. void
  158. start_claim(int n)
  159. { ProcList *p;
  160. RunList *r, *q = (RunList *) 0;
  161. for (p = rdy; p; p = p->nxt)
  162. if (p->tn == n
  163. && strcmp(p->n->name, ":never:") == 0)
  164. { runnable(p, 1, 1);
  165. goto found;
  166. }
  167. printf("spin: couldn't find claim (ignored)\n");
  168. Skip_claim = 1;
  169. goto done;
  170. found:
  171. /* move claim to far end of runlist, and reassign it pid 0 */
  172. if (columns == 2)
  173. { depth = 0;
  174. pstext(0, "0::never:");
  175. for (r = run; r; r = r->nxt)
  176. { if (!strcmp(r->n->name, ":never:"))
  177. continue;
  178. sprintf(Buf, "%d:%s",
  179. r->pid+1, r->n->name);
  180. pstext(r->pid+1, Buf);
  181. } }
  182. if (run->pid == 0) return; /* it is the first process started */
  183. q = run; run = run->nxt;
  184. q->pid = 0; q->nxt = (RunList *) 0; /* remove */
  185. done:
  186. Have_claim = 1;
  187. for (r = run; r; r = r->nxt)
  188. { r->pid = r->pid+Have_claim; /* adjust */
  189. if (!r->nxt)
  190. { r->nxt = q;
  191. break;
  192. } }
  193. }
  194. int
  195. f_pid(char *n)
  196. { RunList *r;
  197. int rval = -1;
  198. for (r = run; r; r = r->nxt)
  199. if (strcmp(n, r->n->name) == 0)
  200. { if (rval >= 0)
  201. { printf("spin: remote ref to proctype %s, ", n);
  202. printf("has more than one match: %d and %d\n",
  203. rval, r->pid);
  204. } else
  205. rval = r->pid;
  206. }
  207. return rval;
  208. }
  209. void
  210. wrapup(int fini)
  211. {
  212. limited_vis = 0;
  213. if (columns)
  214. { extern void putpostlude(void);
  215. if (columns == 2) putpostlude();
  216. if (!no_wrapup)
  217. printf("-------------\nfinal state:\n-------------\n");
  218. }
  219. if (no_wrapup)
  220. goto short_cut;
  221. if (nproc != nstop)
  222. { int ov = verbose;
  223. printf("#processes: %d\n", nproc-nstop - Have_claim + Skip_claim);
  224. verbose &= ~4;
  225. dumpglobals();
  226. verbose = ov;
  227. verbose &= ~1; /* no more globals */
  228. verbose |= 32; /* add process states */
  229. for (X = run; X; X = X->nxt)
  230. talk(X);
  231. verbose = ov; /* restore */
  232. }
  233. printf("%d process%s created\n",
  234. nproc - Have_claim + Skip_claim,
  235. (xspin || nproc!=1)?"es":"");
  236. short_cut:
  237. if (xspin) alldone(0); /* avoid an abort from xspin */
  238. if (fini) alldone(1);
  239. }
  240. static char is_blocked[256];
  241. static int
  242. p_blocked(int p)
  243. { int i, j;
  244. is_blocked[p%256] = 1;
  245. for (i = j = 0; i < nproc - nstop; i++)
  246. j += is_blocked[i];
  247. if (j >= nproc - nstop)
  248. { memset(is_blocked, 0, 256);
  249. return 1;
  250. }
  251. return 0;
  252. }
  253. static Element *
  254. silent_moves(Element *e)
  255. { Element *f;
  256. switch (e->n->ntyp) {
  257. case GOTO:
  258. if (Rvous) break;
  259. f = get_lab(e->n, 1);
  260. cross_dsteps(e->n, f->n);
  261. return f; /* guard against goto cycles */
  262. case UNLESS:
  263. return silent_moves(e->sub->this->frst);
  264. case NON_ATOMIC:
  265. case ATOMIC:
  266. case D_STEP:
  267. e->n->sl->this->last->nxt = e->nxt;
  268. return silent_moves(e->n->sl->this->frst);
  269. case '.':
  270. return silent_moves(e->nxt);
  271. }
  272. return e;
  273. }
  274. static void
  275. pickproc(void)
  276. { SeqList *z; Element *has_else;
  277. short Choices[256];
  278. int j, k, nr_else = 0;
  279. if (nproc <= nstop+1)
  280. { X = run;
  281. return;
  282. }
  283. if (!interactive || depth < jumpsteps)
  284. { /* was: j = (int) Rand()%(nproc-nstop); */
  285. if (Priority_Sum < nproc-nstop)
  286. fatal("cannot happen - weights", (char *)0);
  287. j = (int) Rand()%Priority_Sum;
  288. while (j - X->priority >= 0)
  289. { j -= X->priority;
  290. X = X->nxt;
  291. if (!X) X = run;
  292. }
  293. } else
  294. { int only_choice = -1;
  295. int no_choice = 0, proc_no_ch, proc_k;
  296. try_again: printf("Select a statement\n");
  297. try_more: for (X = run, k = 1; X; X = X->nxt)
  298. { if (X->pid > 255) break;
  299. Choices[X->pid] = (short) k;
  300. if (!X->pc
  301. || (X->prov && !eval(X->prov)))
  302. { if (X == run)
  303. Choices[X->pid] = 0;
  304. continue;
  305. }
  306. X->pc = silent_moves(X->pc);
  307. if (!X->pc->sub && X->pc->n)
  308. { int unex;
  309. unex = !Enabled0(X->pc);
  310. if (unex)
  311. no_choice++;
  312. else
  313. only_choice = k;
  314. if (!xspin && unex && !(verbose&32))
  315. { k++;
  316. continue;
  317. }
  318. printf("\tchoice %d: ", k++);
  319. p_talk(X->pc, 0);
  320. if (unex)
  321. printf(" unexecutable,");
  322. printf(" [");
  323. comment(stdout, X->pc->n, 0);
  324. if (X->pc->esc) printf(" + Escape");
  325. printf("]\n");
  326. } else {
  327. has_else = ZE;
  328. proc_no_ch = no_choice;
  329. proc_k = k;
  330. for (z = X->pc->sub, j=0; z; z = z->nxt)
  331. { Element *y = silent_moves(z->this->frst);
  332. int unex;
  333. if (!y) continue;
  334. if (y->n->ntyp == ELSE)
  335. { has_else = (Rvous)?ZE:y;
  336. nr_else = k++;
  337. continue;
  338. }
  339. unex = !Enabled0(y);
  340. if (unex)
  341. no_choice++;
  342. else
  343. only_choice = k;
  344. if (!xspin && unex && !(verbose&32))
  345. { k++;
  346. continue;
  347. }
  348. printf("\tchoice %d: ", k++);
  349. p_talk(X->pc, 0);
  350. if (unex)
  351. printf(" unexecutable,");
  352. printf(" [");
  353. comment(stdout, y->n, 0);
  354. printf("]\n");
  355. }
  356. if (has_else)
  357. { if (no_choice-proc_no_ch >= (k-proc_k)-1)
  358. { only_choice = nr_else;
  359. printf("\tchoice %d: ", nr_else);
  360. p_talk(X->pc, 0);
  361. printf(" [else]\n");
  362. } else
  363. { no_choice++;
  364. printf("\tchoice %d: ", nr_else);
  365. p_talk(X->pc, 0);
  366. printf(" unexecutable, [else]\n");
  367. } }
  368. } }
  369. X = run;
  370. if (k - no_choice < 2 && Tval == 0)
  371. { Tval = 1;
  372. no_choice = 0; only_choice = -1;
  373. goto try_more;
  374. }
  375. if (xspin)
  376. printf("Make Selection %d\n\n", k-1);
  377. else
  378. { if (k - no_choice < 2)
  379. { printf("no executable choices\n");
  380. alldone(0);
  381. }
  382. printf("Select [1-%d]: ", k-1);
  383. }
  384. if (!xspin && k - no_choice == 2)
  385. { printf("%d\n", only_choice);
  386. j = only_choice;
  387. } else
  388. { char buf[256];
  389. fflush(stdout);
  390. scanf("%s", buf);
  391. j = -1;
  392. if (isdigit(buf[0]))
  393. j = atoi(buf);
  394. else
  395. { if (buf[0] == 'q')
  396. alldone(0);
  397. }
  398. if (j < 1 || j >= k)
  399. { printf("\tchoice is outside range\n");
  400. goto try_again;
  401. } }
  402. MadeChoice = 0;
  403. for (X = run; X; X = X->nxt)
  404. { if (!X->nxt
  405. || X->nxt->pid > 255
  406. || j < Choices[X->nxt->pid])
  407. {
  408. MadeChoice = 1+j-Choices[X->pid];
  409. break;
  410. } }
  411. }
  412. }
  413. void
  414. sched(void)
  415. { Element *e;
  416. RunList *Y=0; /* previous process in run queue */
  417. RunList *oX;
  418. int go, notbeyond = 0;
  419. #ifdef PC
  420. int bufmax = 100;
  421. #endif
  422. if (dumptab)
  423. { formdump();
  424. symdump();
  425. dumplabels();
  426. return;
  427. }
  428. if (has_enabled && u_sync > 0)
  429. { printf("spin: error, cannot use 'enabled()' in ");
  430. printf("models with synchronous channels.\n");
  431. nr_errs++;
  432. }
  433. if (analyze)
  434. { gensrc();
  435. return;
  436. } else if (s_trail)
  437. { match_trail();
  438. return;
  439. }
  440. if (claimproc)
  441. printf("warning: never claim not used in random simulation\n");
  442. if (eventmap)
  443. printf("warning: trace assertion not used in random simulation\n");
  444. X = run;
  445. pickproc();
  446. while (X)
  447. { context = X->n;
  448. if (X->pc && X->pc->n)
  449. { lineno = X->pc->n->ln;
  450. Fname = X->pc->n->fn;
  451. }
  452. if (cutoff > 0 && depth >= cutoff)
  453. { printf("-------------\n");
  454. printf("depth-limit (-u%d steps) reached\n", cutoff);
  455. break;
  456. }
  457. #ifdef PC
  458. if (xspin && !interactive && --bufmax <= 0)
  459. { int c; /* avoid buffer overflow on pc's */
  460. printf("spin: type return to proceed\n");
  461. fflush(stdout);
  462. c = getc(stdin);
  463. if (c == 'q') wrapup(0);
  464. bufmax = 100;
  465. }
  466. #endif
  467. depth++; LastStep = ZE;
  468. oX = X; /* a rendezvous could change it */
  469. go = 1;
  470. if (X && X->prov && X->pc
  471. && !(X->pc->status & D_ATOM)
  472. && !eval(X->prov))
  473. { if (!xspin && ((verbose&32) || (verbose&4)))
  474. { p_talk(X->pc, 1);
  475. printf("\t<<Not Enabled>>\n");
  476. }
  477. go = 0;
  478. }
  479. if (go && (e = eval_sub(X->pc)))
  480. { if (depth >= jumpsteps
  481. && ((verbose&32) || (verbose&4)))
  482. { if (X == oX)
  483. if (!(e->status & D_ATOM) || (verbose&32)) /* no talking in d_steps */
  484. { p_talk(X->pc, 1);
  485. printf(" [");
  486. if (!LastStep) LastStep = X->pc;
  487. comment(stdout, LastStep->n, 0);
  488. printf("]\n");
  489. }
  490. if (verbose&1) dumpglobals();
  491. if (verbose&2) dumplocal(X);
  492. if (!(e->status & D_ATOM))
  493. if (xspin)
  494. printf("\n");
  495. }
  496. if (oX != X)
  497. { e = silent_moves(e);
  498. notbeyond = 0;
  499. }
  500. oX->pc = e; LastX = X;
  501. if (!interactive) Tval = 0;
  502. memset(is_blocked, 0, 256);
  503. if (X->pc && (X->pc->status & (ATOM|L_ATOM))
  504. && (notbeyond == 0 || oX != X))
  505. { if ((X->pc->status & L_ATOM))
  506. notbeyond = 1;
  507. continue; /* no process switch */
  508. }
  509. } else
  510. { depth--;
  511. if (oX->pc->status & D_ATOM)
  512. non_fatal("stmnt in d_step blocks", (char *)0);
  513. if (X->pc->n->ntyp == '@'
  514. && X->pid == (nproc-nstop-1))
  515. { if (X != run)
  516. Y->nxt = X->nxt;
  517. else
  518. run = X->nxt;
  519. nstop++;
  520. Priority_Sum -= X->priority;
  521. if (verbose&4)
  522. { whoruns(1);
  523. dotag(stdout, "terminates\n");
  524. }
  525. LastX = X;
  526. if (!interactive) Tval = 0;
  527. if (nproc == nstop) break;
  528. memset(is_blocked, 0, 256);
  529. } else
  530. { if (p_blocked(X->pid))
  531. { if (Tval) break;
  532. Tval = 1;
  533. if (depth >= jumpsteps)
  534. { oX = X;
  535. X = (RunList *) 0; /* to suppress indent */
  536. dotag(stdout, "timeout\n");
  537. X = oX;
  538. } } } }
  539. Y = X;
  540. pickproc();
  541. notbeyond = 0;
  542. }
  543. context = ZS;
  544. wrapup(0);
  545. }
  546. int
  547. complete_rendez(void)
  548. { RunList *orun = X, *tmp;
  549. Element *s_was = LastStep;
  550. Element *e;
  551. int j, ointer = interactive;
  552. if (s_trail)
  553. return 1;
  554. if (orun->pc->status & D_ATOM)
  555. fatal("rv-attempt in d_step sequence", (char *)0);
  556. Rvous = 1;
  557. interactive = 0;
  558. j = (int) Rand()%Priority_Sum; /* randomize start point */
  559. X = run;
  560. while (j - X->priority >= 0)
  561. { j -= X->priority;
  562. X = X->nxt;
  563. if (!X) X = run;
  564. }
  565. for (j = nproc - nstop; j > 0; j--)
  566. { if (X != orun
  567. && (!X->prov || eval(X->prov))
  568. && (e = eval_sub(X->pc)))
  569. { if (TstOnly)
  570. { X = orun;
  571. Rvous = 0;
  572. goto out;
  573. }
  574. if ((verbose&32) || (verbose&4))
  575. { tmp = orun; orun = X; X = tmp;
  576. if (!s_was) s_was = X->pc;
  577. p_talk(s_was, 1);
  578. printf(" [");
  579. comment(stdout, s_was->n, 0);
  580. printf("]\n");
  581. tmp = orun; orun = X; X = tmp;
  582. if (!LastStep) LastStep = X->pc;
  583. p_talk(LastStep, 1);
  584. printf(" [");
  585. comment(stdout, LastStep->n, 0);
  586. printf("]\n");
  587. }
  588. Rvous = 0; /* before silent_moves */
  589. X->pc = silent_moves(e);
  590. out: interactive = ointer;
  591. return 1;
  592. }
  593. X = X->nxt;
  594. if (!X) X = run;
  595. }
  596. Rvous = 0;
  597. X = orun;
  598. interactive = ointer;
  599. return 0;
  600. }
  601. /***** Runtime - Local Variables *****/
  602. static void
  603. addsymbol(RunList *r, Symbol *s)
  604. { Symbol *t;
  605. int i;
  606. for (t = r->symtab; t; t = t->next)
  607. if (strcmp(t->name, s->name) == 0)
  608. return; /* it's already there */
  609. t = (Symbol *) emalloc(sizeof(Symbol));
  610. t->name = s->name;
  611. t->type = s->type;
  612. t->hidden = s->hidden;
  613. t->nbits = s->nbits;
  614. t->nel = s->nel;
  615. t->ini = s->ini;
  616. t->setat = depth;
  617. t->context = r->n;
  618. if (s->type != STRUCT)
  619. { if (s->val) /* if already initialized, copy info */
  620. { t->val = (int *) emalloc(s->nel*sizeof(int));
  621. for (i = 0; i < s->nel; i++)
  622. t->val[i] = s->val[i];
  623. } else
  624. (void) checkvar(t, 0); /* initialize it */
  625. } else
  626. { if (s->Sval)
  627. fatal("saw preinitialized struct %s", s->name);
  628. t->Slst = s->Slst;
  629. t->Snm = s->Snm;
  630. t->owner = s->owner;
  631. /* t->context = r->n; */
  632. }
  633. t->next = r->symtab; /* add it */
  634. r->symtab = t;
  635. }
  636. static void
  637. setlocals(RunList *r)
  638. { Ordered *walk;
  639. Symbol *sp;
  640. RunList *oX = X;
  641. X = r;
  642. for (walk = all_names; walk; walk = walk->next)
  643. { sp = walk->entry;
  644. if (sp
  645. && sp->context
  646. && strcmp(sp->context->name, r->n->name) == 0
  647. && sp->Nid >= 0
  648. && (sp->type == UNSIGNED
  649. || sp->type == BIT
  650. || sp->type == MTYPE
  651. || sp->type == BYTE
  652. || sp->type == CHAN
  653. || sp->type == SHORT
  654. || sp->type == INT
  655. || sp->type == STRUCT))
  656. { if (!findloc(sp))
  657. non_fatal("setlocals: cannot happen '%s'",
  658. sp->name);
  659. }
  660. }
  661. X = oX;
  662. }
  663. static void
  664. oneparam(RunList *r, Lextok *t, Lextok *a, ProcList *p)
  665. { int k; int at, ft;
  666. RunList *oX = X;
  667. if (!a)
  668. fatal("missing actual parameters: '%s'", p->n->name);
  669. if (t->sym->nel != 1)
  670. fatal("array in parameter list, %s", t->sym->name);
  671. k = eval(a->lft);
  672. at = Sym_typ(a->lft);
  673. X = r; /* switch context */
  674. ft = Sym_typ(t);
  675. if (at != ft && (at == CHAN || ft == CHAN))
  676. { char buf[128], tag1[64], tag2[64];
  677. (void) sputtype(tag1, ft);
  678. (void) sputtype(tag2, at);
  679. sprintf(buf, "type-clash in params of %s(..), (%s<-> %s)",
  680. p->n->name, tag1, tag2);
  681. non_fatal("%s", buf);
  682. }
  683. t->ntyp = NAME;
  684. addsymbol(r, t->sym);
  685. (void) setval(t, k);
  686. X = oX;
  687. }
  688. static void
  689. setparams(RunList *r, ProcList *p, Lextok *q)
  690. { Lextok *f, *a; /* formal and actual pars */
  691. Lextok *t; /* list of pars of 1 type */
  692. if (q)
  693. { lineno = q->ln;
  694. Fname = q->fn;
  695. }
  696. for (f = p->p, a = q; f; f = f->rgt) /* one type at a time */
  697. for (t = f->lft; t; t = t->rgt, a = (a)?a->rgt:a)
  698. { if (t->ntyp != ',')
  699. oneparam(r, t, a, p); /* plain var */
  700. else
  701. oneparam(r, t->lft, a, p); /* expanded struct */
  702. }
  703. }
  704. Symbol *
  705. findloc(Symbol *s)
  706. { Symbol *r;
  707. if (!X)
  708. { /* fatal("error, cannot eval '%s' (no proc)", s->name); */
  709. return ZS;
  710. }
  711. for (r = X->symtab; r; r = r->next)
  712. if (strcmp(r->name, s->name) == 0)
  713. break;
  714. if (!r)
  715. { addsymbol(X, s);
  716. r = X->symtab;
  717. }
  718. return r;
  719. }
  720. int
  721. in_bound(Symbol *r, int n)
  722. {
  723. if (!r) return 0;
  724. if (n >= r->nel || n < 0)
  725. { printf("spin: indexing %s[%d] - size is %d\n",
  726. r->name, n, r->nel);
  727. non_fatal("indexing array \'%s\'", r->name);
  728. return 0;
  729. }
  730. return 1;
  731. }
  732. int
  733. getlocal(Lextok *sn)
  734. { Symbol *r, *s = sn->sym;
  735. int n = eval(sn->lft);
  736. r = findloc(s);
  737. if (r && r->type == STRUCT)
  738. return Rval_struct(sn, r, 1); /* 1 = check init */
  739. if (in_bound(r, n))
  740. return cast_val(r->type, r->val[n], r->nbits);
  741. return 0;
  742. }
  743. int
  744. setlocal(Lextok *p, int m)
  745. { Symbol *r = findloc(p->sym);
  746. int n = eval(p->lft);
  747. if (in_bound(r, n))
  748. { if (r->type == STRUCT)
  749. (void) Lval_struct(p, r, 1, m); /* 1 = check init */
  750. else
  751. {
  752. #if 0
  753. if (r->nbits > 0)
  754. m = (m & ((1<<r->nbits)-1));
  755. r->val[n] = m;
  756. #else
  757. r->val[n] = cast_val(r->type, m, r->nbits);
  758. #endif
  759. r->setat = depth;
  760. } }
  761. return 1;
  762. }
  763. void
  764. whoruns(int lnr)
  765. { if (!X) return;
  766. if (lnr) printf("%3d: ", depth);
  767. printf("proc ");
  768. if (Have_claim && X->pid == 0)
  769. printf(" -");
  770. else
  771. printf("%2d", X->pid - Have_claim);
  772. printf(" (%s) ", X->n->name);
  773. }
  774. static void
  775. talk(RunList *r)
  776. {
  777. if ((verbose&32) || (verbose&4))
  778. { p_talk(r->pc, 1);
  779. printf("\n");
  780. if (verbose&1) dumpglobals();
  781. if (verbose&2) dumplocal(r);
  782. }
  783. }
  784. void
  785. p_talk(Element *e, int lnr)
  786. { static int lastnever = -1;
  787. int newnever = -1;
  788. if (e && e->n)
  789. newnever = e->n->ln;
  790. if (Have_claim && X && X->pid == 0
  791. && lastnever != newnever && e)
  792. { if (xspin)
  793. { printf("MSC: ~G line %d\n", newnever);
  794. #if 0
  795. printf("%3d: proc - (NEVER) line %d \"never\" ",
  796. depth, newnever);
  797. printf("(state 0)\t[printf('MSC: never\\\\n')]\n");
  798. } else
  799. { printf("%3d: proc - (NEVER) line %d \"never\"\n",
  800. depth, newnever);
  801. #endif
  802. }
  803. lastnever = newnever;
  804. }
  805. whoruns(lnr);
  806. if (e)
  807. { printf("line %3d %s (state %d)",
  808. e->n?e->n->ln:-1,
  809. e->n?e->n->fn->name:"-",
  810. e->seqno);
  811. if (!xspin
  812. && ((e->status&ENDSTATE) || has_lab(e, 2))) /* 2=end */
  813. { printf(" <valid end state>");
  814. }
  815. }
  816. }
  817. int
  818. remotelab(Lextok *n)
  819. { int i;
  820. lineno = n->ln;
  821. Fname = n->fn;
  822. if (n->sym->type != 0 && n->sym->type != LABEL)
  823. { printf("spin: error, type: %d\n", n->sym->type);
  824. fatal("not a labelname: '%s'", n->sym->name);
  825. }
  826. if (n->indstep >= 0)
  827. { fatal("remote ref to label '%s' inside d_step",
  828. n->sym->name);
  829. }
  830. if ((i = find_lab(n->sym, n->lft->sym, 1)) == 0)
  831. fatal("unknown labelname: %s", n->sym->name);
  832. return i;
  833. }
  834. int
  835. remotevar(Lextok *n)
  836. { int prno, i, added=0;
  837. RunList *Y, *oX;
  838. Lextok *onl;
  839. Symbol *os;
  840. lineno = n->ln;
  841. Fname = n->fn;
  842. if (!n->lft->lft)
  843. prno = f_pid(n->lft->sym->name);
  844. else
  845. { prno = eval(n->lft->lft); /* pid - can cause recursive call */
  846. #if 0
  847. if (n->lft->lft->ntyp == CONST) /* user-guessed pid */
  848. #endif
  849. { prno += Have_claim;
  850. added = Have_claim;
  851. } }
  852. if (prno < 0)
  853. return 0; /* non-existing process */
  854. #if 0
  855. i = nproc - nstop;
  856. for (Y = run; Y; Y = Y->nxt)
  857. { --i;
  858. printf(" %s: i=%d, prno=%d, ->pid=%d\n", Y->n->name, i, prno, Y->pid);
  859. }
  860. #endif
  861. i = nproc - nstop;
  862. for (Y = run; Y; Y = Y->nxt)
  863. if (--i == prno)
  864. { if (strcmp(Y->n->name, n->lft->sym->name) != 0)
  865. { printf("spin: remote reference error on '%s[%d]'\n",
  866. n->lft->sym->name, prno-added);
  867. non_fatal("refers to wrong proctype '%s'", Y->n->name);
  868. }
  869. if (strcmp(n->sym->name, "_p") == 0)
  870. { if (Y->pc)
  871. return Y->pc->seqno;
  872. /* harmless, can only happen with -t */
  873. return 0;
  874. }
  875. #if 1
  876. /* new 4.0 allow remote variables */
  877. oX = X;
  878. X = Y;
  879. onl = n->lft;
  880. n->lft = n->rgt;
  881. os = n->sym;
  882. n->sym = findloc(n->sym);
  883. i = getval(n);
  884. n->sym = os;
  885. n->lft = onl;
  886. X = oX;
  887. return i;
  888. #else
  889. break;
  890. #endif
  891. }
  892. printf("remote ref: %s[%d] ", n->lft->sym->name, prno-added);
  893. non_fatal("%s not found", n->sym->name);
  894. printf("have only:\n");
  895. i = nproc - nstop - 1;
  896. for (Y = run; Y; Y = Y->nxt, i--)
  897. if (!strcmp(Y->n->name, n->lft->sym->name))
  898. printf("\t%d\t%s\n", i, Y->n->name);
  899. return 0;
  900. }