sched.c 21 KB

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