sched.c 23 KB

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