ref: 28e9566dc539244b3b429c21c556d656733839c2
parent: 077e719dfbf9bf2582bed80026251cc0d108c16e
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed Nov 22 16:09:31 EST 2017
spin: Update to most recent version. (thanks Ori_B) from Ori_B: There were a small number of changes needed from the tarball on spinroot.org: - The mkfile needed to be updated - Memory.h needed to not be included - It needed to invoke /bin/cpp instead of gcc -E - It depended on `yychar`, which our yacc doesn't provide. I'm still figuring out how to use spin, but it seems to do the right thing when testing a few of the examples: % cd $home/src/Spin/Examples/ % spin -a peterson.pml % pcc pan.c -D_POSIX_SOURCE % ./6.out (Spin Version 6.4.7 -- 19 August 2017) + Partial Order Reduction Full statespace search for: never claim - (none specified) assertion violations + acceptance cycles - (not selected) invalid end states + State-vector 32 byte, depth reached 24, errors: 0 40 states, stored 27 states, matched 67 transitions (= stored+matched) 0 atomic steps hash conflicts: 0 (resolved) Stats on memory usage (in Megabytes): 0.002 equivalent memory usage for states (stored*(State-vector + overhead)) 0.292 actual memory usage for states 128.000 memory used for hash table (-w24) 0.534 memory used for DFS stack (-m10000) 128.730 total actual memory usage unreached in proctype user /tmp/Spin/Examples/peterson.pml:20, state 10, "-end-" (1 of 10 states) pan: elapsed time 1.25 seconds pan: rate 32 states/second
--- a/sys/src/cmd/spin/dstep.c
+++ b/sys/src/cmd/spin/dstep.c
@@ -1,20 +1,18 @@
/***** spin: dstep.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
+#include <assert.h>
#include "spin.h"
#include "y.tab.h"
-#define MAXDSTEP 1024 /* was 512 */
+#define MAXDSTEP 2048 /* was 512 */
-char *NextLab[64];
+char *NextLab[64]; /* must match value in pangen2.c:41 */
int Level=0, GenCode=0, IsGuard=0, TestOnly=0;
static int Tj=0, Jt=0, LastGoto=0;
@@ -21,7 +19,7 @@
static int Tojump[MAXDSTEP], Jumpto[MAXDSTEP], Special[MAXDSTEP];
static void putCode(FILE *, Element *, Element *, Element *, int);
-extern int Pid, claimnr, separate, OkBreak;
+extern int Pid, separate, OkBreak;
static void
Sourced(int n, int special)
@@ -59,7 +57,7 @@
if (Tojump[j] == Jumpto[i])
break;
if (j == Tj)
- { char buf[12];
+ { char buf[16];
if (Jumpto[i] == OkBreak)
{ if (!LastGoto)
fprintf(fd, "S_%.3d_0: /* break-dest */\n",
@@ -80,10 +78,11 @@
}
for (j = i = 0; j < Tj; j++)
if (Special[j])
- { Tojump[i] = Tojump[j];
+ { if (i >= MAXDSTEP)
+ { fatal("cannot happen (dstep.c)", (char *)0);
+ }
+ Tojump[i] = Tojump[j];
Special[i] = 2;
- if (i >= MAXDSTEP)
- fatal("cannot happen (dstep.c)", (char *)0);
i++;
}
Tj = i; /* keep only the global exit-labels */
@@ -164,7 +163,7 @@
break;
case ELSE:
if (inh++ > 0) fprintf(fd, " || ");
-/* 4.2.5 */ if (Pid != claimnr)
+/* 4.2.5 */ if (!pid_is_claim(Pid))
fprintf(fd, "(boq == -1 /* else */)");
else
fprintf(fd, "(1 /* else */)");
@@ -184,7 +183,7 @@
case 's':
if (inh++ > 0) fprintf(fd, " || ");
fprintf(fd, "("); TestOnly=1;
-/* 4.2.1 */ if (Pid != claimnr) fprintf(fd, "(boq == -1) && ");
+/* 4.2.1 */ if (!pid_is_claim(Pid)) fprintf(fd, "(boq == -1) && ");
putstmnt(fd, ee->n, ee->seqno);
fprintf(fd, ")"); TestOnly=0;
break;
@@ -191,10 +190,10 @@
case 'c':
if (inh++ > 0) fprintf(fd, " || ");
fprintf(fd, "("); TestOnly=1;
- if (Pid != claimnr)
+ if (!pid_is_claim(Pid))
fprintf(fd, "(boq == -1 && ");
putstmnt(fd, ee->n->lft, e->seqno);
- if (Pid != claimnr)
+ if (!pid_is_claim(Pid))
fprintf(fd, ")");
fprintf(fd, ")"); TestOnly=0;
break;
@@ -204,7 +203,8 @@
int
putcode(FILE *fd, Sequence *s, Element *nxt, int justguards, int ln, int seqno)
-{ int isg=0; char buf[64];
+{ int isg=0;
+ static char buf[64];
NextLab[0] = "continue";
filterbad(s->frst);
@@ -215,6 +215,7 @@
return putcode(fd, s->frst->n->sl->this, nxt, 0, ln, seqno);
case NON_ATOMIC:
(void) putcode(fd, s->frst->n->sl->this, ZE, 1, ln, seqno);
+ if (justguards) return 0; /* 6.2.5 */
break;
case IF:
fprintf(fd, "if (!(");
@@ -245,7 +246,7 @@
case 's':
fprintf(fd, "if (");
#if 1
-/* 4.2.1 */ if (Pid != claimnr) fprintf(fd, "(boq != -1) || ");
+/* 4.2.1 */ if (!pid_is_claim(Pid)) fprintf(fd, "(boq != -1) || ");
#endif
fprintf(fd, "!("); TestOnly=1;
putstmnt(fd, s->frst->n, s->frst->seqno);
@@ -253,7 +254,7 @@
break;
case 'c':
fprintf(fd, "if (!(");
- if (Pid != claimnr) fprintf(fd, "boq == -1 && ");
+ if (!pid_is_claim(Pid)) fprintf(fd, "boq == -1 && ");
TestOnly=1;
putstmnt(fd, s->frst->n->lft, s->frst->seqno);
fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
@@ -262,19 +263,31 @@
fprintf(fd, "if (boq != -1 || (");
if (separate != 2) fprintf(fd, "trpt->");
fprintf(fd, "o_pm&1))\n\t\t\tcontinue;");
+ { extern FILE *th;
+ fprintf(th, "#ifndef ELSE_IN_GUARD\n");
+ fprintf(th, " #define ELSE_IN_GUARD\n");
+ fprintf(th, "#endif\n");
+ }
break;
case ASGN: /* new 3.0.8 */
fprintf(fd, "IfNotBlocked");
break;
+ default:
+ fprintf(fd, "/* default %d */\n\t\t", s->frst->n->ntyp);
}
+
+ /* 6.2.5 : before TstOnly */
+ fprintf(fd, "\n\n\t\treached[%d][%d] = 1;\n\t\t", Pid, seqno);
+ fprintf(fd, "reached[%d][t->st] = 1;\n\t\t", Pid); /* next state */
+ fprintf(fd, "reached[%d][tt] = 1;\n", Pid); /* current state */
+
+ /* 6.2.5 : before sv_save() */
+ if (s->frst->n->ntyp != NON_ATOMIC)
+ fprintf(fd, "\n\t\tif (TstOnly) return 1;\n"); /* if called from enabled() */
+
if (justguards) return 0;
fprintf(fd, "\n\t\tsv_save();\n\t\t");
-#if 1
- fprintf(fd, "reached[%d][%d] = 1;\n\t\t", Pid, seqno);
- fprintf(fd, "reached[%d][t->st] = 1;\n\t\t", Pid); /* true next state */
- fprintf(fd, "reached[%d][tt] = 1;\n", Pid); /* true current state */
-#endif
sprintf(buf, "Uerror(\"block in d_step seq, line %d\")", ln);
NextLab[0] = buf;
putCode(fd, s->frst, s->extent, nxt, isg);
@@ -359,7 +372,7 @@
case '.':
if (LastGoto) break;
if (e->nxt && (e->nxt->status & DONE2))
- { i = e->nxt?e->nxt->Seqno:0;
+ { i = e->nxt->Seqno;
fprintf(fd, "\t\tgoto S_%.3d_0;", i);
fprintf(fd, " /* '.' */\n");
Dested(i);
@@ -375,7 +388,7 @@
break;
}
i = e->nxt?e->nxt->Seqno:0;
- if (e->nxt && e->nxt->status & DONE2 && !LastGoto)
+ if (e->nxt && (e->nxt->status & DONE2) && !LastGoto)
{ fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
fprintf(fd, "/* ';' */\n");
Dested(i);
--- a/sys/src/cmd/spin/flow.c
+++ b/sys/src/cmd/spin/flow.c
@@ -1,24 +1,24 @@
/***** spin: flow.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include "spin.h"
#include "y.tab.h"
extern Symbol *Fname;
-extern int nr_errs, lineno, verbose;
-extern short has_unless, has_badelse;
+extern int nr_errs, lineno, verbose, in_for, old_scope_rules, s_trail;
+extern short has_unless, has_badelse, has_xu;
+extern char CurScope[MAXSCOPESZ];
Element *Al_El = ZE;
Label *labtab = (Label *) 0;
-int Unique=0, Elcnt=0, DstepStart = -1;
+int Unique = 0, Elcnt = 0, DstepStart = -1;
+int initialization_ok = 1;
+short has_accept;
static Lbreak *breakstack = (Lbreak *) 0;
static Lextok *innermost;
@@ -37,10 +37,16 @@
open_seq(int top)
{ SeqList *t;
Sequence *s = (Sequence *) emalloc(sizeof(Sequence));
+ s->minel = -1;
t = seqlist(s, cur_s);
cur_s = t;
- if (top) Elcnt = 1;
+ if (top)
+ { Elcnt = 1;
+ initialization_ok = 1;
+ } else
+ { initialization_ok = 0;
+ }
}
void
@@ -84,6 +90,7 @@
&& a->indstep != b->indstep)
{ lineno = a->ln;
Fname = a->fn;
+ if (!s_trail)
fatal("jump into d_step sequence", (char *) 0);
}
}
@@ -113,8 +120,8 @@
&& n->ntyp != PRINT
&& n->ntyp != PRINTM)
{ if (verbose&32)
- printf("spin: line %d %s, redundant skip\n",
- n->ln, n->fn->name);
+ printf("spin: %s:%d, redundant skip\n",
+ n->fn->name, n->ln);
if (e != s->frst
&& e != s->last
&& e != s->extent)
@@ -147,7 +154,11 @@
{ Sequence *s = cur_s->this;
Symbol *z;
- if (nottop > 0 && (z = has_lab(s->frst, 0)))
+ if (nottop == 0) /* end of proctype body */
+ { initialization_ok = 1;
+ }
+
+ if (nottop > 0 && s->frst && (z = has_lab(s->frst, 0)))
{ printf("error: (%s:%d) label %s placed incorrectly\n",
(s->frst->n)?s->frst->n->fn->name:"-",
(s->frst->n)?s->frst->n->ln:0,
@@ -183,12 +194,12 @@
printf("\"Label: { statement ... }\"\n");
break;
case 6:
- printf("=====>instead of\n");
+ printf("=====> instead of\n");
printf(" do (or if)\n");
printf(" :: ...\n");
printf(" :: Label: statement\n");
printf(" od (of fi)\n");
- printf("=====>always use\n");
+ printf("=====> use\n");
printf("Label: do (or if)\n");
printf(" :: ...\n");
printf(" :: statement\n");
@@ -198,8 +209,9 @@
printf("cannot happen - labels\n");
break;
}
- alldone(1);
- }
+ if (nottop != 6)
+ { alldone(1);
+ } }
if (nottop == 4
&& !Rjumpslocal(s->frst, s->last))
@@ -217,13 +229,14 @@
do_unless(Lextok *No, Lextok *Es)
{ SeqList *Sl;
Lextok *Re = nn(ZN, UNLESS, ZN, ZN);
+
Re->ln = No->ln;
Re->fn = No->fn;
-
has_unless++;
+
if (Es->ntyp == NON_ATOMIC)
- Sl = Es->sl;
- else
+ { Sl = Es->sl;
+ } else
{ open_seq(0); add_seq(Es);
Sl = seqlist(close_seq(1), 0);
}
@@ -348,6 +361,31 @@
} }
}
+void
+popbreak(void)
+{
+ if (!breakstack)
+ fatal("cannot happen, breakstack", (char *) 0);
+
+ breakstack = breakstack->nxt; /* pop stack */
+}
+
+static Lbreak *ob = (Lbreak *) 0;
+
+void
+safe_break(void)
+{
+ ob = breakstack;
+ popbreak();
+}
+
+void
+restore_break(void)
+{
+ breakstack = ob;
+ ob = (Lbreak *) 0;
+}
+
static Element *
if_seq(Lextok *n)
{ int tok = n->ntyp;
@@ -388,8 +426,13 @@
&& prev_z->this->frst->n->ntyp == ELSE)
{ prev_z->this->frst->n->val = 1;
has_badelse++;
- non_fatal("dubious use of 'else' combined with i/o,",
- (char *)0);
+ if (has_xu)
+ { fatal("invalid use of 'else' combined with i/o and xr/xs assertions,",
+ (char *)0);
+ } else
+ { non_fatal("dubious use of 'else' combined with i/o,",
+ (char *)0);
+ }
nr_errs--;
}
@@ -396,13 +439,13 @@
e->n = nn(n, tok, ZN, ZN);
e->n->sl = s; /* preserve as info only */
e->sub = s;
- for (z = s; z; prev_z = z, z = z->nxt)
+ for (z = s; z; z = z->nxt)
add_el(t, z->this); /* append target */
if (tok == DO)
{ add_el(t, cur_s->this); /* target upfront */
t = new_el(nn(n, BREAK, ZN, ZN)); /* break target */
set_lab(break_dest(), t); /* new exit */
- breakstack = breakstack->nxt; /* pop stack */
+ popbreak();
}
add_el(e, cur_s->this);
add_el(t, cur_s->this);
@@ -563,33 +606,86 @@
void
set_lab(Symbol *s, Element *e)
{ Label *l; extern Symbol *context;
+ int cur_uiid = is_inline();
if (!s) return;
+
for (l = labtab; l; l = l->nxt)
- if (l->s == s && l->c == context)
+ { if (strcmp(l->s->name, s->name) == 0
+ && l->c == context
+ && (old_scope_rules || strcmp((const char *) s->bscp, (const char *) l->s->bscp) == 0)
+ && l->uiid == cur_uiid)
{ non_fatal("label %s redeclared", s->name);
break;
- }
+ } }
+
+ if (strncmp(s->name, "accept", 6) == 0
+ && strncmp(s->name, "accept_all", 10) != 0)
+ { has_accept = 1;
+ }
+
l = (Label *) emalloc(sizeof(Label));
l->s = s;
l->c = context;
l->e = e;
+ l->uiid = cur_uiid;
l->nxt = labtab;
labtab = l;
}
+static Label *
+get_labspec(Lextok *n)
+{ Symbol *s = n->sym;
+ Label *l, *anymatch = (Label *) 0;
+ int ln;
+ /*
+ * try to find a label with the same inline id (uiid)
+ * but if it doesn't exist, return any other match
+ * within the same scope
+ */
+ for (l = labtab; l; l = l->nxt)
+ { if (strcmp(l->s->name, s->name) == 0 /* labelname matches */
+ && s->context == l->s->context) /* same scope */
+ {
+#if 0
+ if (anymatch && n->uiid == anymatch->uiid)
+ { if (0) non_fatal("label %s re-declared", s->name);
+ }
+ if (0)
+ { printf("Label %s uiid now::then %d :: %d bcsp %s :: %s\n",
+ s->name, n->uiid, l->uiid, s->bscp, l->s->bscp);
+ printf("get_labspec match on %s %s (bscp goto %s - label %s)\n",
+ s->name, s->context->name, s->bscp, l->s->bscp);
+ }
+#endif
+ /* same block scope */
+ if (strcmp((const char *) s->bscp, (const char *) l->s->bscp) == 0)
+ { return l; /* definite match */
+ }
+ /* higher block scope */
+ ln = strlen((const char *) l->s->bscp);
+ if (strncmp((const char *) s->bscp, (const char *) l->s->bscp, ln) == 0)
+ { anymatch = l; /* possible match */
+ } else if (!anymatch)
+ { anymatch = l; /* somewhere else in same context */
+ } } }
+
+ return anymatch; /* return best match */
+}
+
Element *
get_lab(Lextok *n, int md)
-{ Label *l;
- Symbol *s = n->sym;
+{ Label *l = get_labspec(n);
- for (l = labtab; l; l = l->nxt)
- if (s == l->s)
- return (l->e);
+ if (l != (Label *) 0)
+ { return (l->e);
+ }
- lineno = n->ln;
- Fname = n->fn;
- if (md) fatal("undefined label %s", s->name);
+ if (md)
+ { lineno = n->ln;
+ Fname = n->fn;
+ fatal("undefined label %s", n->sym->name);
+ }
return ZE;
}
@@ -670,21 +766,46 @@
}
l->e->status |= CHECK2; /* treat as if global */
if (l->e->status & (ATOM | L_ATOM | D_ATOM))
- { non_fatal("cannot reference label inside atomic or d_step (%s)",
- c->name);
+ { printf("spin: %s:%d, warning, reference to label ",
+ Fname->name, lineno);
+ printf("from inside atomic or d_step (%s)\n", c->name);
}
}
int
find_lab(Symbol *s, Symbol *c, int markit)
-{ Label *l;
+{ Label *l, *pm = (Label *) 0, *apm = (Label *) 0;
+ int ln;
+ /* generally called for remote references in never claims */
for (l = labtab; l; l = l->nxt)
- { if (strcmp(s->name, l->s->name) == 0
+ {
+ if (strcmp(s->name, l->s->name) == 0
&& strcmp(c->name, l->c->name) == 0)
- { l->visible |= markit;
- return (l->e->seqno);
- } }
+ { ln = strlen((const char *) l->s->bscp);
+ if (0)
+ { printf("want '%s' in context '%s', scope ref '%s' - label '%s'\n",
+ s->name, c->name, s->bscp, l->s->bscp);
+ }
+ /* same or higher block scope */
+ if (strcmp((const char *) s->bscp, (const char *) l->s->bscp) == 0)
+ { pm = l; /* definite match */
+ break;
+ }
+ if (strncmp((const char *) s->bscp, (const char *) l->s->bscp, ln) == 0)
+ { pm = l; /* possible match */
+ } else
+ { apm = l; /* remote */
+ } } }
+
+ if (pm)
+ { pm->visible |= markit;
+ return pm->e->seqno;
+ }
+ if (apm)
+ { apm->visible |= markit;
+ return apm->e->seqno;
+ } /* else printf("Not Found\n"); */
return 0;
}
@@ -735,6 +856,226 @@
}
}
+#if 0
+static int depth = 0;
+void dump_sym(Symbol *, char *);
+
+void
+dump_lex(Lextok *t, char *s)
+{ int i;
+
+ depth++;
+ printf(s);
+ for (i = 0; i < depth; i++)
+ printf("\t");
+ explain(t->ntyp);
+ if (t->ntyp == NAME) printf(" %s ", t->sym->name);
+ if (t->ntyp == CONST) printf(" %d ", t->val);
+ if (t->ntyp == STRUCT)
+ { dump_sym(t->sym, "\n:Z:");
+ }
+ if (t->lft)
+ { dump_lex(t->lft, "\nL");
+ }
+ if (t->rgt)
+ { dump_lex(t->rgt, "\nR");
+ }
+ depth--;
+}
+void
+dump_sym(Symbol *z, char *s)
+{ int i;
+ char txt[64];
+ depth++;
+ printf(s);
+ for (i = 0; i < depth; i++)
+ printf("\t");
+
+ if (z->type == CHAN)
+ { if (z->ini && z->ini->rgt && z->ini->rgt->sym)
+ { /* dump_sym(z->ini->rgt->sym, "\n:I:"); -- could also be longer list */
+ if (z->ini->rgt->rgt
+ || !z->ini->rgt->sym)
+ fatal("chan %s in for should have only one field (a typedef)", z->name);
+ printf(" -- %s %p -- ", z->ini->rgt->sym->name, z->ini->rgt->sym);
+ }
+ } else if (z->type == STRUCT)
+ { if (z->Snm)
+ printf(" == %s %p == ", z->Snm->name, z->Snm);
+ else
+ { if (z->Slst)
+ dump_lex(z->Slst, "\n:X:");
+ if (z->ini)
+ dump_lex(z->ini, "\n:I:");
+ }
+ }
+ depth--;
+
+}
+#endif
+
+int
+match_struct(Symbol *s, Symbol *t)
+{
+ if (!t
+ || !t->ini
+ || !t->ini->rgt
+ || !t->ini->rgt->sym
+ || t->ini->rgt->rgt)
+ { fatal("chan %s in for should have only one field (a typedef)", t?t->name:"--");
+ }
+ /* we already know that s is a STRUCT */
+ if (0)
+ { printf("index type %s %p ==\n", s->Snm->name, s->Snm);
+ printf("chan type %s %p --\n\n", t->ini->rgt->sym->name, t->ini->rgt->sym);
+ }
+
+ return (s->Snm == t->ini->rgt->sym);
+}
+
+void
+valid_name(Lextok *a3, Lextok *a5, Lextok *a8, char *tp)
+{
+ if (a3->ntyp != NAME)
+ { fatal("%s ( .name : from .. to ) { ... }", tp);
+ }
+ if (a3->sym->type == CHAN
+ || a3->sym->type == STRUCT
+ || a3->sym->isarray != 0)
+ { fatal("bad index in for-construct %s", a3->sym->name);
+ }
+ if (a5->ntyp == CONST && a8->ntyp == CONST && a5->val > a8->val)
+ { non_fatal("start value for %s exceeds end-value", a3->sym->name);
+ }
+}
+
+void
+for_setup(Lextok *a3, Lextok *a5, Lextok *a8)
+{ /* for ( a3 : a5 .. a8 ) */
+
+ valid_name(a3, a5, a8, "for");
+ /* a5->ntyp = a8->ntyp = CONST; */
+ add_seq(nn(a3, ASGN, a3, a5)); /* start value */
+ open_seq(0);
+ add_seq(nn(ZN, 'c', nn(a3, LE, a3, a8), ZN)); /* condition */
+}
+
+Lextok *
+for_index(Lextok *a3, Lextok *a5)
+{ Lextok *z0, *z1, *z2, *z3;
+ Symbol *tmp_cnt;
+ char tmp_nm[MAXSCOPESZ+16];
+ /* for ( a3 in a5 ) { ... } */
+
+ if (a3->ntyp != NAME)
+ { fatal("for ( .name in name ) { ... }", (char *) 0);
+ }
+
+ if (a5->ntyp != NAME)
+ { fatal("for ( %s in .name ) { ... }", a3->sym->name);
+ }
+
+ if (a3->sym->type == STRUCT)
+ { if (a5->sym->type != CHAN)
+ { fatal("for ( %s in .channel_name ) { ... }",
+ a3->sym->name);
+ }
+ z0 = a5->sym->ini;
+ if (!z0
+ || z0->val <= 0
+ || z0->rgt->ntyp != STRUCT
+ || z0->rgt->rgt != NULL)
+ { fatal("bad channel type %s in for", a5->sym->name);
+ }
+
+ if (!match_struct(a3->sym, a5->sym))
+ { fatal("type of %s does not match chan", a3->sym->name);
+ }
+
+ z1 = nn(ZN, CONST, ZN, ZN); z1->val = 0;
+ z2 = nn(a5, LEN, a5, ZN);
+
+ sprintf(tmp_nm, "_f0r_t3mp%s", CurScope); /* make sure it's unique */
+ tmp_cnt = lookup(tmp_nm);
+ if (z0->val > 255) /* check nr of slots, i.e. max length */
+ { tmp_cnt->type = SHORT; /* should be rare */
+ } else
+ { tmp_cnt->type = BYTE;
+ }
+ z3 = nn(ZN, NAME, ZN, ZN);
+ z3->sym = tmp_cnt;
+
+ add_seq(nn(z3, ASGN, z3, z1)); /* start value 0 */
+
+ open_seq(0);
+
+ add_seq(nn(ZN, 'c', nn(z3, LT, z3, z2), ZN)); /* condition */
+
+ /* retrieve message from the right slot -- for now: rotate contents */
+ in_for = 0;
+ add_seq(nn(a5, 'r', a5, expand(a3, 1))); /* receive */
+ add_seq(nn(a5, 's', a5, expand(a3, 1))); /* put back in to rotate */
+ in_for = 1;
+ return z3;
+ } else
+ { if (a5->sym->isarray == 0
+ || a5->sym->nel <= 0)
+ { fatal("bad arrayname %s", a5->sym->name);
+ }
+ z1 = nn(ZN, CONST, ZN, ZN); z1->val = 0;
+ z2 = nn(ZN, CONST, ZN, ZN); z2->val = a5->sym->nel - 1;
+ for_setup(a3, z1, z2);
+ return a3;
+ }
+}
+
+Lextok *
+for_body(Lextok *a3, int with_else)
+{ Lextok *t1, *t2, *t0, *rv;
+
+ rv = nn(ZN, CONST, ZN, ZN); rv->val = 1;
+ rv = nn(ZN, '+', a3, rv);
+ rv = nn(a3, ASGN, a3, rv);
+ add_seq(rv); /* initial increment */
+
+ /* completed loop body, main sequence */
+ t1 = nn(ZN, 0, ZN, ZN);
+ t1->sq = close_seq(8);
+
+ open_seq(0); /* add else -> break sequence */
+ if (with_else)
+ { add_seq(nn(ZN, ELSE, ZN, ZN));
+ }
+ t2 = nn(ZN, GOTO, ZN, ZN);
+ t2->sym = break_dest();
+ add_seq(t2);
+ t2 = nn(ZN, 0, ZN, ZN);
+ t2->sq = close_seq(9);
+
+ t0 = nn(ZN, 0, ZN, ZN);
+ t0->sl = seqlist(t2->sq, seqlist(t1->sq, 0));
+
+ rv = nn(ZN, DO, ZN, ZN);
+ rv->sl = t0->sl;
+
+ return rv;
+}
+
+Lextok *
+sel_index(Lextok *a3, Lextok *a5, Lextok *a7)
+{ /* select ( a3 : a5 .. a7 ) */
+
+ valid_name(a3, a5, a7, "select");
+ /* a5->ntyp = a7->ntyp = CONST; */
+
+ add_seq(nn(a3, ASGN, a3, a5)); /* start value */
+ open_seq(0);
+ add_seq(nn(ZN, 'c', nn(a3, LT, a3, a7), ZN)); /* condition */
+
+ pushbreak(); /* new 6.2.1 */
+ return for_body(a3, 0); /* no else, just a non-deterministic break */
+}
+
static void
walk_atomic(Element *a, Element *b, int added)
{ Element *f; Symbol *ofn; int oln;
@@ -747,8 +1088,8 @@
switch (f->n->ntyp) {
case ATOMIC:
if (verbose&32)
- printf("spin: warning, line %3d %s, atomic inside %s (ignored)\n",
- f->n->ln, f->n->fn->name, (added)?"d_step":"atomic");
+ printf("spin: %s:%d, warning, atomic inside %s (ignored)\n",
+ f->n->fn->name, f->n->ln, (added)?"d_step":"atomic");
goto mknonat;
case D_STEP:
if (!(verbose&32))
@@ -755,8 +1096,8 @@
{ if (added) goto mknonat;
break;
}
- printf("spin: warning, line %3d %s, d_step inside ",
- f->n->ln, f->n->fn->name);
+ printf("spin: %s:%d, warning, d_step inside ",
+ f->n->fn->name, f->n->ln);
if (added)
{ printf("d_step (ignored)\n");
goto mknonat;
@@ -770,8 +1111,8 @@
break;
case UNLESS:
if (added)
- { printf("spin: error, line %3d %s, unless in d_step (ignored)\n",
- f->n->ln, f->n->fn->name);
+ { printf("spin: error, %s:%d, unless in d_step (ignored)\n",
+ f->n->fn->name, f->n->ln);
}
}
for (h = f->sub; h; h = h->nxt)
@@ -789,6 +1130,15 @@
for (l = labtab; l; l = l->nxt)
if (l->c != 0 && l->s->name[0] != ':')
- printf("label %s %d <%s>\n",
- l->s->name, l->e->seqno, l->c->name);
+ { printf("label %s %d ",
+ l->s->name, l->e->seqno);
+ if (l->uiid == 0)
+ printf("<%s>", l->c->name);
+ else
+ printf("<%s i%d>", l->c->name, l->uiid);
+ if (!old_scope_rules)
+ { printf("\t{scope %s}", l->s->bscp);
+ }
+ printf("\n");
+ }
}
--- a/sys/src/cmd/spin/guided.c
+++ b/sys/src/cmd/spin/guided.c
@@ -1,17 +1,15 @@
/***** spin: guided.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include "spin.h"
#include <sys/types.h>
#include <sys/stat.h>
+#include <limits.h>
#include "y.tab.h"
extern RunList *run, *X;
@@ -19,8 +17,9 @@
extern Symbol *Fname, *oFname;
extern int verbose, lineno, xspin, jumpsteps, depth, merger, cutoff;
extern int nproc, nstop, Tval, ntrail, columns;
-extern short Have_claim, Skip_claim;
+extern short Have_claim, Skip_claim, has_code;
extern void ana_src(int, int);
+extern char **trailfilename;
int TstOnly = 0, pno;
@@ -73,6 +72,53 @@
return (!Have_claim || !X || X->pid != 0);
}
+int globmin = INT_MAX;
+int globmax = 0;
+
+int
+find_min(Sequence *s)
+{ SeqList *l;
+ Element *e;
+
+ if (s->minel < 0)
+ { s->minel = INT_MAX;
+ for (e = s->frst; e; e = e->nxt)
+ { if (e->status & 512)
+ { continue;
+ }
+ e->status |= 512;
+
+ if (e->n->ntyp == ATOMIC
+ || e->n->ntyp == NON_ATOMIC
+ || e->n->ntyp == D_STEP)
+ { int n = find_min(e->n->sl->this);
+ if (n < s->minel)
+ { s->minel = n;
+ }
+ } else if (e->Seqno < s->minel)
+ { s->minel = e->Seqno;
+ }
+ for (l = e->sub; l; l = l->nxt)
+ { int n = find_min(l->this);
+ if (n < s->minel)
+ { s->minel = n;
+ } } }
+ }
+ if (s->minel < globmin)
+ { globmin = s->minel;
+ }
+ return s->minel;
+}
+
+int
+find_max(Sequence *s)
+{
+ if (s->last->Seqno > globmax)
+ { globmax = s->last->Seqno;
+ }
+ return s->last->Seqno;
+}
+
void
match_trail(void)
{ int i, a, nst;
@@ -79,6 +125,17 @@
Element *dothis;
char snap[512], *q;
+ if (has_code)
+ { printf("spin: important:\n");
+ printf(" =======================================warning====\n");
+ printf(" this model contains embedded c code statements\n");
+ printf(" these statements will not be executed when the trail\n");
+ printf(" is replayed in this way -- they are just printed,\n");
+ printf(" which will likely lead to inaccurate variable values.\n");
+ printf(" for an accurate replay use: ./pan -r\n");
+ printf(" =======================================warning====\n\n");
+ }
+
/*
* if source model name is leader.pml
* look for the trail file under these names:
@@ -88,10 +145,18 @@
* leader.tra
*/
- if (ntrail)
- sprintf(snap, "%s%d.trail", oFname->name, ntrail);
- else
- sprintf(snap, "%s.trail", oFname->name);
+ if (trailfilename)
+ { if (strlen(*trailfilename) < sizeof(snap))
+ { strcpy(snap, (const char *) *trailfilename);
+ } else
+ { fatal("filename %s too long", *trailfilename);
+ }
+ } else
+ { if (ntrail)
+ sprintf(snap, "%s%d.trail", oFname->name, ntrail);
+ else
+ sprintf(snap, "%s.trail", oFname->name);
+ }
if ((fd = fopen(snap, "r")) == NULL)
{ snap[strlen(snap)-2] = '\0'; /* .tra */
@@ -118,9 +183,9 @@
} }
okay:
if (xspin == 0 && newer(oFname->name, snap))
- printf("spin: warning, \"%s\" is newer than %s\n",
- oFname->name, snap);
-
+ { printf("spin: warning, \"%s\" is newer than %s\n",
+ oFname->name, snap);
+ }
Tval = 1;
/*
@@ -132,10 +197,23 @@
hookup();
while (fscanf(fd, "%d:%d:%d\n", &depth, &pno, &nst) == 3)
- { if (depth == -2) { start_claim(pno); continue; }
- if (depth == -4) { merger = 1; ana_src(0, 1); continue; }
- if (depth == -1)
+ { if (depth == -2)
{ if (verbose)
+ { printf("starting claim %d\n", pno);
+ }
+ start_claim(pno);
+ continue;
+ }
+ if (depth == -4)
+ { if (verbose)
+ { printf("using statement merging\n");
+ }
+ merger = 1;
+ ana_src(0, 1);
+ continue;
+ }
+ if (depth == -1)
+ { if (1 || verbose)
{ if (columns == 2)
dotag(stdout, " CYCLE>\n");
else
@@ -188,16 +266,50 @@
pno - Have_claim, i, nst, dothis->n->ntyp);
lost_trail();
}
+
+ if (0 && !xspin && (verbose&32))
+ { printf("step %d i=%d pno %d stmnt %d\n", depth, i, pno, nst);
+ }
+
for (X = run; X; X = X->nxt)
{ if (--i == pno)
break;
}
+
if (!X)
- { printf("%3d: no process %d ", depth, pno - Have_claim);
- printf("(state %d)\n", nst);
- lost_trail();
+ { if (verbose&32)
+ { printf("%3d: no process %d (stmnt %d)\n", depth, pno - Have_claim, nst);
+ printf(" max %d (%d - %d + %d) claim %d ",
+ nproc - nstop + Skip_claim,
+ nproc, nstop, Skip_claim, Have_claim);
+ printf("active processes:\n");
+ for (X = run; X; X = X->nxt)
+ { printf("\tpid %d\tproctype %s\n", X->pid, X->n->name);
+ }
+ printf("\n");
+ continue;
+ } else
+ { printf("%3d:\tproc %d (?) ", depth, pno);
+ lost_trail();
+ }
+ } else
+ { int min_seq = find_min(X->ps);
+ int max_seq = find_max(X->ps);
+
+
+ if (nst < min_seq || nst > max_seq)
+ { printf("%3d: error: invalid statement", depth);
+ if (verbose&32)
+ { printf(": pid %d:%d (%s:%d:%d) stmnt %d (valid range %d .. %d)",
+ pno, X->pid, X->n->name, X->tn, X->b, nst, min_seq, max_seq);
+ }
+ printf("\n");
+ continue;
+ /* lost_trail(); */
+ }
+ X->pc = dothis;
}
- X->pc = dothis;
+
lineno = dothis->n->ln;
Fname = dothis->n->fn;
@@ -271,7 +383,7 @@
} }
if (Have_claim && X && X->pid == 0
- && dothis && dothis->n
+ && dothis->n
&& lastclaim != dothis->n->ln)
{ lastclaim = dothis->n->ln;
if (columns == 2)
--- a/sys/src/cmd/spin/main.c
+++ b/sys/src/cmd/spin/main.c
@@ -1,25 +1,23 @@
/***** spin: main.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include <stdlib.h>
+#include <assert.h>
#include "spin.h"
#include "version.h"
+#include <sys/types.h>
+#include <sys/stat.h>
#include <signal.h>
-/* #include <malloc.h> */
#include <time.h>
#ifdef PC
-#include <io.h>
-extern int unlink(const char *);
+ #include <io.h>
#else
-#include <unistd.h>
+ #include <unistd.h>
#endif
#include "y.tab.h"
@@ -29,7 +27,13 @@
extern char *claimproc;
extern void repro_src(void);
extern void qhide(int);
+extern char CurScope[MAXSCOPESZ];
+extern short has_provided, has_code, has_ltl, has_accept;
+extern int realread, buzzed;
+static void add_comptime(char *);
+static void add_runtime(char *);
+
Symbol *Fname, *oFname;
int Etimeouts; /* nr timeouts in program */
@@ -40,12 +44,19 @@
int no_print, no_wrapup, Caccess, limited_vis, like_java;
int separate; /* separate compilation */
int export_ast; /* pangen5.c */
-int inlineonly; /* show inlined code */
-int seedy; /* be verbose about chosen seed */
+int norecompile; /* main.c */
+int old_scope_rules; /* use pre 5.3.0 rules */
+int old_priority_rules; /* use pre 6.2.0 rules */
+int product, Strict;
+short replay;
-int dataflow = 1, merger = 1, deadvar = 1, ccache = 1;
+int merger = 1, deadvar = 1, implied_semis = 1;
+int ccache = 0; /* oyvind teig: 5.2.0 case caching off by default */
-static int preprocessonly, SeedUsed;
+static int preprocessonly, SeedUsed, itsr, itsr_n;
+static int seedy; /* be verbose about chosen seed */
+static int inlineonly; /* show inlined code */
+static int dataflow = 1;
#if 0
meaning of flags on verbose:
@@ -61,99 +72,515 @@
static char Operator[] = "operator: ";
static char Keyword[] = "keyword: ";
static char Function[] = "function-name: ";
-static char **add_ltl = (char **)0;
-static char **ltl_file = (char **)0;
-static char **nvr_file = (char **)0;
+static char **add_ltl = (char **) 0;
+static char **ltl_file = (char **) 0;
+static char **nvr_file = (char **) 0;
+static char *ltl_claims = (char *) 0;
+static char *pan_runtime = "";
+static char *pan_comptime = "";
+static char formula[4096];
+static FILE *fd_ltl = (FILE *) 0;
static char *PreArg[64];
static int PreCnt = 0;
static char out1[64];
-static void explain(int);
-#ifndef CPP
- /* OS2: "spin -Picc -E/Pd+ -E/Q+" */
- /* Visual C++: "spin -PCL -E/E */
-#ifdef PC
-#define CPP "gcc -E -x c" /* most systems have gcc anyway */
- /* else use "cpp" */
-#else
-#ifdef SOLARIS
-#define CPP "/usr/ccs/lib/cpp"
-#else
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
-#define CPP "cpp"
-#else
-#define CPP "/bin/cpp" /* classic Unix systems */
-#endif
-#endif
-#endif
+char **trailfilename; /* new option 'k' */
-#endif
-static char *PreProc = CPP;
+void explain(int);
+
+#define CPP "/bin/cpp" /* sometimes: "/lib/cpp" */
+
+static char PreProc[512];
extern int depth; /* at least some steps were made */
+int
+WhatSeed(void)
+{
+ return SeedUsed;
+}
+
void
+final_fiddle(void)
+{ char *has_a, *has_l, *has_f;
+
+ /* no -a or -l but has_accept: add -a */
+ /* no -a or -l in pan_runtime: add -DSAFETY to pan_comptime */
+ /* -a or -l but no -f then add -DNOFAIR */
+
+ has_a = strstr(pan_runtime, "-a");
+ has_l = strstr(pan_runtime, "-l");
+ has_f = strstr(pan_runtime, "-f");
+
+ if (!has_l && !has_a && strstr(pan_comptime, "-DNP"))
+ { add_runtime("-l");
+ has_l = strstr(pan_runtime, "-l");
+ }
+
+ if (!has_a && !has_l
+ && !strstr(pan_comptime, "-DSAFETY"))
+ { if (has_accept
+ && !strstr(pan_comptime, "-DBFS")
+ && !strstr(pan_comptime, "-DNOCLAIM"))
+ { add_runtime("-a");
+ has_a = pan_runtime;
+ } else
+ { add_comptime("-DSAFETY");
+ } }
+
+ if ((has_a || has_l) && !has_f
+ && !strstr(pan_comptime, "-DNOFAIR"))
+ { add_comptime("-DNOFAIR");
+ }
+}
+
+static int
+change_param(char *t, char *what, int range, int bottom)
+{ char *ptr;
+ int v;
+
+ assert(range < 1000 && range > 0);
+ if ((ptr = strstr(t, what)) != NULL)
+ { ptr += strlen(what);
+ if (!isdigit((int) *ptr))
+ { return 0;
+ }
+ v = atoi(ptr) + 1; /* was: v = (atoi(ptr)+1)%range */
+ if (v >= range)
+ { v = bottom;
+ }
+ if (v >= 100)
+ { *ptr++ = '0' + (v/100); v %= 100;
+ *ptr++ = '0' + (v/10);
+ *ptr = '0' + (v%10);
+ } else if (v >= 10)
+ { *ptr++ = '0' + (v/10);
+ *ptr++ = '0' + (v%10);
+ *ptr = ' ';
+ } else
+ { *ptr++ = '0' + v;
+ *ptr++ = ' ';
+ *ptr = ' ';
+ } }
+ return 1;
+}
+
+static void
+change_rs(char *t)
+{ char *ptr;
+ int cnt = 0;
+ long v;
+
+ if ((ptr = strstr(t, "-RS")) != NULL)
+ { ptr += 3;
+ /* room for at least 10 digits */
+ v = Rand()%1000000000L;
+ while (v/10 > 0)
+ { *ptr++ = '0' + v%10;
+ v /= 10;
+ cnt++;
+ }
+ *ptr++ = '0' + v;
+ cnt++;
+ while (cnt++ < 10)
+ { *ptr++ = ' ';
+ } }
+}
+
+int
+omit_str(char *in, char *s)
+{ char *ptr = strstr(in, s);
+ int i, nr = -1;
+
+ if (ptr)
+ { for (i = 0; i < (int) strlen(s); i++)
+ { *ptr++ = ' ';
+ }
+ if (isdigit((int) *ptr))
+ { nr = atoi(ptr);
+ while (isdigit((int) *ptr))
+ { *ptr++ = ' ';
+ } } }
+ return nr;
+}
+
+void
+string_trim(char *t)
+{ int n = strlen(t) - 1;
+
+ while (n > 0 && t[n] == ' ')
+ { t[n--] = '\0';
+ }
+}
+
+int
+e_system(int v, const char *s)
+{ static int count = 1;
+ /* v == 0 : checks to find non-linked version of gcc */
+ /* v == 1 : all other commands */
+ /* v == 2 : preprocessing the promela input */
+
+ if (v == 1)
+ { if (verbose&(32|64)) /* -v or -w */
+ { printf("cmd%02d: %s\n", count++, s);
+ fflush(stdout);
+ }
+ if (verbose&64) /* only -w */
+ { return 0; /* suppress the call to system(s) */
+ } }
+ return system(s);
+}
+
+void
alldone(int estatus)
-{
- if (preprocessonly == 0
- && strlen(out1) > 0)
- (void) unlink((const char *)out1);
+{ char *ptr;
+#if defined(WIN32) || defined(WIN64)
+ struct _stat x;
+#else
+ struct stat x;
+#endif
+ if (preprocessonly == 0 && strlen(out1) > 0)
+ { (void) unlink((const char *) out1);
+ }
- if (seedy && !analyze && !export_ast
+ (void) unlink(TMP_FILE1);
+ (void) unlink(TMP_FILE2);
+
+ if (!buzzed && seedy && !analyze && !export_ast
&& !s_trail && !preprocessonly && depth > 0)
- printf("seed used: %d\n", SeedUsed);
+ { printf("seed used: %d\n", SeedUsed);
+ }
- if (xspin && (analyze || s_trail))
+ if (!buzzed && xspin && (analyze || s_trail))
{ if (estatus)
- printf("spin: %d error(s) - aborting\n",
- estatus);
- else
- printf("Exit-Status 0\n");
+ { printf("spin: %d error(s) - aborting\n",
+ estatus);
+ } else
+ { printf("Exit-Status 0\n");
+ } }
+
+ if (buzzed && replay && !has_code && !estatus)
+ { extern QH *qh;
+ QH *j;
+ int i;
+ char *tmp = (char *) emalloc(strlen("spin -t") +
+ strlen(pan_runtime) + strlen(Fname->name) + 8);
+ pan_runtime = (char *) emalloc(2048); /* more than enough */
+ sprintf(pan_runtime, "-n%d ", SeedUsed);
+ if (jumpsteps)
+ { sprintf(&pan_runtime[strlen(pan_runtime)], "-j%d ", jumpsteps);
+ }
+ if (trailfilename)
+ { sprintf(&pan_runtime[strlen(pan_runtime)], "-k%s ", *trailfilename);
+ }
+ if (cutoff)
+ { sprintf(&pan_runtime[strlen(pan_runtime)], "-u%d ", cutoff);
+ }
+ for (i = 1; i <= PreCnt; i++)
+ { strcat(pan_runtime, PreArg[i]);
+ strcat(pan_runtime, " ");
+ }
+ for (j = qh; j; j = j->nxt)
+ { sprintf(&pan_runtime[strlen(pan_runtime)], "-q%d ", j->n);
+ }
+ if (strcmp(PreProc, CPP) != 0)
+ { sprintf(&pan_runtime[strlen(pan_runtime)], "\"-P%s\" ", PreProc);
+ }
+ /* -oN options 1..5 are ignored in simulations */
+ if (old_priority_rules) strcat(pan_runtime, "-o6 ");
+ if (!implied_semis) strcat(pan_runtime, "-o7 ");
+ if (no_print) strcat(pan_runtime, "-b ");
+ if (no_wrapup) strcat(pan_runtime, "-B ");
+ if (columns == 1) strcat(pan_runtime, "-c ");
+ if (columns == 2) strcat(pan_runtime, "-M ");
+ if (seedy == 1) strcat(pan_runtime, "-h ");
+ if (like_java == 1) strcat(pan_runtime, "-J ");
+ if (old_scope_rules) strcat(pan_runtime, "-O ");
+ if (notabs) strcat(pan_runtime, "-T ");
+ if (verbose&1) strcat(pan_runtime, "-g ");
+ if (verbose&2) strcat(pan_runtime, "-l ");
+ if (verbose&4) strcat(pan_runtime, "-p ");
+ if (verbose&8) strcat(pan_runtime, "-r ");
+ if (verbose&16) strcat(pan_runtime, "-s ");
+ if (verbose&32) strcat(pan_runtime, "-v ");
+ if (verbose&64) strcat(pan_runtime, "-w ");
+ if (m_loss) strcat(pan_runtime, "-m ");
+ sprintf(tmp, "spin -t %s %s", pan_runtime, Fname->name);
+ estatus = e_system(1, tmp); /* replay */
+ exit(estatus); /* replay without c_code */
}
+
+ if (buzzed && (!replay || has_code) && !estatus)
+ { char *tmp, *tmp2 = NULL, *P_X;
+ char *C_X = (buzzed == 2) ? "-O" : "";
+
+ if (replay && strlen(pan_comptime) == 0)
+ {
+#if defined(WIN32) || defined(WIN64)
+ P_X = "pan";
+#else
+ P_X = "./pan";
+#endif
+ if (stat(P_X, (struct stat *)&x) < 0)
+ { goto recompile; /* no executable pan for replay */
+ }
+ tmp = (char *) emalloc(8 + strlen(P_X) + strlen(pan_runtime) +4);
+ /* the final +4 is too allow adding " &" in some cases */
+ sprintf(tmp, "%s %s", P_X, pan_runtime);
+ goto runit;
+ }
+#if defined(WIN32) || defined(WIN64)
+ P_X = "-o pan pan.c && pan";
+#else
+ P_X = "-o pan pan.c && ./pan";
+#endif
+ /* swarm and biterate randomization additions */
+ if (!replay && itsr) /* iterative search refinement */
+ { if (!strstr(pan_comptime, "-DBITSTATE"))
+ { add_comptime("-DBITSTATE");
+ }
+ if (!strstr(pan_comptime, "-DPUTPID"))
+ { add_comptime("-DPUTPID");
+ }
+ if (!strstr(pan_comptime, "-DT_RAND")
+ && !strstr(pan_comptime, "-DT_REVERSE"))
+ { add_runtime("-T0 "); /* controls t_reverse */
+ }
+ if (!strstr(pan_runtime, "-P") /* runtime flag */
+ || pan_runtime[2] < '0'
+ || pan_runtime[2] > '1') /* no -P0 or -P1 */
+ { add_runtime("-P0 "); /* controls p_reverse */
+ }
+ if (!strstr(pan_runtime, "-w"))
+ { add_runtime("-w18 "); /* -w18 = 256K */
+ } else
+ { char nv[32];
+ int x;
+ x = omit_str(pan_runtime, "-w");
+ if (x >= 0)
+ { sprintf(nv, "-w%d ", x);
+ add_runtime(nv); /* added spaces */
+ } }
+ if (!strstr(pan_runtime, "-h"))
+ { add_runtime("-h0 "); /* 0..499 */
+ /* leave 2 spaces for increments up to -h499 */
+ } else if (!strstr(pan_runtime, "-hash"))
+ { char nv[32];
+ int x;
+ x = omit_str(pan_runtime, "-h");
+ if (x >= 0)
+ { sprintf(nv, "-h%d ", x%500);
+ add_runtime(nv); /* added spaces */
+ } }
+ if (!strstr(pan_runtime, "-k"))
+ { add_runtime("-k1 "); /* 1..3 */
+ } else
+ { char nv[32];
+ int x;
+ x = omit_str(pan_runtime, "-k");
+ if (x >= 0)
+ { sprintf(nv, "-k%d ", x%4);
+ add_runtime(nv); /* added spaces */
+ } }
+ if (strstr(pan_runtime, "-p_rotate"))
+ { char nv[32];
+ int x;
+ x = omit_str(pan_runtime, "-p_rotate");
+ if (x < 0)
+ { x = 0;
+ }
+ sprintf(nv, "-p_rotate%d ", x%256);
+ add_runtime(nv); /* added spaces */
+ } else if (strstr(pan_runtime, "-p_permute") == 0)
+ { add_runtime("-p_rotate0 ");
+ }
+ if (strstr(pan_runtime, "-RS"))
+ { (void) omit_str(pan_runtime, "-RS");
+ }
+ /* need room for at least 10 digits */
+ add_runtime("-RS1234567890 ");
+ change_rs(pan_runtime);
+ }
+recompile:
+ if (strstr(PreProc, "cpp")) /* unix/linux */
+ { strcpy(PreProc, "gcc"); /* need compiler */
+ } else if ((tmp = strstr(PreProc, "-E")) != NULL)
+ { *tmp = '\0'; /* strip preprocessing flags */
+ }
+
+ final_fiddle();
+ tmp = (char *) emalloc(8 + /* account for alignment */
+ strlen(PreProc) +
+ strlen(C_X) +
+ strlen(pan_comptime) +
+ strlen(P_X) +
+ strlen(pan_runtime) +
+ strlen(" -p_reverse & "));
+ tmp2 = tmp;
+
+ /* P_X ends with " && ./pan " */
+ sprintf(tmp, "%s %s %s %s %s",
+ PreProc, C_X, pan_comptime, P_X, pan_runtime);
+
+ if (!replay)
+ { if (itsr < 0) /* swarm only */
+ { strcat(tmp, " &"); /* after ./pan */
+ itsr = -itsr; /* now same as biterate */
+ }
+ /* do compilation first
+ * split cc command from run command
+ * leave cc in tmp, and set tmp2 to run
+ */
+ if ((ptr = strstr(tmp, " && ")) != NULL)
+ { tmp2 = ptr + 4; /* first run */
+ *ptr = '\0';
+ } }
+
+ if (has_ltl)
+ { (void) unlink("_spin_nvr.tmp");
+ }
+ if (!norecompile)
+ {
+#ifdef PC
+ /* make sure that if compilation fails we do not continue */
+ (void) unlink("./pan.exe");
+#else
+ (void) unlink("./pan");
+#endif
+ }
+runit:
+ if (norecompile && tmp != tmp2)
+ { estatus = 0;
+ } else
+ { if (itsr > 0) /* else it happens below */
+ { estatus = e_system(1, tmp); /* compile or run */
+ } }
+ if (replay || estatus < 0)
+ { goto skipahead;
+ }
+ /* !replay */
+ if (itsr == 0) /* single run */
+ { estatus = e_system(1, tmp2);
+ } else if (itsr > 0) /* iterative search refinement */
+ { int is_swarm = 0;
+ if (tmp2 != tmp) /* swarm: did only compilation so far */
+ { tmp = tmp2; /* now we point to the run command */
+ estatus = e_system(1, tmp); /* first run */
+ }
+ itsr--; /* count down */
+
+ /* the following are added back randomly later */
+ (void) omit_str(tmp, "-p_reverse"); /* replaced by spaces */
+ (void) omit_str(tmp, "-p_normal");
+
+ if (strstr(tmp, " &") != NULL)
+ { (void) omit_str(tmp, " &");
+ is_swarm = 1;
+ }
+
+ /* increase -w every itsr_n-th run */
+ if ((itsr_n > 0 && (itsr == 0 || (itsr%itsr_n) != 0))
+ || (change_param(tmp, "-w", 36, 18) >= 0)) /* max 4G bit statespace */
+ { (void) change_param(tmp, "-h", 500, 0); /* hash function 0.499 */
+ (void) change_param(tmp, "-p_rotate", 256, 0); /* if defined */
+ (void) change_param(tmp, "-k", 4, 1); /* nr bits per state 0->1,2,3 */
+ (void) change_param(tmp, "-T", 2, 0); /* with or without t_reverse*/
+ (void) change_param(tmp, "-P", 2, 0); /* -P 0..1 != p_reverse */
+ change_rs(tmp); /* change random seed */
+ string_trim(tmp);
+ if (rand()%5 == 0) /* 20% of all runs */
+ { strcat(tmp, " -p_reverse ");
+ /* at end, so this overrides -p_rotateN, if there */
+ /* but -P0..1 disable this in 50% of the cases */
+ /* so its really activated in 10% of all runs */
+ } else if (rand()%6 == 0) /* override p_rotate and p_reverse */
+ { strcat(tmp, " -p_normal ");
+ }
+ if (is_swarm)
+ { strcat(tmp, " &");
+ }
+ goto runit;
+ } }
+skipahead:
+ (void) unlink("pan.b");
+ (void) unlink("pan.c");
+ (void) unlink("pan.h");
+ (void) unlink("pan.m");
+ (void) unlink("pan.p");
+ (void) unlink("pan.t");
+ }
exit(estatus);
}
+#if 0
+ -P0 normal active process creation
+ -P1 reversed order for *active* process creation != p_reverse
+ -T0 normal transition exploration
+ -T1 reversed order of transition exploration
+
+ -DP_RAND (random starting point +- -DP_REVERSE)
+ -DPERMUTED (also enables -p_rotateN and -p_reverse)
+ -DP_REVERSE (same as -DPERMUTED with -p_reverse, but 7% faster)
+
+ -DT_RAND (random starting point -- optionally with -T0..1)
+ -DT_REVERSE (superseded by -T0..1 options)
+
+ -hash generates new hash polynomial for -h0
+
+ permutation modes:
+ -permuted (adds -DPERMUTED) -- this is also the default with -swarm
+ -t_reverse (same as -T1)
+ -p_reverse (similar to -P1)
+ -p_rotateN
+ -p_normal
+
+ less useful would be (since there is less non-determinism in transitions):
+ -t_rotateN -- a controlled version of -DT_RAND
+
+ compiling with -DPERMUTED enables a number of new runtime options,
+ that -swarmN,M will also exploit:
+ -p_permute (default)
+ -p_rotateN
+ -p_reverse
+#endif
+
void
preprocess(char *a, char *b, int a_tmp)
-{ char precmd[512], cmd[1024]; int i;
+{ char precmd[1024], cmd[2048];
+ int i;
#ifdef PC
- extern int try_zpp(char *, char *);
- if (PreCnt == 0 && try_zpp(a, b)) goto out;
+ /* gcc is sometimes a symbolic link to gcc-4
+ that does not work well in cygwin, so we try
+ to use the actual executable that is used.
+ the code below assumes we are on a cygwin-like system
+ */
+ if (strncmp(PreProc, "gcc ", strlen("gcc ")) == 0)
+ { if (e_system(0, "gcc-4 --version > pan.pre") == 0)
+ { strcpy(PreProc, "gcc-4 -std=gnu99 -E -x c");
+ } else if (e_system(0, "gcc-3 --version > pan.pre") == 0)
+ { strcpy(PreProc, "gcc-3 -std=gnu99 -E -x c");
+ } }
#endif
+
+ assert(strlen(PreProc) < sizeof(precmd));
strcpy(precmd, PreProc);
for (i = 1; i <= PreCnt; i++)
{ strcat(precmd, " ");
strcat(precmd, PreArg[i]);
}
+ if (strlen(precmd) > sizeof(precmd))
+ { fprintf(stdout, "spin: too many -D args, aborting\n");
+ alldone(1);
+ }
sprintf(cmd, "%s %s > %s", precmd, a, b);
- if (system((const char *)cmd))
+ if (e_system(2, (const char *)cmd)) /* preprocessing */
{ (void) unlink((const char *) b);
if (a_tmp) (void) unlink((const char *) a);
fprintf(stdout, "spin: preprocessing failed\n"); /* 4.1.2 was stderr */
alldone(1); /* no return, error exit */
}
-#ifdef PC
-out:
-#endif
if (a_tmp) (void) unlink((const char *) a);
}
-FILE *
-cpyfile(char *src, char *tgt)
-{ FILE *inp, *out;
- char buf[1024];
-
- inp = fopen(src, "r");
- out = fopen(tgt, "w");
- if (!inp || !out)
- { printf("spin: cannot cp %s to %s\n", src, tgt);
- alldone(1);
- }
- while (fgets(buf, 1024, inp))
- fprintf(out, "%s", buf);
- fclose(inp);
- return out;
-}
-
void
usage(void)
{
@@ -168,33 +595,73 @@
printf("\t-d produce symbol-table information\n");
printf("\t-Dyyy pass -Dyyy to the preprocessor\n");
printf("\t-Eyyy pass yyy to the preprocessor\n");
+ printf("\t-e compute synchronous product of multiple never claims (modified by -L)\n");
printf("\t-f \"..formula..\" translate LTL ");
printf("into never claim\n");
- printf("\t-F file like -f, but with the LTL ");
- printf("formula stored in a 1-line file\n");
+ printf("\t-F file like -f, but with the LTL formula stored in a 1-line file\n");
printf("\t-g print all global variables\n");
- printf("\t-h at end of run, print value of seed for random nr generator used\n");
+ printf("\t-h at end of run, print value of seed for random nr generator used\n");
printf("\t-i interactive (random simulation)\n");
printf("\t-I show result of inlining and preprocessing\n");
printf("\t-J reverse eval order of nested unlesses\n");
printf("\t-jN skip the first N steps ");
printf("in simulation trail\n");
+ printf("\t-k fname use the trailfile stored in file fname, see also -t\n");
+ printf("\t-L when using -e, use strict language intersection\n");
printf("\t-l print all local variables\n");
- printf("\t-M print msc-flow in Postscript\n");
+ printf("\t-M generate msc-flow in tcl/tk format\n");
printf("\t-m lose msgs sent to full queues\n");
- printf("\t-N file use never claim stored in file\n");
+ printf("\t-N fname use never claim stored in file fname\n");
printf("\t-nN seed for random nr generator\n");
+ printf("\t-O use old scope rules (pre 5.3.0)\n");
printf("\t-o1 turn off dataflow-optimizations in verifier\n");
printf("\t-o2 don't hide write-only variables in verifier\n");
printf("\t-o3 turn off statement merging in verifier\n");
+ printf("\t-o4 turn on rendezvous optiomizations in verifier\n");
+ printf("\t-o5 turn on case caching (reduces size of pan.m, but affects reachability reports)\n");
+ printf("\t-o6 revert to the old rules for interpreting priority tags (pre version 6.2)\n");
+ printf("\t-o7 revert to the old rules for semi-colon usage (pre version 6.3)\n");
printf("\t-Pxxx use xxx for preprocessing\n");
printf("\t-p print all statements\n");
+ printf("\t-pp pretty-print (reformat) stdin, write stdout\n");
printf("\t-qN suppress io for queue N in printouts\n");
printf("\t-r print receive events\n");
+ printf("\t-replay replay an error trail-file found earlier\n");
+ printf("\t if the model contains embedded c-code, the ./pan executable is used\n");
+ printf("\t otherwise spin itself is used to replay the trailfile\n");
+ printf("\t note that pan recognizes different runtime options than spin itself\n");
+ printf("\t-search (or -run) generate a verifier, and compile and run it\n");
+ printf("\t options before -search are interpreted by spin to parse the input\n");
+ printf("\t options following a -search are used to compile and run the verifier pan\n");
+ printf("\t valid options that can follow a -search argument include:\n");
+ printf("\t -bfs perform a breadth-first search\n");
+ printf("\t -bfspar perform a parallel breadth-first search\n");
+ printf("\t -bcs use the bounded-context-switching algorithm\n");
+ printf("\t -bitstate or -bit, use bitstate storage\n");
+ printf("\t -biterate use bitstate with iterative search refinement (-w18..-w35)\n");
+ printf("\t -swarmN,M like -biterate, but running all iterations in parallel\n");
+ printf("\t perform N parallel runs and increment -w every M runs\n");
+ printf("\t default value for N is 10, default for M is 1\n");
+ printf("\t (add -w to see which commands will be executed)\n");
+ printf("\t (add -W if ./pan exists and need not be recompiled)\n");
+ printf("\t -link file.c link executable pan to file.c\n");
+ printf("\t -collapse use collapse state compression\n");
+ printf("\t -hc use hash-compact storage\n");
+ printf("\t -noclaim ignore all ltl and never claims\n");
+ printf("\t -p_permute use process scheduling order random permutation\n");
+ printf("\t -p_rotateN use process scheduling order rotation by N\n");
+ printf("\t -p_reverse use process scheduling order reversal\n");
+ printf("\t -ltl p verify the ltl property named p\n");
+ printf("\t -safety compile for safety properties only\n");
+ printf("\t -i use the dfs iterative shortening algorithm\n");
+ printf("\t -a search for acceptance cycles\n");
+ printf("\t -l search for non-progress cycles\n");
+ printf("\t similarly, a -D... parameter can be specified to modify the compilation\n");
+ printf("\t and any valid runtime pan argument can be specified for the verification\n");
printf("\t-S1 and -S2 separate pan source for claim and model\n");
printf("\t-s print send events\n");
printf("\t-T do not indent printf output\n");
- printf("\t-t[N] follow [Nth] simulation trail\n");
+ printf("\t-t[N] follow [Nth] simulation trail, see also -k\n");
printf("\t-Uyyy pass -Uyyy to the preprocessor\n");
printf("\t-uN stop a simulation run after N steps\n");
printf("\t-v verbose, more warnings\n");
@@ -204,8 +671,8 @@
alldone(1);
}
-void
-optimizations(char nr)
+int
+optimizations(int nr)
{
switch (nr) {
case '1':
@@ -243,37 +710,114 @@
printf("spin: case caching turned %s\n",
ccache?"on":"off");
break;
+ case '6':
+ old_priority_rules = 1;
+ if (verbose&32)
+ printf("spin: using old priority rules (pre version 6.2)\n");
+ return 0; /* no break */
+ case '7':
+ implied_semis = 0;
+ if (verbose&32)
+ printf("spin: no implied semi-colons (pre version 6.3)\n");
+ return 0; /* no break */
default:
printf("spin: bad or missing parameter on -o\n");
usage();
break;
}
+ return 1;
}
-#if 0
-static int
-Rename(const char *old, char *new)
-{ FILE *fo, *fn;
- char buf[1024];
+static void
+add_comptime(char *s)
+{ char *tmp;
- if ((fo = fopen(old, "r")) == NULL)
- { printf("spin: cannot open %s\n", old);
- return 1;
+ if (!s || strstr(pan_comptime, s))
+ { return;
}
- if ((fn = fopen(new, "w")) == NULL)
- { printf("spin: cannot create %s\n", new);
- fclose(fo);
- return 2;
+
+ tmp = (char *) emalloc(strlen(pan_comptime)+strlen(s)+2);
+ sprintf(tmp, "%s %s", pan_comptime, s);
+ pan_comptime = tmp;
+}
+
+static struct {
+ char *ifsee, *thendo;
+ int keeparg;
+} pats[] = {
+ { "-bfspar", "-DBFS_PAR", 0 },
+ { "-bfs", "-DBFS", 0 },
+ { "-bcs", "-DBCS", 0 },
+ { "-bitstate", "-DBITSTATE", 0 },
+ { "-bit", "-DBITSTATE", 0 },
+ { "-hc", "-DHC4", 0 },
+ { "-collapse", "-DCOLLAPSE", 0 },
+ { "-noclaim", "-DNOCLAIM", 0 },
+ { "-permuted", "-DPERMUTED", 0 },
+ { "-p_permute", "-DPERMUTED", 1 },
+ { "-p_rotate", "-DPERMUTED", 1 },
+ { "-p_reverse", "-DPERMUTED", 1 },
+ { "-safety", "-DSAFETY", 0 },
+ { "-i", "-DREACH", 1 },
+ { "-l", "-DNP", 1 },
+ { 0, 0 }
+};
+
+static void
+set_itsr_n(char *s) /* e.g., -swarm12,3 */
+{ char *tmp;
+
+ if ((tmp = strchr(s, ',')) != NULL)
+ { tmp++;
+ if (*tmp != '\0' && isdigit((int) *tmp))
+ { itsr_n = atoi(tmp);
+ if (itsr_n < 2)
+ { itsr_n = 0;
+ } } }
+}
+
+static void
+add_runtime(char *s)
+{ char *tmp;
+ int i;
+
+ if (strncmp(s, "-biterate", strlen("-biterate")) == 0)
+ { itsr = 10; /* default nr of sequential iterations */
+ if (isdigit((int) s[9]))
+ { itsr = atoi(&s[9]);
+ if (itsr < 1)
+ { itsr = 1;
+ }
+ set_itsr_n(s);
+ }
+ return;
}
- while (fgets(buf, 1024, fo))
- fputs(buf, fn);
+ if (strncmp(s, "-swarm", strlen("-swarm")) == 0)
+ { itsr = -10; /* parallel iterations */
+ if (isdigit((int) s[6]))
+ { itsr = atoi(&s[6]);
+ if (itsr < 1)
+ { itsr = 1;
+ }
+ itsr = -itsr;
+ set_itsr_n(s);
+ }
+ return;
+ }
- fclose(fo);
- fclose(fn);
+ for (i = 0; pats[i].ifsee; i++)
+ { if (strncmp(s, pats[i].ifsee, strlen(pats[i].ifsee)) == 0)
+ { add_comptime(pats[i].thendo);
+ if (pats[i].keeparg)
+ { break;
+ }
+ return;
+ } }
- return 0; /* success */
+ tmp = (char *) emalloc(strlen(pan_runtime)+strlen(s)+2);
+ sprintf(tmp, "%s %s", pan_runtime, s);
+ pan_runtime = tmp;
}
-#endif
int
main(int argc, char *argv[])
@@ -285,17 +829,16 @@
yyin = stdin;
yyout = stdout;
tl_out = stdout;
+ strcpy(CurScope, "_");
- /* unused flags: e, w, x, y, z, A, G, I, L, O, Q, R, S, T, W */
+ assert(strlen(CPP) < sizeof(PreProc));
+ strcpy(PreProc, CPP);
+
+ /* unused flags: y, z, G, L, Q, R, W */
while (argc > 1 && argv[1][0] == '-')
{ switch (argv[1][1]) {
-
- /* generate code for separate compilation: S1 or S2 */
- case 'S': separate = atoi(&argv[1][2]);
- /* fall through */
- case 'a': analyze = 1; break;
-
case 'A': export_ast = 1; break;
+ case 'a': analyze = 1; break;
case 'B': no_wrapup = 1; break;
case 'b': no_print = 1; break;
case 'C': Caccess = 1; break;
@@ -305,6 +848,7 @@
case 'd': dumptab = 1; break;
case 'E': PreArg[++PreCnt] = (char *) &argv[1][2];
break;
+ case 'e': product++; break; /* see also 'L' */
case 'F': ltl_file = (char **) (argv+2);
argc--; argv++; break;
case 'f': add_ltl = (char **) argv;
@@ -315,6 +859,10 @@
case 'I': inlineonly = 1; break;
case 'J': like_java = 1; break;
case 'j': jumpsteps = atoi(&argv[1][2]); break;
+ case 'k': s_trail = 1;
+ trailfilename = (char **) (argv+2);
+ argc--; argv++; break;
+ case 'L': Strict++; break; /* modified -e */
case 'l': verbose += 2; break;
case 'M': columns = 2; break;
case 'm': m_loss = 1; break;
@@ -321,28 +869,100 @@
case 'N': nvr_file = (char **) (argv+2);
argc--; argv++; break;
case 'n': T = atoi(&argv[1][2]); tl_terse = 1; break;
- case 'o': optimizations(argv[1][2]);
- usedopts = 1; break;
- case 'P': PreProc = (char *) &argv[1][2]; break;
- case 'p': verbose += 4; break;
- case 'q': if (isdigit(argv[1][2]))
+ case 'O': old_scope_rules = 1; break;
+ case 'o': usedopts += optimizations(argv[1][2]); break;
+ case 'P': assert(strlen((const char *) &argv[1][2]) < sizeof(PreProc));
+ strcpy(PreProc, (const char *) &argv[1][2]);
+ break;
+ case 'p': if (argv[1][2] == 'p')
+ { pretty_print();
+ alldone(0);
+ }
+ verbose += 4; break;
+ case 'q': if (isdigit((int) argv[1][2]))
qhide(atoi(&argv[1][2]));
break;
- case 'r': verbose += 8; break;
- case 's': verbose += 16; break;
+ case 'r':
+ if (strcmp(&argv[1][1], "run") == 0)
+ { Srand((unsigned int) T);
+samecase: if (buzzed != 0)
+ { fatal("cannot combine -x with -run -replay or -search", (char *)0);
+ }
+ buzzed = 2;
+ analyze = 1;
+ argc--; argv++;
+ /* process all remaining arguments as relating to pan: */
+ while (argc > 1 && argv[1][0] == '-')
+ { switch (argv[1][1]) {
+ case 'D': /* eg -DNP */
+ /* case 'E': conflicts with runtime arg */
+ case 'O': /* eg -O2 */
+ case 'U': /* to undefine a macro */
+ add_comptime(argv[1]);
+ break;
+ case 'l':
+ if (strcmp(&argv[1][1], "ltl") == 0)
+ { add_runtime("-N");
+ argc--; argv++;
+ add_runtime(argv[1]); /* prop name */
+ break;
+ }
+ if (strcmp(&argv[1][1], "link") == 0)
+ { argc--; argv++;
+ add_comptime(argv[1]);
+ break;
+ }
+ /* else fall through */
+ default:
+ add_runtime(argv[1]); /* -bfs etc. */
+ break;
+ }
+ argc--; argv++;
+ }
+ argc++; argv--;
+ } else if (strcmp(&argv[1][1], "replay") == 0)
+ { replay = 1;
+ add_runtime("-r");
+ goto samecase;
+ } else
+ { verbose += 8;
+ }
+ break;
+ case 'S': separate = atoi(&argv[1][2]); /* S1 or S2 */
+ /* generate code for separate compilation */
+ analyze = 1; break;
+ case 's':
+ if (strcmp(&argv[1][1], "simulate") == 0)
+ { break; /* ignore */
+ }
+ if (strcmp(&argv[1][1], "search") == 0)
+ { goto samecase;
+ }
+ verbose += 16; break;
case 'T': notabs = 1; break;
case 't': s_trail = 1;
- if (isdigit(argv[1][2]))
- ntrail = atoi(&argv[1][2]);
+ if (isdigit((int)argv[1][2]))
+ { ntrail = atoi(&argv[1][2]);
+ }
break;
case 'U': PreArg[++PreCnt] = (char *) &argv[1][0];
break; /* undefine */
- case 'u': cutoff = atoi(&argv[1][2]); break; /* new 3.4.14 */
+ case 'u': cutoff = atoi(&argv[1][2]); break;
case 'v': verbose += 32; break;
- case 'V': printf("%s\n", Version);
+ case 'V': printf("%s\n", SpinVersion);
alldone(0);
break;
case 'w': verbose += 64; break;
+ case 'W': norecompile = 1; break; /* 6.4.7: for swarm/biterate */
+ case 'x': /* internal - reserved use */
+ if (buzzed != 0)
+ { fatal("cannot combine -x with -run -search or -replay", (char *)0);
+ }
+ buzzed = 1; /* implies also -a -o3 */
+ pan_runtime = "-d";
+ analyze = 1;
+ usedopts += optimizations('3');
+ break;
case 'X': xspin = notabs = 1;
#ifndef PC
signal(SIGPIPE, alldone); /* not posix... */
@@ -355,54 +975,61 @@
}
argc--; argv++;
}
+
+ if (columns == 2 && !cutoff)
+ { cutoff = 1024;
+ }
+
if (usedopts && !analyze)
- printf("spin: warning -o[123] option ignored in simulations\n");
-
+ printf("spin: warning -o[1..5] option ignored in simulations\n");
+
if (ltl_file)
- { char formula[4096];
- add_ltl = ltl_file-2; add_ltl[1][1] = 'f';
+ { add_ltl = ltl_file-2; add_ltl[1][1] = 'f';
if (!(tl_out = fopen(*ltl_file, "r")))
{ printf("spin: cannot open %s\n", *ltl_file);
alldone(1);
}
- fgets(formula, 4096, tl_out);
+ if (!fgets(formula, 4096, tl_out))
+ { printf("spin: cannot read %s\n", *ltl_file);
+ }
fclose(tl_out);
tl_out = stdout;
*ltl_file = (char *) formula;
}
if (argc > 1)
- { char cmd[128], out2[64];
+ { FILE *fd = stdout;
+ char cmd[512], out2[512];
/* must remain in current dir */
strcpy(out1, "pan.pre");
if (add_ltl || nvr_file)
- strcpy(out2, "pan.___");
+ { assert(strlen(argv[1]) < sizeof(out2));
+ sprintf(out2, "%s.nvr", argv[1]);
+ if ((fd = fopen(out2, MFLAGS)) == NULL)
+ { printf("spin: cannot create tmp file %s\n",
+ out2);
+ alldone(1);
+ }
+ fprintf(fd, "#include \"%s\"\n", argv[1]);
+ }
if (add_ltl)
- { tl_out = cpyfile(argv[1], out2);
- nr_errs = tl_main(2, add_ltl); /* in tl_main.c */
- fclose(tl_out);
+ { tl_out = fd;
+ nr_errs = tl_main(2, add_ltl);
+ fclose(fd);
preprocess(out2, out1, 1);
} else if (nvr_file)
- { FILE *fd; char buf[1024];
-
- if ((fd = fopen(*nvr_file, "r")) == NULL)
- { printf("spin: cannot open %s\n",
- *nvr_file);
- alldone(1);
- }
- tl_out = cpyfile(argv[1], out2);
- while (fgets(buf, 1024, fd))
- fprintf(tl_out, "%s", buf);
- fclose(tl_out);
+ { fprintf(fd, "#include \"%s\"\n", *nvr_file);
fclose(fd);
preprocess(out2, out1, 1);
} else
- preprocess(argv[1], out1, 0);
+ { preprocess(argv[1], out1, 0);
+ }
if (preprocessonly)
- alldone(0);
+ { alldone(0);
+ }
if (!(yyin = fopen(out1, "r")))
{ printf("spin: cannot open %s\n", out1);
@@ -409,11 +1036,14 @@
alldone(1);
}
- if (strncmp(argv[1], "progress", 8) == 0
- || strncmp(argv[1], "accept", 6) == 0)
- sprintf(cmd, "_%s", argv[1]);
- else
- strcpy(cmd, argv[1]);
+ assert(strlen(argv[1])+1 < sizeof(cmd));
+
+ if (strncmp(argv[1], "progress", (size_t) 8) == 0
+ || strncmp(argv[1], "accept", (size_t) 6) == 0)
+ { sprintf(cmd, "_%s", argv[1]);
+ } else
+ { strcpy(cmd, argv[1]);
+ }
oFname = Fname = lookup(cmd);
if (oFname->name[0] == '\"')
{ int i = (int) strlen(oFname->name);
@@ -428,13 +1058,14 @@
printf("spin: missing argument to -f\n");
alldone(1);
}
- printf("%s\n", Version);
- printf("reading input from stdin:\n");
+ printf("%s\n", SpinVersion);
+ fprintf(stderr, "spin: error, no filename specified\n");
fflush(stdout);
+ alldone(1);
}
if (columns == 2)
{ extern void putprelude(void);
- if (xspin || verbose&(1|4|8|16|32))
+ if (xspin || (verbose & (1|4|8|16|32)))
{ printf("spin: -c precludes all flags except -t\n");
alldone(1);
}
@@ -441,10 +1072,13 @@
putprelude();
}
if (columns && !(verbose&8) && !(verbose&16))
- verbose += (8+16);
+ { verbose += (8+16);
+ }
if (columns == 2 && limited_vis)
- verbose += (1+4);
- Srand(T); /* defined in run.c */
+ { verbose += (1+4);
+ }
+
+ Srand((unsigned int) T); /* defined in run.c */
SeedUsed = T;
s = lookup("_"); s->type = PREDEF; /* write-only global var */
s = lookup("_p"); s->type = PREDEF;
@@ -451,9 +1085,27 @@
s = lookup("_pid"); s->type = PREDEF;
s = lookup("_last"); s->type = PREDEF;
s = lookup("_nr_pr"); s->type = PREDEF; /* new 3.3.10 */
+ s = lookup("_priority"); s->type = PREDEF; /* new 6.2.0 */
yyparse();
fclose(yyin);
+
+ if (ltl_claims)
+ { Symbol *r;
+ fclose(fd_ltl);
+ if (!(yyin = fopen(ltl_claims, "r")))
+ { fatal("cannot open %s", ltl_claims);
+ }
+ r = oFname;
+ oFname = Fname = lookup(ltl_claims);
+ lineno = 0;
+ yyparse();
+ fclose(yyin);
+ oFname = Fname = r;
+ if (0)
+ { (void) unlink(ltl_claims);
+ } }
+
loose_ends();
if (inlineonly)
@@ -463,31 +1115,73 @@
chanaccess();
if (!Caccess)
- { if (!s_trail && (dataflow || merger))
- ana_src(dataflow, merger);
+ { if (has_provided && merger)
+ { merger = 0; /* cannot use statement merging in this case */
+ }
+ if (!s_trail && (dataflow || merger) && (!replay || has_code))
+ { ana_src(dataflow, merger);
+ }
sched();
alldone(nr_errs);
}
+
return 0;
}
-int
-yywrap(void) /* dummy routine */
+void
+ltl_list(char *nm, char *fm)
{
- return 1;
+ if (s_trail
+ || analyze
+ || dumptab) /* when generating pan.c or replaying a trace */
+ { if (!ltl_claims)
+ { ltl_claims = "_spin_nvr.tmp";
+ if ((fd_ltl = fopen(ltl_claims, MFLAGS)) == NULL)
+ { fatal("cannot open tmp file %s", ltl_claims);
+ }
+ tl_out = fd_ltl;
+ }
+
+ add_ltl = (char **) emalloc(5 * sizeof(char *));
+ add_ltl[1] = "-c";
+ add_ltl[2] = nm;
+ add_ltl[3] = "-f";
+ add_ltl[4] = (char *) emalloc(strlen(fm)+4);
+ strcpy(add_ltl[4], "!(");
+ strcat(add_ltl[4], fm);
+ strcat(add_ltl[4], ")");
+ /* add_ltl[4] = fm; */
+ nr_errs += tl_main(4, add_ltl);
+
+ fflush(tl_out);
+ /* should read this file after the main file is read */
+ }
}
void
non_fatal(char *s1, char *s2)
-{ extern char yytext[];
+{ extern int yychar; extern char yytext[];
- printf("spin: line %3d %s, Error: ",
- lineno, Fname?Fname->name:"nofilename");
+ printf("spin: %s:%d, Error: ",
+ Fname?Fname->name:(oFname?oFname->name:"nofilename"), lineno);
+#if 1
+ printf(s1, s2); /* avoids a gcc warning */
+#else
if (s2)
printf(s1, s2);
else
printf(s1);
- if (yytext && strlen(yytext)>1)
+ if (yychar > 0)
+ { if (yychar == SEMI)
+ { printf(" statement separator");
+ } else
+ { printf(" saw '");
+ explain(yychar);
+ printf("'");
+ } }
+#endif
+
+ if (strlen(yytext)>1)
printf(" near '%s'", yytext);
printf("\n");
nr_errs++;
@@ -497,37 +1191,52 @@
fatal(char *s1, char *s2)
{
non_fatal(s1, s2);
+ (void) unlink("pan.b");
+ (void) unlink("pan.c");
+ (void) unlink("pan.h");
+ (void) unlink("pan.m");
+ (void) unlink("pan.t");
+ (void) unlink("pan.p");
+ (void) unlink("pan.pre");
+ if (!(verbose&32))
+ { (void) unlink("_spin_nvr.tmp");
+ }
alldone(1);
}
char *
-emalloc(int n)
+emalloc(size_t n)
{ char *tmp;
+ static unsigned long cnt = 0;
if (n == 0)
return NULL; /* robert shelton 10/20/06 */
if (!(tmp = (char *) malloc(n)))
+ { printf("spin: allocated %ld Gb, wanted %d bytes more\n",
+ cnt/(1024*1024*1024), (int) n);
fatal("not enough memory", (char *)0);
+ }
+ cnt += (unsigned long) n;
memset(tmp, 0, n);
return tmp;
}
void
-trapwonly(Lextok *n, char *unused)
-{ extern int realread;
- short i = (n->sym)?n->sym->type:0;
+trapwonly(Lextok *n /* , char *unused */)
+{ short i = (n->sym)?n->sym->type:0;
- if (i != MTYPE
- && i != BIT
- && i != BYTE
- && i != SHORT
- && i != INT
- && i != UNSIGNED)
- return;
+ /* printf("%s realread %d type %d\n", n->sym?n->sym->name:"--", realread, i); */
- if (realread)
- n->sym->hidden |= 128; /* var is read at least once */
+ if (realread
+ && (i == MTYPE
+ || i == BIT
+ || i == BYTE
+ || i == SHORT
+ || i == INT
+ || i == UNSIGNED))
+ { n->sym->hidden |= 128; /* var is read at least once */
+ }
}
void
@@ -555,7 +1264,8 @@
{ Lextok *n = (Lextok *) emalloc(sizeof(Lextok));
static int warn_nn = 0;
- n->ntyp = (short) t;
+ n->uiid = is_inline(); /* record origin of the statement */
+ n->ntyp = (unsigned short) t;
if (s && s->fn)
{ n->ln = s->ln;
n->fn = s->fn;
@@ -679,13 +1389,13 @@
#endif
}
-static void
+void
explain(int n)
{ FILE *fd = stdout;
switch (n) {
default: if (n > 0 && n < 256)
- fprintf(fd, "'%c' = '", n);
- fprintf(fd, "%d'", n);
+ fprintf(fd, "'%c' = ", n);
+ fprintf(fd, "%d", n);
break;
case '\b': fprintf(fd, "\\b"); break;
case '\t': fprintf(fd, "\\t"); break;
@@ -698,6 +1408,16 @@
case 'R': fprintf(fd, "recv poll %s", Operator); break;
case '@': fprintf(fd, "@"); break;
case '?': fprintf(fd, "(x->y:z)"); break;
+#if 1
+ case NEXT: fprintf(fd, "X"); break;
+ case ALWAYS: fprintf(fd, "[]"); break;
+ case EVENTUALLY: fprintf(fd, "<>"); break;
+ case IMPLIES: fprintf(fd, "->"); break;
+ case EQUIV: fprintf(fd, "<->"); break;
+ case UNTIL: fprintf(fd, "U"); break;
+ case WEAK_UNTIL: fprintf(fd, "W"); break;
+ case IN: fprintf(fd, "%sin", Keyword); break;
+#endif
case ACTIVE: fprintf(fd, "%sactive", Keyword); break;
case AND: fprintf(fd, "%s&&", Operator); break;
case ASGN: fprintf(fd, "%s=", Operator); break;
@@ -724,6 +1444,7 @@
case FI: fprintf(fd, "%sfi", Keyword); break;
case FULL: fprintf(fd, "%sfull", Function); break;
case GE: fprintf(fd, "%s>=", Operator); break;
+ case GET_P: fprintf(fd, "%sget_priority",Function); break;
case GOTO: fprintf(fd, "%sgoto", Keyword); break;
case GT: fprintf(fd, "%s>", Operator); break;
case HIDDEN: fprintf(fd, "%shidden", Keyword); break;
@@ -763,6 +1484,8 @@
case RUN: fprintf(fd, "%srun", Operator); break;
case SEP: fprintf(fd, "token: ::"); break;
case SEMI: fprintf(fd, ";"); break;
+ case ARROW: fprintf(fd, "->"); break;
+ case SET_P: fprintf(fd, "%sset_priority",Function); break;
case SHOW: fprintf(fd, "%sshow", Keyword); break;
case SND: fprintf(fd, "%s!", Operator); break;
case STRING: fprintf(fd, "a string"); break;
@@ -776,3 +1499,5 @@
case UNLESS: fprintf(fd, "%sunless", Keyword); break;
}
}
+
+
--- a/sys/src/cmd/spin/mesg.c
+++ b/sys/src/cmd/spin/mesg.c
@@ -1,14 +1,12 @@
/***** spin: mesg.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
+#include <stdlib.h>
#include "spin.h"
#include "y.tab.h"
@@ -24,9 +22,10 @@
extern int nproc, nstop;
extern short Have_claim;
+QH *qh;
Queue *qtab = (Queue *) 0; /* linked list of queues */
Queue *ltab[MAXQ]; /* linear list of queues */
-int nqs = 0, firstrow = 1;
+int nqs = 0, firstrow = 1, has_stdin = 0;
char Buf[4096];
static Lextok *n_rem = (Lextok *) 0;
@@ -73,7 +72,7 @@
return eval(s->ini);
q = (Queue *) emalloc(sizeof(Queue));
- q->qid = ++nqs;
+ q->qid = (short) ++nqs;
q->nslots = s->ini->val;
q->nflds = cnt_mpars(s->ini->rgt);
q->setat = depth;
@@ -130,7 +129,7 @@
if (whichq == -1)
{ printf("Error: sending to an uninitialized chan\n");
- whichq = 0;
+ /* whichq = 0; */
return 0;
}
if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
@@ -143,6 +142,37 @@
return 0;
}
+#ifndef PC
+ #include <termios.h>
+ static struct termios initial_settings, new_settings;
+
+ void
+ peek_ch_init(void)
+ {
+ tcgetattr(0,&initial_settings);
+
+ new_settings = initial_settings;
+ new_settings.c_lflag &= ~ICANON;
+ new_settings.c_lflag &= ~ECHO;
+ new_settings.c_lflag &= ~ISIG;
+ new_settings.c_cc[VMIN] = 0;
+ new_settings.c_cc[VTIME] = 0;
+ }
+
+ int
+ peek_ch(void)
+ { int n;
+
+ has_stdin = 1;
+
+ tcsetattr(0, TCSANOW, &new_settings);
+ n = getchar();
+ tcsetattr(0, TCSANOW, &initial_settings);
+
+ return n;
+ }
+#endif
+
int
qrecv(Lextok *n, int full)
{ int whichq = eval(n->lft)-1;
@@ -150,22 +180,37 @@
if (whichq == -1)
{ if (n->sym && !strcmp(n->sym->name, "STDIN"))
{ Lextok *m;
-
+#ifndef PC
+ static int did_once = 0;
+ if (!did_once) /* 6.2.4 */
+ { peek_ch_init();
+ did_once = 1;
+ }
+#endif
if (TstOnly) return 1;
for (m = n->rgt; m; m = m->rgt)
if (m->lft->ntyp != CONST && m->lft->ntyp != EVAL)
- { int c = getchar();
+ {
+#ifdef PC
+ int c = getchar();
+#else
+ int c = peek_ch(); /* 6.2.4, was getchar(); */
+#endif
+ if (c == 27 || c == 3) /* escape or control-c */
+ { printf("quit\n");
+ exit(0);
+ } /* else: non-blocking */
+ if (c == EOF) return 0; /* no char available */
(void) setval(m->lft, c);
} else
- fatal("invalid use of STDIN", (char *)0);
-
- whichq = 0;
+ { fatal("invalid use of STDIN", (char *)0);
+ }
return 1;
}
printf("Error: receiving from an uninitialized chan %s\n",
n->sym?n->sym->name:"");
- whichq = 0;
+ /* whichq = 0; */
return 0;
}
if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
@@ -185,9 +230,11 @@
for (j = 0, m = n->rgt; m && j < q->nflds; m = m->rgt, j++)
{ New = cast_val(q->fld_width[j], eval(m->lft), 0);
Old = q->contents[i*q->nflds+j];
- if (New == Old) continue;
- if (New > Old) break; /* inner loop */
- if (New < Old) goto found;
+ if (New == Old)
+ continue;
+ if (New > Old)
+ break; /* inner loop */
+ goto found; /* New < Old */
}
found:
for (j = q->qlen-1; j >= i; j--)
@@ -204,7 +251,8 @@
typ_ck(int ft, int at, char *s)
{
if ((verbose&32) && ft != at
- && (ft == CHAN || at == CHAN))
+ && (ft == CHAN || at == CHAN)
+ && (at != PREDEF || strcmp(s, "recv") != 0))
{ char buf[128], tag1[64], tag2[64];
(void) sputtype(tag1, ft);
(void) sputtype(tag2, at);
@@ -383,7 +431,7 @@
return 1;
}
-void
+static void
channm(Lextok *n)
{ char lbuf[512];
@@ -394,7 +442,11 @@
else if (n->sym->type == STRUCT)
{ Symbol *r = n->sym;
if (r->context)
- r = findloc(r);
+ { r = findloc(r);
+ if (!r)
+ { strcat(Buf, "*?*");
+ return;
+ } }
ini_struct(r);
printf("%s", r->name);
strcpy(lbuf, "");
@@ -422,7 +474,11 @@
sr_buf(v, q->fld_width[j] == MTYPE);
if (j == q->nflds - 1)
{ int cnr;
- if (s_trail) cnr = pno; else cnr = X?X->pid - Have_claim:0;
+ if (s_trail)
+ { cnr = pno;
+ } else
+ { cnr = X?X->pid - Have_claim:0;
+ }
if (tr[0] == '[') strcat(Buf, "]");
pstext(cnr, Buf);
}
@@ -458,12 +514,6 @@
}
}
-typedef struct QH {
- int n;
- struct QH *nxt;
-} QH;
-QH *qh;
-
void
qhide(int q)
{ QH *p = (QH *) emalloc(sizeof(QH));
@@ -483,7 +533,7 @@
static void
sr_talk(Lextok *n, int v, char *tr, char *a, int j, Queue *q)
-{ char s[64];
+{ char s[128];
if (qishidden(eval(n->lft)))
return;
@@ -510,9 +560,20 @@
}
if (j == 0)
- { whoruns(1);
- printf("line %3d %s %s",
- n->ln, n->fn->name, s);
+ { char snm[128];
+ whoruns(1);
+ { char *ptr = n->fn->name;
+ char *qtr = snm;
+ while (*ptr != '\0')
+ { if (*ptr != '\"')
+ { *qtr++ = *ptr;
+ }
+ ptr++;
+ }
+ *qtr = '\0';
+ printf("%s:%d %s",
+ snm, n->ln, s);
+ }
} else
printf(",");
sr_mesg(stdout, v, q->fld_width[j] == MTYPE);
@@ -554,7 +615,11 @@
sr_mesg(FILE *fd, int v, int j)
{ Buf[0] ='\0';
sr_buf(v, j);
+#if 1
+ fprintf(fd, Buf, (char *) 0); /* prevent compiler warning */
+#else
fprintf(fd, Buf);
+#endif
}
void
@@ -572,10 +637,15 @@
continue;
if (q->nslots == 0)
continue; /* rv q always empty */
+#if 0
+ if (q->qlen == 0) /* new 7/10 -- dont show if queue is empty */
+ { continue;
+ }
+#endif
printf("\t\tqueue %d (", q->qid);
if (r)
printf("%s(%d):", r->n->name, r->pid - Have_claim);
- if (s->nel != 1)
+ if (s->nel > 1 || s->isarray)
printf("%s[%d]): ", s->name, n);
else
printf("%s): ", s->name);
@@ -609,7 +679,11 @@
}
}
- if (!n || n->ntyp == LEN || n->ntyp == RUN)
+ /* ok on the rhs of an assignment: */
+ if (!n || n->ntyp == LEN || n->ntyp == RUN
+ || n->ntyp == FULL || n->ntyp == NFULL
+ || n->ntyp == EMPTY || n->ntyp == NEMPTY
+ || n->ntyp == 'R')
return;
if (n->sym && n->sym->type == CHAN)
@@ -627,7 +701,122 @@
nochan_manip(p, n->rgt, 1);
}
+typedef struct BaseName {
+ char *str;
+ int cnt;
+ struct BaseName *nxt;
+} BaseName;
+
+static BaseName *bsn;
+
void
+newbasename(char *s)
+{ BaseName *b;
+
+/* printf("+++++++++%s\n", s); */
+ for (b = bsn; b; b = b->nxt)
+ if (strcmp(b->str, s) == 0)
+ { b->cnt++;
+ return;
+ }
+ b = (BaseName *) emalloc(sizeof(BaseName));
+ b->str = emalloc(strlen(s)+1);
+ b->cnt = 1;
+ strcpy(b->str, s);
+ b->nxt = bsn;
+ bsn = b;
+}
+
+void
+delbasename(char *s)
+{ BaseName *b, *prv = (BaseName *) 0;
+
+ for (b = bsn; b; prv = b, b = b->nxt)
+ { if (strcmp(b->str, s) == 0)
+ { b->cnt--;
+ if (b->cnt == 0)
+ { if (prv)
+ { prv->nxt = b->nxt;
+ } else
+ { bsn = b->nxt;
+ } }
+/* printf("---------%s\n", s); */
+ break;
+ } }
+}
+
+void
+checkindex(char *s, char *t)
+{ BaseName *b;
+
+/* printf("xxx Check %s (%s)\n", s, t); */
+ for (b = bsn; b; b = b->nxt)
+ {
+/* printf(" %s\n", b->str); */
+ if (strcmp(b->str, s) == 0)
+ { non_fatal("do not index an array with itself (%s)", t);
+ break;
+ } }
+}
+
+void
+scan_tree(Lextok *t, char *mn, char *mx)
+{ char sv[512];
+ char tmp[32];
+ int oln = lineno;
+
+ if (!t) return;
+
+ lineno = t->ln;
+
+ if (t->ntyp == NAME)
+ { strcat(mn, t->sym->name);
+ strcat(mx, t->sym->name);
+ if (t->lft) /* array index */
+ { strcat(mn, "[]");
+ newbasename(mn);
+ strcpy(sv, mn); /* save */
+ strcpy(mn, ""); /* clear */
+ strcat(mx, "[");
+ scan_tree(t->lft, mn, mx); /* index */
+ strcat(mx, "]");
+ checkindex(mn, mx); /* match against basenames */
+ strcpy(mn, sv); /* restore */
+ delbasename(mn);
+ }
+ if (t->rgt) /* structure element */
+ { scan_tree(t->rgt, mn, mx);
+ }
+ } else if (t->ntyp == CONST)
+ { strcat(mn, "1"); /* really: t->val */
+ sprintf(tmp, "%d", t->val);
+ strcat(mx, tmp);
+ } else if (t->ntyp == '.')
+ { strcat(mn, ".");
+ strcat(mx, ".");
+ scan_tree(t->lft, mn, mx);
+ } else
+ { strcat(mn, "??");
+ strcat(mx, "??");
+ }
+ lineno = oln;
+}
+
+void
+no_nested_array_refs(Lextok *n) /* a [ a[1] ] with a[1] = 1, causes trouble in pan.b */
+{ char mn[512];
+ char mx[512];
+
+/* printf("==================================ZAP\n"); */
+ bsn = (BaseName *) 0; /* start new list */
+ strcpy(mn, "");
+ strcpy(mx, "");
+
+ scan_tree(n, mn, mx);
+/* printf("==> %s\n", mn); */
+}
+
+void
no_internals(Lextok *n)
{ char *sp;
@@ -638,7 +827,10 @@
sp = n->sym->name;
if ((strlen(sp) == strlen("_nr_pr") && strcmp(sp, "_nr_pr") == 0)
+ || (strlen(sp) == strlen("_pid") && strcmp(sp, "_pid") == 0)
|| (strlen(sp) == strlen("_p") && strcmp(sp, "_p") == 0))
- { fatal("attempt to assign value to system variable %s", sp);
+ { fatal("invalid assignment to %s", sp);
}
+
+ no_nested_array_refs(n);
}
--- a/sys/src/cmd/spin/mkfile
+++ b/sys/src/cmd/spin/mkfile
@@ -8,6 +8,7 @@
guided.$O\
main.$O\
mesg.$O\
+ msc_tcl.$O\
pangen1.$O\
pangen2.$O\
pangen3.$O\
@@ -14,8 +15,7 @@
pangen4.$O\
pangen5.$O\
pangen6.$O\
- pc_zpp.$O\
- ps_msc.$O\
+ pangen7.$O\
reprosrc.$O\
run.$O\
sched.$O\
@@ -45,7 +45,7 @@
</sys/src/cmd/mkone
CC=pcc -c
-CFLAGS=-B -D_POSIX_SOURCE
+CFLAGS=-B -D_POSIX_SOURCE -D_PLAN9
YFLAGS=-S -d
$SPIN_OS: spin.h
--- /dev/null
+++ b/sys/src/cmd/spin/msc_tcl.c
@@ -1,0 +1,376 @@
+/***** spin: msc_tcl.c *****/
+
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
+
+#include <stdlib.h>
+#include "spin.h"
+#include "version.h"
+
+#define MW 500 /* page width */
+#define RH 100 /* right margin */
+#define WW 80 /* distance between process lines */
+#define HH 12 /* vertical distance between steps */
+#define LW 2 /* line width of message arrows */
+
+#define RVC "darkred" /* rendezvous arrows */
+#define MPC "darkblue" /* asynchronous message passing arrow */
+#define GRC "lightgrey" /* grid lines */
+
+static int MH = 600; /* anticipated page-length */
+static FILE *pfd;
+static char **I; /* initial procs */
+static int *D,*R; /* maps between depth (stepnr) and ldepth (msc-step) */
+static short *M; /* x location of each box at index y */
+static short *T; /* y index of match for each box at index y */
+static char **L; /* text labels */
+static int ProcLine[256]; /* active processes */
+static int UsedLine[256]; /* process line has at least one entry */
+static int ldepth = 1;
+static int maxx, TotSteps = 2*4096; /* max nr of steps for simulation output */
+static float Scaler = (float) 1.0;
+
+static int xscale = 2;
+static int yscale = 1;
+static int no_box;
+
+extern int ntrail, s_trail, pno, depth;
+extern Symbol *oFname;
+
+extern void exit(int);
+extern void putpostlude(void);
+
+static void putpages(void);
+
+static void
+psline(int x0, int y0, int x1, int y1, char *color)
+{ char *side = "last";
+
+ if (x0 == x1) /* gridline */
+ { fprintf(pfd, ".c create line %d %d %d %d -fill %s -tags grid -width 1 \n",
+ xscale*(x0+1)*WW-20, yscale*y0+20,
+ xscale*(x1+1)*WW-20, yscale*y1+20, color);
+ fprintf(pfd, ".c lower grid\n");
+ } else
+ { int xm = xscale*(x0+1)*WW + (xscale*(x1 - x0)*WW)/2 - 20; /* mid x */
+
+ if (y1 - y0 <= HH+20)
+ { y1 = y0+20; /* close enough to horizontal - looks better */
+ }
+
+ fprintf(pfd, ".c create line %d %d %d %d -fill %s -tags mesg -width %d\n",
+ xscale*(x0+1)*WW-20, yscale*y0+20+10,
+ xm, yscale*y0+20+10, color, LW);
+
+ if (y1 != y0+20)
+ { fprintf(pfd, ".c create line %d %d %d %d -fill %s -tags mesg -width %d\n",
+ xm, yscale*y0+20+10,
+ xm, yscale*y1+20-10, color, LW);
+ }
+
+ fprintf(pfd, ".c create line %d %d %d %d -fill %s -width %d ",
+ xm, yscale*y1+20-10,
+ xscale*(x1+1)*WW-20, yscale*y1+20-10, color, LW);
+
+ if (strcmp(color, RVC) == 0)
+ { side = "both";
+ }
+ fprintf(pfd, "-arrow %s -arrowshape {5 5 5} -tags mesg\n", side);
+ fprintf(pfd, ".c raise mesg\n");
+ }
+}
+
+static void
+colbox(int ix, int iy, int w, int h_unused, char *color)
+{ int x = ix*WW;
+ int y = iy*HH;
+
+ if (ix < 0 || ix > 255)
+ { fatal("msc_tcl: unexpected\n", (char *) 0);
+ }
+
+ if (ProcLine[ix] < iy)
+ { /* if (ProcLine[ix] > 0) */
+ { psline(ix-1, ProcLine[ix]*HH+HH+4,
+ ix-1, iy*HH-HH, GRC);
+ }
+ fprintf(pfd, "# ProcLine[%d] from %d to %d (Used %d nobox %d)\n",
+ ix, ProcLine[ix], iy, UsedLine[ix], no_box);
+ ProcLine[ix] = iy;
+ } else
+ { fprintf(pfd, "# ProcLine[%d] stays at %d (Used %d nobox %d)\n",
+ ix, ProcLine[ix], UsedLine[ix], no_box);
+ }
+
+ if (UsedLine[ix])
+ { no_box = 2;
+ }
+
+ if (strcmp(color, "black") == 0)
+ { if (no_box == 0) /* shadow */
+ { fprintf(pfd, ".c create rectangle %d %d %d %d -fill black\n",
+ xscale*x-(xscale*4*w/3)-20+4, (yscale*y-10)+20+2,
+ xscale*x+(xscale*4*w/3)-20, (yscale*y+10)+20+2);
+ }
+ } else
+ { if (no_box == 0) /* box with outline */
+ { fprintf(pfd, ".c create rectangle %d %d %d %d -fill ivory\n",
+ xscale*x-(xscale*4*w/3)-20, (yscale*y-10)+20,
+ xscale*x+(xscale*4*w/3)-20, (yscale*y+10)+20);
+ UsedLine[ix]++;
+ } else /* no outline */
+ { fprintf(pfd, ".c create rectangle %d %d %d %d -fill white -width 0\n",
+ xscale*x-(xscale*4*w/3)-20, (yscale*y-10)+20,
+ xscale*x+(xscale*4*w/3)-20, (yscale*y+10)+20);
+ } }
+ if (no_box > 0)
+ { no_box--;
+ }
+}
+
+static void
+stepnumber(int i)
+{ int y = (yscale*i*HH) + 20;
+
+ fprintf(pfd, ".c create text %d %d -fill #eef -text \"%d\"\n",
+ -10+(xscale*WW)/2, y, i);
+
+ /* horizontal dashed grid line */
+ fprintf(pfd, ".c create line %d %d %d %d -fill #eef -dash {6 4}\n",
+ -20+WW*xscale, y, (maxx+1)*WW*xscale-20, y);
+}
+
+static void
+spitbox(int ix, int y, char *s)
+{ float bw; /* box width */
+ char d[256], *t, *z;
+ int a, i, x = ix+1;
+ char *color = "black";
+
+ if (y > 0)
+ { stepnumber(y);
+ }
+
+ bw = (float)1.8*(float)strlen(s); /* guess at default font width */
+ colbox(x, y, (int) (bw+1.0), 5, "black");
+ if (s[0] == '~')
+ { switch (s[1]) {
+ default :
+ case 'R': color = "red"; break;
+ case 'B': color = "blue"; break;
+ case 'G': color = "green"; break;
+ }
+ s += 2;
+ } else if (strchr(s, '!'))
+ { color = "ivory";
+ } else if (strchr(s, '?'))
+ { color = "azure";
+ } else
+ { color = "pink";
+ if (sscanf(s, "%d:%250s", &a, d) == 2
+ && a >= 0 && a < TotSteps)
+ { if (!I[a] || strlen(I[a]) <= strlen(s))
+ { I[a] = (char *) emalloc((int) strlen(s)+1);
+ }
+ strcpy(I[a], s);
+ } }
+
+ colbox(x, y, (int) bw, 4, color);
+
+ z = t = (char *) emalloc(2*strlen(s)+1);
+
+ for (i = 0; i < (int) strlen(s); i++)
+ { if (s[i] == '\n')
+ { continue;
+ }
+ if (s[i] == '[' || s[i] == ']')
+ { *t++ = '\\';
+ }
+ *t++ = s[i];
+ }
+
+ fprintf(pfd, ".c create text %d %d -text \"%s\"\n",
+ xscale*x*WW-20, yscale*y*HH+20, z);
+}
+
+static void
+putpages(void)
+{ int i, lasti=0; float nmh;
+
+ if (maxx*xscale*WW > MW-RH/2)
+ { Scaler = (float) (MW-RH/2) / (float) (maxx*xscale*WW);
+ nmh = (float) MH; nmh /= Scaler; MH = (int) nmh;
+ fprintf(pfd, "# Scaler %f, MH %d\n", Scaler, MH);
+ }
+ if (ldepth >= TotSteps)
+ { ldepth = TotSteps-1;
+ }
+
+/* W: (maxx+2)*xscale*WW */
+/* H: ldepth*HH*yscale+50 */
+ fprintf(pfd, "wm title . \"scenario\"\n");
+ fprintf(pfd, "wm geometry . %dx600+650+100\n", (maxx+2)*xscale*WW);
+
+ fprintf(pfd, "canvas .c -width 800 -height 800 \\\n");
+ fprintf(pfd, " -scrollregion {0c -1c 30c 100c} \\\n");
+ fprintf(pfd, " -xscrollcommand \".hscroll set\" \\\n");
+ fprintf(pfd, " -yscrollcommand \".vscroll set\" \\\n");
+ fprintf(pfd, " -bg white -relief raised -bd 2\n");
+
+ fprintf(pfd, "scrollbar .vscroll -relief sunken ");
+ fprintf(pfd, " -command \".c yview\"\n");
+ fprintf(pfd, "scrollbar .hscroll -relief sunken -orient horiz ");
+ fprintf(pfd, " -command \".c xview\"\n");
+
+ fprintf(pfd, "pack append . \\\n");
+ fprintf(pfd, " .vscroll {right filly} \\\n");
+ fprintf(pfd, " .hscroll {bottom fillx} \\\n");
+ fprintf(pfd, " .c {top expand fill}\n");
+
+ fprintf(pfd, ".c yview moveto 0\n");
+
+ for (i = TotSteps-1; i >= 0; i--)
+ { if (I[i])
+ { spitbox(i, -1, I[i]);
+ } }
+
+ for (i = 0; i <= ldepth; i++)
+ { if (!M[i] && !L[i])
+ { continue; /* no box */
+ }
+ if (T[i] > 0) /* arrow */
+ { if (T[i] == i) /* rv handshake */
+ { psline( M[lasti], lasti*HH,
+ M[i], i*HH, RVC);
+ } else
+ { psline( M[i], i*HH,
+ M[T[i]], T[i]*HH, MPC);
+ } }
+ if (L[i])
+ { spitbox(M[i], i, L[i]);
+ lasti = i;
+ } }
+}
+
+static void
+putbox(int x)
+{
+ if (ldepth >= TotSteps)
+ { fprintf(stderr, "max length of %d steps exceeded - ps file truncated\n",
+ TotSteps);
+ putpostlude();
+ }
+ M[ldepth] = x;
+ if (x > maxx)
+ { maxx = x;
+ fprintf(pfd, "# maxx %d\n", x);
+ }
+}
+
+/* functions called externally: */
+
+extern int WhatSeed(void);
+
+void
+putpostlude(void)
+{ char cmd[512];
+
+ putpages();
+ fprintf(pfd, ".c lower grid\n");
+ fprintf(pfd, ".c raise mesg\n");
+ fclose(pfd);
+
+ fprintf(stderr, "seed used: -n%d\n", WhatSeed());
+ sprintf(cmd, "wish -f %s.tcl &", oFname?oFname->name:"msc");
+ fprintf(stderr, "%s\n", cmd);
+ (void) unlink("pan.pre");
+ exit (system(cmd));
+}
+
+void
+putprelude(void)
+{ char snap[256]; FILE *fd;
+
+ sprintf(snap, "%s.tcl", oFname?oFname->name:"msc");
+ if (!(pfd = fopen(snap, MFLAGS)))
+ { fatal("cannot create file '%s'", snap);
+ }
+ if (s_trail)
+ { if (ntrail)
+ sprintf(snap, "%s%d.trail", oFname?oFname->name:"msc", ntrail);
+ else
+ sprintf(snap, "%s.trail", oFname?oFname->name:"msc");
+ if (!(fd = fopen(snap, "r")))
+ { snap[strlen(snap)-2] = '\0';
+ if (!(fd = fopen(snap, "r")))
+ fatal("cannot open trail file", (char *) 0);
+ }
+ TotSteps = 1;
+ while (fgets(snap, 256, fd)) TotSteps++;
+ fclose(fd);
+ }
+ TotSteps *= 2;
+ R = (int *) emalloc(TotSteps * sizeof(int));
+ D = (int *) emalloc(TotSteps * sizeof(int));
+ M = (short *) emalloc(TotSteps * sizeof(short));
+ T = (short *) emalloc(TotSteps * sizeof(short));
+ L = (char **) emalloc(TotSteps * sizeof(char *));
+ I = (char **) emalloc(TotSteps * sizeof(char *));
+}
+
+void
+putarrow(int from, int to)
+{
+ /* from rv if from == to */
+ /* which means that D[from] == D[to] */
+ /* which means that T[x] == x */
+
+ if (from < TotSteps
+ && to < TotSteps
+ && D[from] < TotSteps)
+ { T[D[from]] = D[to];
+ }
+}
+
+void
+pstext(int x, char *s)
+{ char *tmp = emalloc((int) strlen(s)+1);
+
+ strcpy(tmp, s);
+ if (depth == 0)
+ { I[x] = tmp;
+ } else
+ { if (depth >= TotSteps || ldepth >= TotSteps)
+ { fprintf(stderr, "spin: error: max nr of %d steps exceeded\n",
+ TotSteps);
+ fatal("use -uN to limit steps", (char *) 0);
+ }
+ putbox(x);
+ D[depth] = ldepth;
+ R[ldepth] = depth;
+ L[ldepth] = tmp;
+ ldepth += 2;
+ }
+}
+
+void
+dotag(FILE *fd, char *s)
+{ extern int columns, notabs; extern RunList *X;
+ int i = (!strncmp(s, "MSC: ", 5))?5:0;
+ int pid = s_trail ? pno : (X?X->pid:0);
+
+ if (columns == 2)
+ { pstext(pid, &s[i]);
+ } else
+ { if (!notabs)
+ { printf(" ");
+ for (i = 0; i <= pid; i++)
+ { printf(" ");
+ } }
+ fprintf(fd, "%s", s);
+ fflush(fd);
+ }
+}
--- a/sys/src/cmd/spin/pangen1.c
+++ b/sys/src/cmd/spin/pangen1.c
@@ -1,18 +1,22 @@
/***** spin: pangen1.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include "spin.h"
#include "y.tab.h"
#include "pangen1.h"
#include "pangen3.h"
+#include "pangen6.h"
+#include <assert.h>
+#ifdef SOLARIS
+#include <sys/int_limits.h>
+#else
+#include <stdint.h>
+#endif
extern FILE *tc, *th, *tt;
extern Label *labtab;
@@ -20,9 +24,10 @@
extern ProcList *rdy;
extern Queue *qtab;
extern Symbol *Fname;
-extern int lineno, verbose, Pid, separate;
+extern int lineno, verbose, Pid, separate, old_scope_rules, nclaims;
extern int nrRdy, nqs, mst, Mpars, claimnr, eventmapnr;
-extern short has_sorted, has_random, has_provided;
+extern short has_sorted, has_random, has_provided, has_priority;
+extern Queue *ltab[];
int Npars=0, u_sync=0, u_async=0, hastrack = 1;
short has_io = 0;
@@ -36,9 +41,10 @@
static void dohidden(void);
static void do_init(FILE *, Symbol *);
static void end_labs(Symbol *, int);
-static void put_ptype(char *, int, int, int);
+static void put_ptype(char *, int, int, int, enum btypes);
static void tc_predef_np(void);
static void put_pinit(ProcList *);
+static void multi_init(void);
void walk_struct(FILE *, int, char *, Symbol *, char *, char *, char *);
static void
@@ -46,9 +52,24 @@
{
if (!p) return;
reverse_names(p->nxt);
- fprintf(th, " \"%s\",\n", p->n->name);
+ fprintf(tc, " \"%s\",\n", p->n->name);
}
+static void
+reverse_types(ProcList *p)
+{
+ if (!p) return;
+ reverse_types(p->nxt);
+ fprintf(tc, " %d, /* %s */\n", p->b, p->n->name);
+}
+static int
+blog(int n) /* for small log2 without rounding problems */
+{ int m=1, r=2;
+
+ while (r < n) { m++; r *= 2; }
+ return 1+m;
+}
+
void
genheader(void)
{ ProcList *p; int i;
@@ -57,37 +78,129 @@
{ putunames(th);
goto here;
}
-
+ /* 5.2.3: gcc 3 no longer seems to compute sizeof at compile time */
+ fprintf(th, "#define WS %d /* word size in bytes */\n", (int) sizeof(void *));
fprintf(th, "#define SYNC %d\n", u_sync);
fprintf(th, "#define ASYNC %d\n\n", u_async);
+ fprintf(th, "#ifndef NCORE\n");
+ fprintf(th, " #ifdef DUAL_CORE\n");
+ fprintf(th, " #define NCORE 2\n");
+ fprintf(th, " #elif QUAD_CORE\n");
+ fprintf(th, " #define NCORE 4\n");
+ fprintf(th, " #else\n");
+ fprintf(th, " #define NCORE 1\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, "#endif\n\n");
putunames(th);
- fprintf(tc, "short Air[] = { ");
+ fprintf(tc, "\nshort Air[] = { ");
for (p = rdy, i=0; p; p = p->nxt, i++)
fprintf(tc, "%s (short) Air%d", (p!=rdy)?",":"", i);
fprintf(tc, ", (short) Air%d", i); /* np_ */
+ if (nclaims > 1)
+ { fprintf(tc, "\n#ifndef NOCLAIM\n");
+ fprintf(tc, " , (short) Air%d", i+1); /* Multi */
+ fprintf(tc, "\n#endif\n\t");
+ }
fprintf(tc, " };\n");
- fprintf(th, "char *procname[] = {\n");
+ fprintf(tc, "char *procname[] = {\n");
reverse_names(rdy);
- fprintf(th, " \":np_:\",\n");
- fprintf(th, "};\n\n");
+ fprintf(tc, " \":np_:\",\n");
+ fprintf(tc, " 0\n");
+ fprintf(tc, "};\n\n");
+ fprintf(tc, "enum btypes { NONE=%d, N_CLAIM=%d,", NONE, N_CLAIM);
+ fprintf(tc, " I_PROC=%d, A_PROC=%d,", I_PROC, A_PROC);
+ fprintf(tc, " P_PROC=%d, E_TRACE=%d, N_TRACE=%d };\n\n",
+ P_PROC, E_TRACE, N_TRACE);
+
+ fprintf(tc, "int Btypes[] = {\n");
+ reverse_types(rdy);
+ fprintf(tc, " 0 /* :np_: */\n");
+ fprintf(tc, "};\n\n");
+
here:
for (p = rdy; p; p = p->nxt)
- put_ptype(p->n->name, p->tn, mst, nrRdy+1);
+ put_ptype(p->n->name, p->tn, mst, nrRdy+1, p->b);
/* +1 for np_ */
- put_ptype("np_", nrRdy, mst, nrRdy+1);
+ put_ptype("np_", nrRdy, mst, nrRdy+1, 0);
+ if (nclaims > 1)
+ { /* this is the structure that goes into the state-vector
+ * instead of the actual never claims
+ * this assumes that the claims do not have any local variables
+ * this claim records the types and states of all subclaims in an array
+ * NB: not sure if we need the first 3 fields in this structure
+ * it's here for now to avoid breaking some possible dependence
+ * in the calculations above, we were already taking into account
+ * that there is one never-claim, which will now be this one
+ */
+
+ i = blog(mst);
+ fprintf(th, "\n");
+
+ fprintf(th, "#ifndef NOCLAIM\n");
+ fprintf(th, " #undef VERI\n");
+ fprintf(th, " #define VERI %d\n", nrRdy+1);
+ fprintf(th, " #define Pclaim P%d\n\n", nrRdy+1);
+ fprintf(th, "typedef struct P%d {\n", nrRdy+1);
+ fprintf(th, " unsigned _pid : 8; /* always zero */\n");
+ fprintf(th, " unsigned _t : %d; /* active-claim type */\n",
+ blog(nrRdy+1));
+ fprintf(th, " unsigned _p : %d; /* active-claim state */\n",
+ i);
+ fprintf(th, " unsigned _n : %d; /* active-claim index */\n",
+ blog(nclaims));
+ if (i <= UINT8_MAX) /* in stdint.h = UCHAR_MAX from limits.h */
+ { fprintf(th, " uchar c_cur[NCLAIMS]; /* claim-states */\n");
+ } else if (i <= UINT16_MAX) /* really USHRT_MAX from limits.h */
+ { fprintf(th, " ushort c_cur[NCLAIMS]; /* claim-states */\n");
+ } else /* the most unlikely case */
+ { fprintf(th, " uint c_cur[NCLAIMS]; /* claim-states */\n");
+ }
+ fprintf(th, "} P%d;\n", nrRdy+1);
+
+ fprintf(tc, "#ifndef NOCLAIM\n");
+ fprintf(tc, "uchar spin_c_typ[NCLAIMS]; /* claim-types */\n");
+ fprintf(tc, "#endif\n");
+
+ fprintf(th, " #define Air%d (0)\n\n", nrRdy+1);
+ fprintf(th, "#endif\n");
+ /*
+ * find special states as:
+ * stopstate [ claimnr ][ curstate ] == 1
+ * accpstate [ claimnr ][ curstate ]
+ * progstate [ claimnr ][ curstate ]
+ * reached [ claimnr ][ curstate ]
+ * visstate [ claimnr ][ curstate ]
+ * loopstate [ claimnr ][ curstate ]
+ * mapstate [ claimnr ][ curstate ]
+ */
+ } else
+ { fprintf(th, "#define Pclaim P0\n");
+ fprintf(th, "#ifndef NCLAIMS\n");
+ fprintf(th, " #define NCLAIMS 1\n");
+ fprintf(th, "#endif\n");
+ fprintf(tc, "uchar spin_c_typ[NCLAIMS]; /* claim-types */\n");
+ }
+
ntimes(th, 0, 1, Head0);
if (separate != 2)
{ extern void c_add_stack(FILE *);
+ extern void c_stack_size(FILE *);
ntimes(th, 0, 1, Header);
+ fprintf(th, "#define StackSize (");
+ c_stack_size(th);
+ fprintf(th, ")\n");
+
c_add_stack(th);
ntimes(th, 0, 1, Header0);
+ } else
+ { fprintf(th, "extern char *emalloc(unsigned long);\n");
}
ntimes(th, 0, 1, Head1);
@@ -96,7 +209,13 @@
hastrack = c_add_sv(th);
+ fprintf(th, "#ifdef TRIX\n");
+ fprintf(th, " /* room for 512 proc+chan ptrs, + safety margin */\n");
+ fprintf(th, " char *_ids_[MAXPROC+MAXQ+4];\n");
+ fprintf(th, "#else\n");
fprintf(th, " uchar sv[VECTORSZ];\n");
+ fprintf(th, "#endif\n");
+
fprintf(th, "} State");
#ifdef SOLARIS
fprintf(th,"\n#ifdef GCC\n");
@@ -105,8 +224,24 @@
#endif
fprintf(th, ";\n\n");
- fprintf(th, "#define HAS_TRACK %d\n", hastrack);
+ fprintf(th, "#ifdef TRIX\n");
+ fprintf(th, "typedef struct TRIX_v6 {\n");
+ fprintf(th, " uchar *body; /* aligned */\n");
+ fprintf(th, "#ifndef BFS\n");
+ fprintf(th, " short modified;\n");
+ fprintf(th, "#endif\n");
+ fprintf(th, " short psize;\n");
+ fprintf(th, " short parent_pid;\n");
+ fprintf(th, " struct TRIX_v6 *nxt;\n");
+ fprintf(th, "} TRIX_v6;\n");
+ fprintf(th, "#endif\n\n");
+ fprintf(th, "#define HAS_TRACK %d\n", hastrack);
+ if (0 && hastrack) /* not really a problem */
+ { fprintf(th, "#ifdef BFS_PAR\n");
+ fprintf(th, " #error cannot use BFS_PAR on models with c_track stmnts\n");
+ fprintf(th, "#endif\n");
+ }
if (separate != 2)
dohidden();
}
@@ -116,14 +251,36 @@
{ ProcList *p;
int i = 0;
- if (separate ==2) goto shortcut;
+ if (separate == 2) goto shortcut;
- fprintf(tc, "int\naddproc(int n");
- for (i = 0; i < Npars; i++)
+ ntimes(tc, nrRdy+1, nrRdy+2, R2); /* +1 for np_ -- was th */
+
+ fprintf(tc, "#ifdef TRIX\n");
+ fprintf(tc, "int what_p_size(int);\n");
+ fprintf(tc, "int what_q_size(int);\n\n");
+
+ /* the number of processes just changed by 1 (up or down) */
+ /* this means that the channel indices move up or down by one slot */
+ /* not all new channels may have a valid index yet, but we move */
+ /* all of them anyway, as if they existed */
+ ntimes(tc, 0, 1, R7a);
+ fprintf(tc, "#endif\n\n");
+
+ ntimes(tc, 0, 1, R7b);
+
+ fprintf(tc, "int\naddproc(int calling_pid, int priority, int n");
+ for (/* i = 0 */; i < Npars; i++)
fprintf(tc, ", int par%d", i);
ntimes(tc, 0, 1, Addp0);
ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
+
+ if (nclaims > 1)
+ { fprintf(tc, "#ifndef NOCLAIM\n");
+ ntimes(tc, nrRdy+1, nrRdy+2, R5);
+ fprintf(tc, "#endif\n");
+ }
+
ntimes(tc, 0, 1, Addp1);
if (has_provided)
@@ -132,6 +289,9 @@
fprintf(tt, "{\n\tswitch(ot) {\n");
}
shortcut:
+ if (nclaims > 1)
+ { multi_init();
+ }
tc_predef_np();
for (p = rdy; p; p = p->nxt)
{ Pid = p->tn;
@@ -157,8 +317,17 @@
do_locinits(FILE *fd)
{ ProcList *p;
+ /* the locinit functions may refer to pptr or qptr */
+ fprintf(fd, "#if VECTORSZ>32000\n");
+ fprintf(fd, " extern int \n");
+ fprintf(fd, "#else\n");
+ fprintf(fd, " extern short \n");
+ fprintf(fd, "#endif\n");
+ fprintf(fd, " *proc_offset, *q_offset;\n");
+
for (p = rdy; p; p = p->nxt)
- c_add_locinit(fd, p->tn, p->n->name);
+ { c_add_locinit(fd, p->tn, p->n->name);
+ }
}
void
@@ -167,33 +336,64 @@
switch (separate) {
case 2:
- if (claimnr >= 0)
- ntimes(tc, claimnr, claimnr+1, R0); /* claim only */
+ if (nclaims > 0)
+ { for (p = rdy; p; p = p->nxt)
+ { if (p->b == N_CLAIM)
+ { ntimes(tc, p->tn, p->tn+1, R0); /* claims only */
+ fprintf(tc, "#ifdef HAS_CODE\n");
+ ntimes(tc, p->tn, p->tn+1, R00);
+ fprintf(tc, "#endif\n");
+ } } }
break;
case 1:
ntimes(tc, 0, 1, Code0);
- ntimes(tc, 0, claimnr, R0); /* all except claim */
- ntimes(tc, claimnr+1, nrRdy, R0);
+ for (p = rdy; p; p = p->nxt)
+ { if (p->b != N_CLAIM)
+ { ntimes(tc, p->tn, p->tn+1, R0); /* all except claims */
+ fprintf(tc, "#ifdef HAS_CODE\n");
+ ntimes(tc, p->tn, p->tn+1, R00);
+ fprintf(tc, "#endif\n");
+ } }
break;
case 0:
ntimes(tc, 0, 1, Code0);
ntimes(tc, 0, nrRdy+1, R0); /* +1 for np_ */
+ fprintf(tc, "#ifdef HAS_CODE\n");
+ ntimes(tc, 0, nrRdy+1, R00); /* +1 for np_ */
+ fprintf(tc, "#endif\n");
break;
}
+ /* new place, make sure Maxbody is set to its final value here */
+ fprintf(tc, "\n");
+ if (separate != 2)
+ { ntimes(tc, 1, u_sync+u_async+1, R3); /* nqs is still 0 */
+ fprintf(tc, "\tMaxbody = max(Maxbody, sizeof(State)-VECTORSZ);\n");
+ fprintf(tc, "\tif ((Maxbody %% WS) != 0)\n");
+ fprintf(tc, "\t Maxbody += WS - (Maxbody %% WS);\n\n");
+ }
+
for (p = rdy; p; p = p->nxt)
end_labs(p->n, p->tn);
switch (separate) {
case 2:
- if (claimnr >= 0)
- ntimes(tc, claimnr, claimnr+1, R0a); /* claim only */
+ if (nclaims > 0)
+ { for (p = rdy; p; p = p->nxt)
+ { if (p->b == N_CLAIM)
+ { ntimes(tc, p->tn, p->tn+1, R0a); /* claims only */
+ } } }
return;
case 1:
- ntimes(tc, 0, claimnr, R0a); /* all except claim */
- ntimes(tc, claimnr+1, nrRdy, R0a);
+ for (p = rdy; p; p = p->nxt)
+ { if (p->b != N_CLAIM)
+ { ntimes(tc, p->tn, p->tn+1, R0a); /* all except claims */
+ } }
fprintf(tc, " if (state_tables)\n");
- fprintf(tc, " ini_claim(%d, 0);\n", claimnr);
+ fprintf(tc, " ini_claim(%d, 0);\n", claimnr); /* the default claim */
+ if (acceptors == 0)
+ { acceptors = 1; /* assume at least 1 acceptstate */
+ }
break;
case 0:
ntimes(tc, 0, nrRdy, R0a); /* all */
@@ -200,30 +400,25 @@
break;
}
- ntimes(tc, 0, 1, R0b);
- if (separate == 1 && acceptors == 0)
- acceptors = 1; /* assume at least 1 acceptstate */
ntimes(th, acceptors, acceptors+1, Code1);
ntimes(th, progressors, progressors+1, Code3);
- ntimes(th, nrRdy+1, nrRdy+2, R2); /* +1 for np_ */
- fprintf(tc, " iniglobals();\n");
- ntimes(tc, 0, 1, Code2a);
- ntimes(tc, 0, 1, Code2b); /* bfs option */
- ntimes(tc, 0, 1, Code2c);
+ ntimes(tc, 0, 1, Code2a); /* dfs, bfs */
+ ntimes(tc, 0, 1, Code2e); /* multicore */
+ ntimes(tc, 0, 1, Code2c); /* multicore */
+ ntimes(tc, 0, 1, Code2d);
+
+ fprintf(tc, "void\ndo_reach(void)\n{\n");
ntimes(tc, 0, nrRdy, R4);
fprintf(tc, "}\n\n");
- fprintf(tc, "void\n");
- fprintf(tc, "iniglobals(void)\n{\n");
+ fprintf(tc, "void\niniglobals(int calling_pid)\n{\n");
if (doglobal("", INIV) > 0)
{ fprintf(tc, "#ifdef VAR_RANGES\n");
(void) doglobal("logval(\"", LOGV);
fprintf(tc, "#endif\n");
}
- ntimes(tc, 1, nqs+1, R3);
- fprintf(tc, "\tMaxbody = max(Maxbody, sizeof(State)-VECTORSZ);");
- fprintf(tc, "\n}\n\n");
+ fprintf(tc, "}\n\n");
}
void
@@ -248,17 +443,17 @@
Label *l;
int j; char foo[128];
- if ((i == claimnr && separate == 1)
- || (i != claimnr && separate == 2))
+ if ((pid_is_claim(i) && separate == 1)
+ || (!pid_is_claim(i) && separate == 2))
return;
for (l = labtab; l; l = l->nxt)
for (j = 0; ln[j].n; j++)
- if (strncmp(l->s->name, ln[j].s, ln[j].n) == 0
+ { if (strncmp(l->s->name, ln[j].s, ln[j].n) == 0
&& strcmp(l->c->name, s->name) == 0)
{ fprintf(tc, "\t%s[%d][%d] = 1;\n",
ln[j].t, i, l->e->seqno);
- acceptors += ln[j].m;
+ acceptors += ln[j].m;
progressors += ln[j].p;
if (l->e->status & D_ATOM)
{ sprintf(foo, "%s label inside d_step",
@@ -272,8 +467,7 @@
Fname = l->e->n->fn;
printf("spin: %3d:%s, warning, %s - is invisible\n",
lineno, Fname?Fname->name:"-", foo);
- }
- }
+ } } }
/* visible states -- through remote refs: */
for (l = labtab; l; l = l->nxt)
if (l->visible
@@ -286,7 +480,7 @@
}
void
-ntimes(FILE *fd, int n, int m, char *c[])
+ntimes(FILE *fd, int n, int m, const char *c[])
{
int i, j;
for (j = 0; c[j]; j++)
@@ -305,7 +499,7 @@
n = (s->context != ZS)?s->context->ini:s->ini;
if (n)
- printf("line %3d %s, ", n->ln, n->fn->name);
+ printf("line %s:%d, ", n->fn->name, n->ln);
}
void
@@ -338,7 +532,7 @@
{ if (!(verbose&32)) return;
sputtype(buf, sp->type);
i = (int) strlen(buf);
- while (buf[--i] == ' ') buf[i] = '\0';
+ while (i > 0 && buf[--i] == ' ') buf[i] = '\0';
prehint(sp);
if (sp->context)
printf("proctype %s:", s);
@@ -361,12 +555,12 @@
}
}
-int
-dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s)
+static int
+dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s, enum btypes b)
{ int h, j, k=0; extern int nr_errs;
Ordered *walk;
Symbol *sp;
- char buf[64], buf2[128], buf3[128];
+ char buf[128], buf2[128], buf3[128];
if (dowhat == INIV)
{ /* initialize in order of declaration */
@@ -390,7 +584,8 @@
if (sp->context
&& !sp->owner
&& sp->type == Types[j]
- && ((h == 0 && sp->nel == 1) || (h == 1 && sp->nel > 1))
+ && ((h == 0 && (sp->nel == 1 && sp->isarray == 0))
+ || (h == 1 && (sp->nel > 1 || sp->isarray == 1)))
&& strcmp(s, sp->context->name) == 0)
{ switch (dowhat) {
case LOGV:
@@ -409,7 +604,7 @@
k++;
break;
}
- if (strcmp(s, ":never:") == 0)
+ if (b == N_CLAIM)
{ printf("error: %s defines local %s\n",
s, sp->name);
nr_errs++;
@@ -425,8 +620,8 @@
int i;
if (!qtab)
- { fprintf(fd, "void\nc_chandump(int unused) ");
- fprintf(fd, "{ unused = unused++; /* avoid complaints */ }\n");
+ { fprintf(fd, "void\nc_chandump(int unused)\n");
+ fprintf(fd, "{\tunused++; /* avoid complaints */\n}\n");
return;
}
@@ -465,9 +660,19 @@
void
c_var(FILE *fd, char *pref, Symbol *sp)
-{ char buf[256];
+{ char *ptr, buf[256];
int i;
+ if (!sp)
+ { fatal("cannot happen - c_var", 0);
+ }
+
+ ptr = sp->name;
+ if (!old_scope_rules)
+ { while (*ptr == '_' || isdigit((int)*ptr))
+ { ptr++;
+ } }
+
switch (sp->type) {
case STRUCT:
/* c_struct(fd, pref, sp); */
@@ -476,27 +681,33 @@
sprintf(buf, "%s%s.", pref, sp->name);
c_struct(fd, buf, sp);
break;
+ case MTYPE:
case BIT: case BYTE:
case SHORT: case INT:
case UNSIGNED:
sputtype(buf, sp->type);
- if (sp->nel == 1)
- { fprintf(fd, "\tprintf(\"\t%s %s:\t%%d\\n\", %s%s);\n",
- buf, sp->name, pref, sp->name);
+ if (sp->nel == 1 && sp->isarray == 0)
+ {
+ if (sp->type == MTYPE && ismtype(sp->name))
+ { fprintf(fd, "\tprintf(\"\t%s %s:\t%d\\n\");\n",
+ buf, ptr, ismtype(sp->name));
+ } else
+ { fprintf(fd, "\tprintf(\"\t%s %s:\t%%d\\n\", %s%s);\n",
+ buf, ptr, pref, sp->name);
+ }
} else
{ fprintf(fd, "\t{\tint l_in;\n");
fprintf(fd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n", sp->nel);
fprintf(fd, "\t\t{\n");
fprintf(fd, "\t\t\tprintf(\"\t%s %s[%%d]:\t%%d\\n\", l_in, %s%s[l_in]);\n",
- buf, sp->name, pref, sp->name);
+ buf, ptr, pref, sp->name);
fprintf(fd, "\t\t}\n");
fprintf(fd, "\t}\n");
}
break;
case CHAN:
- if (sp->nel == 1)
- { fprintf(fd, "\tprintf(\"\tchan %s (=%%d):\tlen %%d:\\t\", ",
- sp->name);
+ if (sp->nel == 1 && sp->isarray == 0)
+ { fprintf(fd, "\tprintf(\"\tchan %s (=%%d):\tlen %%d:\\t\", ", ptr);
fprintf(fd, "%s%s, q_len(%s%s));\n",
pref, sp->name, pref, sp->name);
fprintf(fd, "\tc_chandump(%s%s);\n", pref, sp->name);
@@ -503,7 +714,7 @@
} else
for (i = 0; i < sp->nel; i++)
{ fprintf(fd, "\tprintf(\"\tchan %s[%d] (=%%d):\tlen %%d:\\t\", ",
- sp->name, i);
+ ptr, i);
fprintf(fd, "%s%s[%d], q_len(%s%s[%d]));\n",
pref, sp->name, i, pref, sp->name, i);
fprintf(fd, "\tc_chandump(%s%s[%d]);\n",
@@ -518,9 +729,7 @@
{ Ordered *walk;
Symbol *sp;
- if (strcmp(p->n->name, ":never:") != 0
- && strcmp(p->n->name, ":trace:") != 0
- && strcmp(p->n->name, ":notrace:") != 0)
+ if (p->b != N_CLAIM && p->b != E_TRACE && p->b != N_TRACE)
for (walk = all_names; walk; walk = walk->next)
{ sp = walk->entry;
if (!sp->context
@@ -541,9 +750,7 @@
Symbol *sp;
char pref[64];
- if (strcmp(p->n->name, ":never:") != 0
- && strcmp(p->n->name, ":trace:") != 0
- && strcmp(p->n->name, ":notrace:") != 0)
+ if (p->b != N_CLAIM && p->b != E_TRACE && p->b != N_TRACE)
for (walk = all_names; walk; walk = walk->next)
{ sp = walk->entry;
if (!sp->context
@@ -571,10 +778,8 @@
fprintf(fd, " printf(\"global vars:\\n\");\n");
for (walk = all_names; walk; walk = walk->next)
{ sp = walk->entry;
- if (sp->context || sp->owner || (sp->hidden&1)
- || (sp->type == MTYPE && ismtype(sp->name)))
+ if (sp->context || sp->owner || (sp->hidden&1))
continue;
-
c_var(fd, "now.", sp);
}
fprintf(fd, "}\n");
@@ -583,8 +788,6 @@
fprintf(fd, " switch(tp) {\n");
for (p = rdy; p; p = p->nxt)
{ fprintf(fd, " case %d:\n", p->tn);
- fprintf(fd, " \tprintf(\"local vars proc %%d (%s):\\n\", pid);\n",
- p->n->name);
if (c_splurge_any(p))
{ fprintf(fd, " \tprintf(\"local vars proc %%d (%s):\\n\", pid);\n",
p->n->name);
@@ -633,8 +836,9 @@
checktype(sp, (char *) 0);
cnt++; /* fall through */
case PUTV:
- do_var(tc, dowhat, (sp->hidden&1)?"":"now.", sp,
- "", " = ", ";\n");
+ do_var(tc, dowhat,
+ (sp->hidden&1)?"":"now.", sp,
+ "", " = ", ";\n");
break;
} } }
return cnt;
@@ -652,13 +856,12 @@
if ((sp->hidden&1)
&& sp->type == Types[j])
{ if (sp->context || sp->owner)
- fatal("cannot hide non-globals (%s)", sp->name);
+ fatal("cannot hide non-globals (%s)", sp->name);
if (sp->type == CHAN)
- fatal("cannot hide channels (%s)", sp->name);
+ fatal("cannot hide channels (%s)", sp->name);
fprintf(th, "/* hidden variable: */");
typ2c(sp);
} }
- fprintf(th, "int _; /* a predefined write-only variable */\n\n");
}
void
@@ -665,15 +868,25 @@
do_var(FILE *ofd, int dowhat, char *s, Symbol *sp,
char *pre, char *sep, char *ter)
{ int i;
+ char *ptr = sp?sp->name:"";
+ if (!sp)
+ { fatal("cannot happen - do_var", 0);
+ }
+
switch(dowhat) {
case PUTV:
-
if (sp->hidden&1) break;
typ2c(sp);
break;
+
case LOGV:
+ if (!old_scope_rules)
+ { while (*ptr == '_' || isdigit((int)*ptr))
+ { ptr++;
+ } }
+ /* fall thru */
case INIV:
if (sp->type == STRUCT)
{ /* struct may contain a chan */
@@ -682,13 +895,16 @@
}
if (!sp->ini && dowhat != LOGV) /* it defaults to 0 */
break;
- if (sp->nel == 1)
- { fprintf(ofd, "\t\t%s%s%s%s",
- pre, s, sp->name, sep);
- if (dowhat == LOGV)
+ if (sp->nel == 1 && sp->isarray == 0)
+ { if (dowhat == LOGV)
+ { fprintf(ofd, "\t\t%s%s%s%s",
+ pre, s, ptr, sep);
fprintf(ofd, "%s%s", s, sp->name);
- else
+ } else
+ { fprintf(ofd, "\t\t%s%s%s%s",
+ pre, s, sp->name, sep);
do_init(ofd, sp);
+ }
fprintf(ofd, "%s", ter);
} else
{ if (sp->ini && sp->ini->ntyp == CHAN)
@@ -702,20 +918,38 @@
do_init(ofd, sp);
fprintf(ofd, "%s", ter);
}
- } else
- { fprintf(ofd, "\t{\tint l_in;\n");
- fprintf(ofd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n", sp->nel);
- fprintf(ofd, "\t\t{\n");
- fprintf(ofd, "\t\t\t%s%s%s[l_in]%s",
+ } else if (sp->ini)
+ { if (dowhat != LOGV && sp->isarray && sp->ini->ntyp == ',')
+ { Lextok *z, *y;
+ z = sp->ini;
+ for (i = 0; i < sp->nel; i++)
+ { if (z && z->ntyp == ',')
+ { y = z->lft;
+ z = z->rgt;
+ } else
+ { y = z;
+ }
+ fprintf(ofd, "\t\t%s%s%s[%d]%s",
+ pre, s, sp->name, i, sep);
+ putstmnt(ofd, y, 0);
+ fprintf(ofd, "%s", ter);
+ }
+ } else
+ { fprintf(ofd, "\t{\tint l_in;\n");
+ fprintf(ofd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n",
+ sp->nel);
+ fprintf(ofd, "\t\t{\n");
+ fprintf(ofd, "\t\t\t%s%s%s[l_in]%s",
pre, s, sp->name, sep);
- if (dowhat == LOGV)
- fprintf(ofd, "%s%s[l_in]", s, sp->name);
- else
- putstmnt(ofd, sp->ini, 0);
- fprintf(ofd, "%s", ter);
- fprintf(ofd, "\t\t}\n");
- fprintf(ofd, "\t}\n");
- } }
+ if (dowhat == LOGV)
+ { fprintf(ofd, "%s%s[l_in]", s, sp->name);
+ } else
+ { putstmnt(ofd, sp->ini, 0);
+ }
+ fprintf(ofd, "%s", ter);
+ fprintf(ofd, "\t\t}\n");
+ fprintf(ofd, "\t}\n");
+ } } }
break;
}
}
@@ -722,57 +956,48 @@
static void
do_init(FILE *ofd, Symbol *sp)
-{ int i; extern Queue *ltab[];
+{ int i;
if (sp->ini
&& sp->type == CHAN
&& ((i = qmake(sp)) > 0))
{ if (sp->ini->ntyp == CHAN)
- fprintf(ofd, "addqueue(%d, %d)",
- i, ltab[i-1]->nslots == 0);
- else
- fprintf(ofd, "%d", i);
+ { fprintf(ofd, "addqueue(calling_pid, %d, %d)",
+ i, ltab[i-1]->nslots == 0);
+ } else
+ { fprintf(ofd, "%d", i);
+ }
} else
- putstmnt(ofd, sp->ini, 0);
+ { putstmnt(ofd, sp->ini, 0);
+ }
}
-static int
-blog(int n) /* for small log2 without rounding problems */
-{ int m=1, r=2;
-
- while (r < n) { m++; r *= 2; }
- return 1+m;
-}
-
static void
-put_ptype(char *s, int i, int m0, int m1)
+put_ptype(char *s, int i, int m0, int m1, enum btypes b)
{ int k;
- if (strcmp(s, ":init:") == 0)
- fprintf(th, "#define Pinit ((P%d *)this)\n", i);
+ if (b == I_PROC)
+ { fprintf(th, "#define Pinit ((P%d *)this)\n", i);
+ } else if (b == P_PROC || b == A_PROC)
+ { fprintf(th, "#define P%s ((P%d *)this)\n", s, i);
+ }
- if (strcmp(s, ":never:") != 0
- && strcmp(s, ":trace:") != 0
- && strcmp(s, ":notrace:") != 0
- && strcmp(s, ":init:") != 0
- && strcmp(s, "_:never_template:_") != 0
- && strcmp(s, "np_") != 0)
- fprintf(th, "#define P%s ((P%d *)this)\n", s, i);
-
fprintf(th, "typedef struct P%d { /* %s */\n", i, s);
fprintf(th, " unsigned _pid : 8; /* 0..255 */\n");
fprintf(th, " unsigned _t : %d; /* proctype */\n", blog(m1));
fprintf(th, " unsigned _p : %d; /* state */\n", blog(m0));
+ fprintf(th, "#ifdef HAS_PRIORITY\n");
+ fprintf(th, " unsigned _priority : 8; /* 0..255 */\n");
+ fprintf(th, "#endif\n");
LstSet = ZS;
nBits = 8 + blog(m1) + blog(m0);
- k = dolocal(tc, "", PUTV, i, s); /* includes pars */
-
+ k = dolocal(tc, "", PUTV, i, s, b); /* includes pars */
c_add_loc(th, s);
fprintf(th, "} P%d;\n", i);
if ((!LstSet && k > 0) || has_state)
- fprintf(th, "#define Air%d 0\n", i);
- else
+ fprintf(th, "#define Air%d 0\n\n", i);
+ else if (LstSet || k == 0) /* 5.0, added condition */
{ fprintf(th, "#define Air%d (sizeof(P%d) - ", i, i);
if (k == 0)
{ fprintf(th, "%d", (nBits+7)/8);
@@ -802,35 +1027,79 @@
fatal("cannot happen Air %s",
LstSet->name);
}
-done: fprintf(th, ")\n");
+done: fprintf(th, ")\n\n");
}
}
static void
tc_predef_np(void)
-{ int i = nrRdy; /* 1+ highest proctype nr */
+{
+ fprintf(th, "#define _NP_ %d\n", nrRdy); /* 1+ highest proctype nr */
- fprintf(th, "#define _NP_ %d\n", i);
-/* if (separate == 2) fprintf(th, "extern "); */
- fprintf(th, "uchar reached%d[3]; /* np_ */\n", i);
+ fprintf(th, "#define _nstates%d 3 /* np_ */\n", nrRdy);
+ fprintf(th, "#define _endstate%d 2 /* np_ */\n\n", nrRdy);
+ fprintf(th, "#define _start%d 0 /* np_ */\n", nrRdy);
- fprintf(th, "#define nstates%d 3 /* np_ */\n", i);
- fprintf(th, "#define endstate%d 2 /* np_ */\n\n", i);
- fprintf(th, "#define start%d 0 /* np_ */\n", i);
-
- fprintf(tc, "\tcase %d: /* np_ */\n", i);
+ fprintf(tc, "\tcase %d: /* np_ */\n", nrRdy);
if (separate == 1)
- { fprintf(tc, "\t\tini_claim(%d, h);\n", i);
+ { fprintf(tc, "\t\tini_claim(%d, h);\n", nrRdy);
} else
- { fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, i);
- fprintf(tc, "\t\t((P%d *)pptr(h))->_p = 0;\n", i);
- fprintf(tc, "\t\treached%d[0] = 1;\n", i);
- fprintf(tc, "\t\taccpstate[%d][1] = 1;\n", i);
+ { fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", nrRdy, nrRdy);
+ fprintf(tc, "\t\t((P%d *)pptr(h))->_p = 0;\n", nrRdy);
+
+ fprintf(tc, "#ifdef HAS_PRIORITY\n");
+ fprintf(tc, "\t\t((P%d *)pptr(h))->_priority = priority;\n", nrRdy);
+ fprintf(tc, "#endif\n");
+
+ fprintf(tc, "\t\treached%d[0] = 1;\n", nrRdy);
+ fprintf(tc, "\t\taccpstate[%d][1] = 1;\n", nrRdy);
}
fprintf(tc, "\t\tbreak;\n");
}
static void
+multi_init(void)
+{ ProcList *p;
+ Element *e;
+ int i = nrRdy+1;
+ int ini, j;
+ int nrc = nclaims;
+
+ fprintf(tc, "#ifndef NOCLAIM\n");
+ fprintf(tc, "\tcase %d: /* claim select */\n", i);
+ for (p = rdy, j = 0; p; p = p->nxt, j++)
+ { if (p->b == N_CLAIM)
+ { e = p->s->frst;
+ ini = huntele(e, e->status, -1)->seqno;
+
+ fprintf(tc, "\t\tspin_c_typ[%d] = %d; /* %s */\n",
+ j, p->tn, p->n->name);
+ fprintf(tc, "\t\t((P%d *)pptr(h))->c_cur[%d] = %d;\n",
+ i, j, ini);
+ fprintf(tc, "\t\treached%d[%d]=1;\n", p->tn, ini);
+
+ /* the default initial claim is first one in model */
+ if (--nrc == 0)
+ { fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, p->tn);
+ fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;\n", i, ini);
+ fprintf(tc, "\t\t((P%d *)pptr(h))->_n = %d; /* %s */\n",
+ i, j, p->n->name);
+ fprintf(tc, "\t\tsrc_claim = src_ln%d;\n", p->tn);
+ fprintf(tc, "#ifndef BFS\n");
+ fprintf(tc, "\t\tif (whichclaim == -1 && claimname == NULL)\n");
+ fprintf(tc, "\t\t\tprintf(\"0: Claim %s (%d), from state %d\\n\");\n",
+ p->n->name, p->tn, ini);
+ fprintf(tc, "#endif\n");
+ }
+ } }
+ fprintf(tc, "\t\tif (whichclaim != -1)\n");
+ fprintf(tc, "\t\t{ select_claim(whichclaim);\n");
+ fprintf(tc, "\t\t}\n");
+ fprintf(tc, "\t\tbreak;\n\n");
+ fprintf(tc, "#endif\n");
+}
+
+static void
put_pinit(ProcList *P)
{ Lextok *fp, *fpt, *t;
Element *e = P->s->frst;
@@ -839,7 +1108,7 @@
int i = P->tn;
int ini, j, k;
- if (i == claimnr
+ if (pid_is_claim(i)
&& separate == 1)
{ fprintf(tc, "\tcase %d: /* %s */\n", i, s->name);
fprintf(tc, "\t\tini_claim(%d, h);\n", i);
@@ -846,14 +1115,12 @@
fprintf(tc, "\t\tbreak;\n");
return;
}
- if (i != claimnr
+ if (!pid_is_claim(i)
&& separate == 2)
return;
ini = huntele(e, e->status, -1)->seqno;
- fprintf(th, "#define start%d %d\n", i, ini);
- if (i == claimnr)
- fprintf(th, "#define start_claim %d\n", ini);
+ fprintf(th, "#define _start%d %d\n", i, ini);
if (i == eventmapnr)
fprintf(th, "#define start_event %d\n", ini);
@@ -860,9 +1127,18 @@
fprintf(tc, "\tcase %d: /* %s */\n", i, s->name);
fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, i);
- fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;", i, ini);
- fprintf(tc, " reached%d[%d]=1;\n", i, ini);
+ fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;\n", i, ini);
+ fprintf(tc, "#ifdef HAS_PRIORITY\n");
+ fprintf(tc, "\t\t((P%d *)pptr(h))->_priority = priority; /* was: %d */\n",
+ i, (P->priority<1)? 1 : P->priority);
+
+ fprintf(tc, "#endif\n");
+ fprintf(tc, "\t\treached%d[%d]=1;\n", i, ini);
+ if (P->b == N_CLAIM)
+ { fprintf(tc, "\t\tsrc_claim = src_ln%d;\n", i);
+ }
+
if (has_provided)
{ fprintf(tt, "\tcase %d: /* %s */\n\t\t", i, s->name);
if (P->prov)
@@ -879,7 +1155,7 @@
for (fp = p, j=0; fp; fp = fp->rgt)
for (fpt = fp->lft; fpt; fpt = fpt->rgt, j++)
{ t = (fpt->ntyp == ',') ? fpt->lft : fpt;
- if (t->sym->nel != 1)
+ if (t->sym->nel > 1 || t->sym->isarray)
{ lineno = t->ln;
Fname = t->fn;
fatal("array in parameter list, %s",
@@ -898,10 +1174,10 @@
fprintf(tc, " = par%d;\n", j);
}
fprintf(tc, "\t\t/* locals: */\n");
- k = dolocal(tc, "", INIV, i, s->name);
+ k = dolocal(tc, "", INIV, i, s->name, P->b);
if (k > 0)
{ fprintf(tc, "#ifdef VAR_RANGES\n");
- (void) dolocal(tc, "logval(\"", LOGV, i, s->name);
+ (void) dolocal(tc, "logval(\"", LOGV, i, s->name, P->b);
fprintf(tc, "#endif\n");
}
@@ -929,17 +1205,19 @@
} }
if (cnt >= 200 || !e)
- fatal("confusing control structure", (char *) 0);
+ { lineno = (f && f->n)?f->n->ln:lineno;
+ fatal("confusing control. structure", (char *) 0);
+ }
return e;
}
Element *
-huntele(Element *f, int o, int stopat)
+huntele(Element *f, unsigned int o, int stopat)
{ Element *g, *e = f;
int cnt=0; /* a precaution against loops */
if (e)
- for (cnt = 0; cnt < 200 && e->n; cnt++)
+ for ( ; cnt < 500 && e->n; cnt++)
{
if (e->seqno == stopat)
break;
@@ -947,6 +1225,10 @@
switch (e->n->ntyp) {
case GOTO:
g = get_lab(e->n,1);
+ if (e == g)
+ { lineno = (f && f->n)?f->n->ln:lineno;
+ fatal("infinite goto loop", (char *) 0);
+ }
cross_dsteps(e->n, g->n);
break;
case '.':
@@ -957,6 +1239,9 @@
break;
case UNLESS:
g = huntele(e->sub->this->frst, o, stopat);
+ if (!g)
+ { fatal("unexpected error 1", (char *) 0);
+ }
break;
case D_STEP:
case ATOMIC:
@@ -968,8 +1253,10 @@
return e;
e = g;
}
- if (cnt >= 200 || !e)
+ if (cnt >= 500 || !e)
+ { lineno = (f && f->n)?f->n->ln:lineno;
fatal("confusing control structure", (char *) 0);
+ }
return e;
}
@@ -992,7 +1279,7 @@
nBits += sp->nbits;
break;
case BIT:
- if (sp->nel == 1 && !(sp->hidden&1))
+ if (sp->nel == 1 && sp->isarray == 0 && !(sp->hidden&1))
{ fprintf(th, "\tunsigned %s : 1", sp->name);
LstSet = sp;
nBits++;
@@ -1031,13 +1318,13 @@
fatal("variable %s undeclared", sp->name);
}
- if (sp->nel != 1)
+ if (sp->nel > 1 || sp->isarray)
fprintf(th, "[%d]", sp->nel);
fprintf(th, ";\n");
}
static void
-ncases(FILE *fd, int p, int n, int m, char *c[])
+ncases(FILE *fd, int p, int n, int m, const char *c[])
{ int i, j;
for (j = 0; c[j]; j++)
@@ -1067,12 +1354,11 @@
Queue *q;
ntimes(tc, 0, 1, Addq0);
+
if (has_io && !nqs)
fprintf(th, "#define NQS 1 /* nqs=%d, but has_io */\n", nqs);
else
fprintf(th, "#define NQS %d\n", nqs);
- fprintf(th, "short q_flds[%d];\n", nqs+1);
- fprintf(th, "short q_max[%d];\n", nqs+1);
for (q = qtab; q; q = q->nxt)
if (q->nslots > qmax)
@@ -1124,6 +1410,22 @@
ntimes(tc, 0, 1, Addq1);
+ fprintf(tc, "#ifdef TRIX\n");
+ fprintf(tc, "int\nwhat_p_size(int t)\n{\tint j;\n");
+ fprintf(tc, " switch (t) {\n");
+ ntimes(tc, 0, nrRdy+1, R5); /* +1 for np_ */
+ fprintf(tc, " default: Uerror(\"bad proctype\");\n");
+ fprintf(tc, " }\n return j;\n}\n\n");
+
+ fprintf(tc, "int\nwhat_q_size(int t)\n{\tint j;\n");
+ fprintf(tc, " switch (t) {\n");
+ for (j = 0; j < nqs+1; j++)
+ { fprintf(tc, " case %d: j = sizeof(Q%d); break;\n", j, j);
+ }
+ fprintf(tc, " default: Uerror(\"bad qtype\");\n");
+ fprintf(tc, " }\n return j;\n}\n");
+ fprintf(tc, "#endif\n\n");
+
if (has_random)
{ fprintf(th, "int Q_has(int");
for (j = 0; j < Mpars; j++)
@@ -1159,7 +1461,7 @@
fprintf(tc, "void\nqsend(int into, int sorted");
for (j = 0; j < Mpars; j++)
fprintf(tc, ", int fld%d", j);
- fprintf(tc, ")\n");
+ fprintf(tc, ", int args_given)\n");
ntimes(tc, 0, 1, Addq11);
for (q = qtab; q; q = q->nxt)
@@ -1202,6 +1504,12 @@
sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
for (j = 0; j < q->nflds; j++)
fprintf(tc, "\t\t%s%d = fld%d;\n", buf0, j, j);
+ fprintf(tc, "\t\tif (args_given != %d)\n", q->nflds);
+ fprintf(tc, "\t\t{ if (args_given > %d)\n", q->nflds);
+ fprintf(tc, "\t\t uerror(\"too many parameters in send stmnt\");\n");
+ fprintf(tc, "\t\t else\n");
+ fprintf(tc, "\t\t uerror(\"too few parameters in send stmnt\");\n");
+ fprintf(tc, "\t\t}\n");
fprintf(tc, "\t\tbreak;\n");
}
ntimes(tc, 0, 1, Addq2);
@@ -1261,14 +1569,15 @@
fprintf(tc, " case %d: j = sizeof(Q%d); break;\n",
q->qid, q->qid);
ntimes(tc, 0, 1, R8b);
+ ntimes(th, 0, 1, Proto); /* function prototypes */
- ntimes(th, 0, 1, Proto); /* tag on function prototypes */
fprintf(th, "void qsend(int, int");
for (j = 0; j < Mpars; j++)
fprintf(th, ", int");
- fprintf(th, ");\n");
+ fprintf(th, ", int);\n\n");
- fprintf(th, "#define Addproc(x) addproc(x");
+ fprintf(th, "#define Addproc(x,y) addproc(256, y, x");
+ /* 256 is param outside the range of valid pids */
for (j = 0; j < Npars; j++)
fprintf(th, ", 0");
fprintf(th, ")\n");
--- a/sys/src/cmd/spin/pangen1.h
+++ b/sys/src/cmd/spin/pangen1.h
@@ -1,20 +1,56 @@
/***** spin: pangen1.h *****/
-/* Copyright (c) 1989-2005 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
-static char *Code2a[] = { /* the tail of procedure run() */
- "#if defined(VERI) && !defined(NOREDUCE) && !defined(NP)",
+static const char *Code2a[] = { /* the tail of procedure run() */
+ " if (state_tables)",
+ " { if (dodot) exit(0);",
+ " printf(\"\\nTransition Type: \");",
+ " printf(\"A=atomic; D=d_step; L=local; G=global\\n\");",
+ " printf(\"Source-State Labels: \");",
+ " printf(\"p=progress; e=end; a=accept;\\n\");",
+ "#ifdef MERGED",
+ " printf(\"Note: statement merging was used. Only the first\\n\");",
+ " printf(\" stmnt executed in each merge sequence is shown\\n\");",
+ " printf(\" (use spin -a -o3 to disable statement merging)\\n\");",
+ "#endif",
+ " pan_exit(0);",
+ " }",
+ "#if defined(BFS) && defined(TRIX)", /* before iniglobals */
+ " { int i;",
+ " for (i = 0; i < MAXPROC+1; i++)",
+ " { processes[i] = (TRIX_v6 *) emalloc(sizeof(TRIX_v6));",
+ " processes[i]->body = (uchar *) emalloc(Maxbody * sizeof(char));",
+ " }",
+ " for (i = 0; i < MAXQ+1; i++)",
+ " { channels[i] = (TRIX_v6 *) emalloc(sizeof(TRIX_v6));",
+ " channels[i]->body = (uchar *) emalloc(Maxbody * sizeof(char));",
+ " } }",
+ "#endif",
+ "#ifdef BFS_PAR",
+ " bfs_setup_mem();",
+ " #ifdef COLLAPSE",
+ " /* this must be the very first allocation from the shared heap */",
+ " #ifdef BFS_SEP_HASH",
+ " ncomps = (ulong *) emalloc((ulong)((256+2) * sizeof(ulong)));",
+ " #else",
+ " ncomps = (ulong *) sh_pre_malloc((ulong)((256+2) * sizeof(ulong)));",
+ " #endif",
+ " #endif",
+ "#endif",
+ " iniglobals(258); /* arg outside range of pids */",
+ "#if defined(VERI) && !defined(NOREDUCE) && !defined(NP) && !defined(BFS) && !defined(HAS_LTL)",
" if (!state_tables",
- "#ifdef HAS_CODE",
+ " #ifdef HAS_CODE",
" && !readtrail",
- "#endif",
+ " #endif",
+ " #if NCORE>1",
+ " && core_id == 0",
+ " #endif",
" )",
" { printf(\"warning: for p.o. reduction to be valid \");",
" printf(\"the never claim must be stutter-invariant\\n\");",
@@ -24,14 +60,7 @@
"#endif",
" UnBlock; /* disable rendez-vous */",
"#ifdef BITSTATE",
-#ifndef POWOW
- " if (udmem)",
- " { udmem *= 1024L*1024L;",
- " SS = (uchar *) emalloc(udmem);",
- " bstore = bstore_mod;",
- " } else",
-#endif
- " SS = (uchar *) emalloc(1L<<(ssize-3));",
+ " sinit();",
"#else",
" hinit();",
"#endif",
@@ -39,18 +68,24 @@
" onstack_init();",
"#endif",
"#if defined(CNTRSTACK) && !defined(BFS)",
- " LL = (uchar *) emalloc(1L<<(ssize-3));",
+ " LL = (uchar *) emalloc(ONE_L<<(ssize-3));",
"#endif",
- " stack = ( Stack *) emalloc(sizeof(Stack));",
+ " stack = (_Stack *) emalloc(sizeof(_Stack));",
" svtack = (Svtack *) emalloc(sizeof(Svtack));",
" /* a place to point for Pptr of non-running procs: */",
- " noptr = (uchar *) emalloc(Maxbody * sizeof(char));",
- "#ifdef SVDUMP",
+ " noqptr = noptr = (uchar *) emalloc(Maxbody * sizeof(char));",
+ "#if defined(SVDUMP) && defined(VERBOSE)",
" if (vprefix > 0)",
- " write(svfd, (uchar *) &vprefix, sizeof(int));",
+ " (void) write(svfd, (uchar *) &vprefix, sizeof(int));",
"#endif",
"#ifdef VERI",
- " Addproc(VERI); /* never - pid = 0 */",
+ " Addproc(VERI,1); /* pid = 0, priority 1 */",
+ " #if NCLAIMS>1",
+ " if (claimname != NULL)",
+ " { whichclaim = find_claim(claimname);",
+ " select_claim(whichclaim);",
+ " }",
+ " #endif",
"#endif",
" active_procs(); /* started after never */",
"#ifdef EVENT_TRACE",
@@ -66,17 +101,21 @@
"#endif",
" do_the_search();",
"#ifdef BITSTATE",
- " if (--Nrun > 0 && HASH_CONST[++HASH_NR])",
+ " if (--Nrun > 0 && HASH_CONST[++HASH_NR])", /* last entry is 0 */
" { printf(\"Run %%d:\\n\", HASH_NR);",
" wrap_stats();",
" printf(\"\\n\");",
- " memset(SS, 0, 1L<<(ssize-3));",
- "#if defined(CNTRSTACK)",
- " memset(LL, 0, 1L<<(ssize-3));",
+ " if (udmem) /* Dillinger 3/2/09 */",
+ " { memset(SS, 0, udmem);",
+ " } else",
+ " { memset(SS, 0, ONE_L<<(ssize-3));",
+ " }",
+ "#ifdef CNTRSTACK",
+ " memset(LL, 0, ONE_L<<(ssize-3));",
"#endif",
- "#if defined(FULLSTACK)",
+ "#ifdef FULLSTACK",
" memset((uchar *) S_Tab, 0, ",
- " maxdepth*sizeof(struct H_el *));",
+ " maxdepth*sizeof(H_el *));",
"#endif",
" nstates=nlinks=truncs=truncs2=ngrabs = 0;",
" nlost=nShadow=hcmp = 0;",
@@ -86,10 +125,159 @@
" }",
"#endif",
"}",
+ "#ifdef HAS_PRIORITY",
+ "extern int highest_priority(int, short, Trans *);",
+ "extern int get_priority(int);",
+ "extern int set_priority(int, int);",
+ "#endif",
+ "#ifdef SPIN_HEAP",
+ "void *",
+ "spin_malloc(int n) /* reserved for use by Modex generated models */",
+ "{ char *spin_heap_ptr = &(now.spin_heap[now.spin_heap_n]);",
+ " if (now.spin_heap_n + n >= sizeof(now.spin_heap))",
+ " { Uerror(\"spin_heap limit reached\");",
+ " }",
+ " now.spin_heap_n += n;",
+ " return spin_heap_ptr;",
+ "}",
+ "void",
+ "spin_free(void *unused)",
+ "{ unused; /* ignore */",
+ "}",
+ "#endif",
+ "int",
+ "spin_join(int p, void **unused)",
+ "{ /* fprintf(stderr, \"join %%d when %%d\\n \", p, now._nr_pr); */",
+ " return (now._nr_pr <= p); /* process *p has stopped */",
+ "}",
+ "",
+ "int",
+ "spin_mutex_free(int *m)",
+ "{ return (*m == 0);",
+ "}",
+ "",
+ "int",
+ "spin_mutex_lock(int *m)",
+ "{ *m = 1;",
+ " return 1;",
+ "}",
+ "void",
+ "spin_mutex_destroy(int *m)",
+ "{ *m = 0;",
+ "}",
+ "void",
+ "spin_mutex_unlock(int *m)",
+ "{ *m = 0;",
+ "}",
+ "void",
+ "spin_mutex_init(int *m, void *val)",
+ "{",
+ " if (!val)", /* the 2nd arg must be NULL, for now */
+ " { *m = 0;",
+ " } else",
+ " { Uerror(\"pthread_mutex_init: unsupported non-default init\");",
+ " }",
+ "}",
+ "",
+ "int",
+ "spin_cond_wait(int *cond, int *lck)", /*release and re-acquire lock *lck */
+ "{ /* this version does not scale very far alas */",
+ " if (((P0 *)this)->_pid + 1 >= WS*8)", /* 32 or 64 */
+ " { Uerror(\"pid exceeds range supported by pthread_cond_wait\");",
+ " }",
+ " if (((*cond)&1) == 0)", /* repeatedly tested, so: */
+ " { spin_mutex_unlock(lck);", /* avoid double counting */
+ " *cond |= (1<<(((P0 *)this)->_pid + 1));",
+ " return 0;", /* blocked, must test again */
+ " } else",
+ " { /* if other processes are already waiting */",
+ " /* while our wait flag is 0, then they should go first */",
+ " if (((*cond)&(~(1 | (1<<(((P0 *)this)->_pid + 1))))) != 0)",
+ " { spin_mutex_unlock(lck);",
+ " return 0;", /* wait for the others to go first */
+ " }",
+ " *cond &= ~1;", /* clear the 'go' bit andy wait flag */
+ " *cond &= ~(1<<(((P0 *)this)->_pid + 1));",
+ " return 1;", /* okay to proceed */
+ " }",
+ "}",
+ "void",
+ "spin_cond_signal(int *cond)",
+ "{",
+ " if ( ((*cond)&(~1)) != 0 )", /* procs are waiting */
+ " { *cond |= 1;", /* set the 'go' bit */
+ " }",
+ "}",
+ "",
"#ifdef HAS_PROVIDED",
- "int provided(int, uchar, int, Trans *);",
+ " int provided(int, uchar, int, Trans *);",
"#endif",
+ "#ifdef BFS_PAR",
+ " extern void bfs_shutdown(const char *);",
+ "#endif",
+ "",
+ "#if NCORE>1",
+ " #define GLOBAL_LOCK (0)",
+ " #ifndef CS_N",
+ " #define CS_N (256*NCORE)", /* must be a power of 2 */
+ " #endif",
+ " #ifdef NGQ", /* no global queue */
+ " #define NR_QS (NCORE)",
+ " #define CS_NR (CS_N+1) /* 2^N + 1, nr critical sections */",
+ " #define GQ_RD GLOBAL_LOCK", /* not really used in this mode */
+ " #define GQ_WR GLOBAL_LOCK", /* but just in case... */
+ " #define CS_ID (1 + (int) (j1_spin & (CS_N-1))) /* mask: 2^N - 1, zero reserved */",
+ " #define QLOCK(n) (1+n)", /* overlaps first n zones of hashtable */
+ " #else",
+ " #define NR_QS (NCORE+1)", /* add a global queue */
+ " #define CS_NR (CS_N+3)", /* 2 extra locks for global q */
+ " #define GQ_RD (1)", /* read access to global q */
+ " #define GQ_WR (2)", /* write access to global q */
+ " #define CS_ID (3 + (int) (j1_spin & (CS_N-1)))",
+ " #define QLOCK(n) (3+n)",/* overlaps first n zones of hashtable */
+ " #endif",
+ "",
+ " #ifndef SEP_STATE",
+ " #define enter_critical(w) e_critical(w)",
+ " #define leave_critical(w) x_critical(w)",
+ " #else",
+ " #ifdef NGQ",
+ " #define enter_critical(w) { if (w < 1+NCORE) e_critical(w); }",
+ " #define leave_critical(w) { if (w < 1+NCORE) x_critical(w); }",
+ " #else",
+ " #define enter_critical(w) { if (w < 3+NCORE) e_critical(w); }",
+ " #define leave_critical(w) { if (w < 3+NCORE) x_critical(w); }",
+ " #endif",
+ " #endif",
+ "",
+ " int",
+ " cpu_printf(const char *fmt, ...)", /* only used with VERBOSE/CHECK/DEBUG */
+ " { va_list args;",
+ " enter_critical(GLOBAL_LOCK); /* printing */",
+ " printf(\"cpu%%d: \", core_id);",
+ " fflush(stdout);",
+ " va_start(args, fmt);",
+ " vprintf(fmt, args);",
+ " va_end(args);",
+ " fflush(stdout);",
+ " leave_critical(GLOBAL_LOCK);",
+ " return 1;",
+ " }",
+ "#else",
+ " #define enter_critical(w) /* none */",
+ " #define leave_critical(w) /* none */",
+ "",
+ " int",
+ " cpu_printf(const char *fmt, ...)",
+ " { va_list args;",
+ " va_start(args, fmt);",
+ " vprintf(fmt, args);",
+ " va_end(args);",
+ " return 1;",
+ " }",
+ "#endif",
+
#ifndef PRINTF
"int",
"Printf(const char *fmt, ...)",
@@ -132,7 +320,7 @@
"static int stackread;",
"static Trail frameptr;",
"Trail *",
- "getframe(int d)",
+ "getframe(long d)",
"{",
" if (CNT1 == CNT2)",
" return &trail[d];",
@@ -153,45 +341,85 @@
" return &frameptr;",
"}",
"#endif",
-
- "#if !defined(SAFETY) && !defined(BITSTATE)",
- "#if !defined(FULLSTACK) || defined(MA)",
- "#define depth_of(x) A_depth /* an estimate */",
- "#else",
- "int",
- "depth_of(struct H_el *s)",
- "{ Trail *t; int d;",
- " for (d = 0; d <= A_depth; d++)",
- " { t = getframe(d);",
- " if (s == t->ostate)",
- " return d;",
- " }",
- " printf(\"pan: cannot happen, depth_of\\n\");",
- " return depthfound;",
- "}",
+ "#if NCORE>1",
+ "extern void cleanup_shm(int);",
+ "volatile uint *search_terminated; /* to signal early termination */",
+ /*
+ * Meaning of bitflags in search_terminated:
+ * 1 set by pan_exit
+ * 2 set by wrapup
+ * 4 set by uerror
+ * 8 set by sudden_stop -- called after someone_crashed and [Uu]error
+ * 16 set by cleanup_shm
+ * 32 set by give_up -- called on signal
+ * 64 set by proxy_exit
+ * 128 set by proxy on write port failure
+ * 256 set by proxy on someone_crashed
+ *
+ * Flags 8|32|128|256 indicate abnormal termination
+ *
+ * The flags are checked in 4 functions in the code:
+ * sudden_stop()
+ * someone_crashed() (proxy and pan version)
+ * mem_hand_off()
+ */
"#endif",
- "#endif",
-
"void",
"pan_exit(int val)",
- "{ if (signoff) printf(\"--end of output--\\n\");",
+ "{ void stop_timer(int);",
+ "#ifdef BFS_PAR",
+ " extern void bfs_mark_done(int);",
+ " extern void bfs_drop_shared_memory(void);",
+ "#endif",
+ " if (signoff)",
+ " { printf(\"--end of output--\\n\");",
+ " }",
+ "#if NCORE>1",
+ " if (search_terminated != NULL)",
+ " { *search_terminated |= 1; /* pan_exit */",
+ " }",
+ "#ifdef USE_DISK",
+ " { void dsk_stats(void);",
+ " dsk_stats();",
+ " }",
+ "#endif",
+ " if (!state_tables && !readtrail)",
+ " { cleanup_shm(1);",
+ " }",
+ "#endif",
+ "#ifdef BFS_PAR",
+ " if (who_am_i != 0)",
+ " { bfs_mark_done(3); /* stopped */",
+ " }",
+ " bfs_drop_shared_memory();",
+ "#endif",
+ " if (val == 2)",
+ " { val = 0;",
+ " }",
+ "#ifdef BFS_PAR",
+ " if (who_am_i == 0)",
+ "#endif",
+ " stop_timer(1);",
+ "",
+ "#ifdef C_EXIT",
+ " C_EXIT; /* trust that it defines a fct */",
+ "#endif",
" exit(val);",
"}",
-
"#ifdef HAS_CODE",
+ "static char tbuf[2][2048];",
+ "",
"char *",
"transmognify(char *s)",
"{ char *v, *w;",
- " static char buf[2][2048];",
" int i, toggle = 0;",
-
" if (!s || strlen(s) > 2047) return s;",
- " memset(buf[0], 0, 2048);",
- " memset(buf[1], 0, 2048);",
- " strcpy(buf[toggle], s);",
- " while ((v = strstr(buf[toggle], \"{c_code\")))", /* assign v */
+ " memset(tbuf[0], 0, 2048);",
+ " memset(tbuf[1], 0, 2048);",
+ " strcpy(tbuf[toggle], s);",
+ " while ((v = strstr(tbuf[toggle], \"{c_code\")))", /* assign v */
" { *v = '\\0'; v++;",
- " strcpy(buf[1-toggle], buf[toggle]);",
+ " strcpy(tbuf[1-toggle], tbuf[toggle]);",
" for (w = v; *w != '}' && *w != '\\0'; w++) /* skip */;",
" if (*w != '}') return s;",
" *w = '\\0'; w++;",
@@ -198,18 +426,18 @@
" for (i = 0; code_lookup[i].c; i++)",
" if (strcmp(v, code_lookup[i].c) == 0",
" && strlen(v) == strlen(code_lookup[i].c))",
- " { if (strlen(buf[1-toggle])",
+ " { if (strlen(tbuf[1-toggle])",
" + strlen(code_lookup[i].t)",
" + strlen(w) > 2047)",
" return s;",
- " strcat(buf[1-toggle], code_lookup[i].t);",
+ " strcat(tbuf[1-toggle], code_lookup[i].t);",
" break;",
" }",
- " strcat(buf[1-toggle], w);",
+ " strcat(tbuf[1-toggle], w);",
" toggle = 1 - toggle;",
" }",
- " buf[toggle][2047] = '\\0';",
- " return buf[toggle];",
+ " tbuf[toggle][2047] = '\\0';",
+ " return tbuf[toggle];",
"}",
"#else",
"char * transmognify(char *s) { return s; }",
@@ -223,7 +451,6 @@
"",
" for (t = trans[ot][tt]; t; t = t->nxt)",
" { printf(\"\\t\\t\");",
-
" q = transmognify(t->tp);",
" for ( ; q && *q; q++)",
" if (*q == '\\n')",
@@ -233,6 +460,17 @@
" printf(\"\\n\");",
" }",
"}",
+ "",
+ "char *",
+ "find_source(int tp, int s)",
+ "{",
+ " if (s >= flref[tp]->from",
+ " && s <= flref[tp]->upto)",
+ " { return flref[tp]->fnm;",
+ " }",
+ " return PanSource; /* i.e., don't know */",
+ "}",
+ "",
"void",
"wrap_trail(void)",
"{ static int wrap_in_progress = 0;",
@@ -243,7 +481,7 @@
"",
" printf(\"spin: trail ends after %%ld steps\\n\", depth);",
" if (onlyproc >= 0)",
- " { if (onlyproc >= now._nr_pr) pan_exit(0);",
+ " { if (onlyproc >= now._nr_pr) { pan_exit(0); }",
" II = onlyproc;",
" z = (P0 *)pptr(II);",
" printf(\"%%3ld:\tproc %%d (%%s) \",",
@@ -250,7 +488,8 @@
" depth, II, procname[z->_t]);",
" for (i = 0; src_all[i].src; i++)",
" if (src_all[i].tp == (int) z->_t)",
- " { printf(\" line %%3d\",",
+ " { printf(\" %%s:%%d\",",
+ " find_source((int) z->_t, (int) z->_p),",
" src_all[i].src[z->_p]);",
" break;",
" }",
@@ -269,7 +508,8 @@
" depth, II, procname[z->_t]);",
" for (i = 0; src_all[i].src; i++)",
" if (src_all[i].tp == (int) z->_t)",
- " { printf(\" line %%3d\",",
+ " { printf(\" %%s:%%d\",",
+ " find_source((int) z->_t, (int) z->_p),",
" src_all[i].src[z->_p]);",
" break;",
" }",
@@ -293,23 +533,100 @@
"findtrail(void)",
"{ FILE *fd;",
" char fnm[512], *q;",
- " char MyFile[512];",
+ " char MyFile[512];", /* avoid using a non-writable string */
+ " char MySuffix[16];",
+ " int try_core;",
+ " int candidate_files;",
"",
- " strcpy(MyFile, TrailFile);", /* avoid problem with non-writable strings */
+ " if (trailfilename != NULL)",
+ " { fd = fopen(trailfilename, \"r\");",
+ " if (fd == NULL)",
+ " { printf(\"pan: cannot find %%s\\n\", trailfilename);",
+ " pan_exit(1);",
+ " } /* else */",
+ " goto success;",
+ " }",
+ "talk:",
+ " try_core = 1;",
+ " candidate_files = 0;",
+ " tprefix = \"trail\";",
+ " strcpy(MyFile, TrailFile);",
+ " do { /* see if there's more than one possible trailfile */",
+ " if (whichtrail)",
+ " { sprintf(fnm, \"%%s%%d.%%s\",",
+ " MyFile, whichtrail, tprefix);",
+ " fd = fopen(fnm, \"r\");",
+ " if (fd != NULL)",
+ " { candidate_files++;",
+ " if (verbose==100)",
+ " printf(\"trail%%d: %%s\\n\",",
+ " candidate_files, fnm);",
+ " fclose(fd);",
+ " }",
+ " if ((q = strchr(MyFile, \'.\')) != NULL)",
+ " { *q = \'\\0\';", /* e.g., strip .pml */
+ " sprintf(fnm, \"%%s%%d.%%s\",",
+ " MyFile, whichtrail, tprefix);",
+ " *q = \'.\';",
+ " fd = fopen(fnm, \"r\");",
+ " if (fd != NULL)",
+ " { candidate_files++;",
+ " if (verbose==100)",
+ " printf(\"trail%%d: %%s\\n\",",
+ " candidate_files, fnm);",
+ " fclose(fd);",
+ " } }",
+ " } else",
+ " { sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
+ " fd = fopen(fnm, \"r\");",
+ " if (fd != NULL)",
+ " { candidate_files++;",
+ " if (verbose==100)",
+ " printf(\"trail%%d: %%s\\n\",",
+ " candidate_files, fnm);",
+ " fclose(fd);",
+ " }",
+ " if ((q = strchr(MyFile, \'.\')) != NULL)",
+ " { *q = \'\\0\';", /* e.g., strip .pml */
+ " sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
+ " *q = \'.\';",
+ " fd = fopen(fnm, \"r\");",
+ " if (fd != NULL)",
+ " { candidate_files++;",
+ " if (verbose==100)",
+ " printf(\"trail%%d: %%s\\n\",",
+ " candidate_files, fnm);",
+ " fclose(fd);",
+ " } } }",
+ " tprefix = MySuffix;",
+ " sprintf(tprefix, \"cpu%%d_trail\", try_core++);",
+ " } while (try_core <= NCORE);",
"",
+ " if (candidate_files != 1)",
+ " { if (verbose != 100)",
+ " { printf(\"error: there are %%d trail files:\\n\",",
+ " candidate_files);",
+ " verbose = 100;",
+ " goto talk;",
+ " } else",
+ " { printf(\"pan: rm or mv all except one\\n\");",
+ " exit(1);",
+ " } }",
+
+ " try_core = 1;",
+ " strcpy(MyFile, TrailFile); /* restore */",
+ " tprefix = \"trail\";",
+ "try_again:",
" if (whichtrail)",
" { sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, tprefix);",
" fd = fopen(fnm, \"r\");",
" if (fd == NULL && (q = strchr(MyFile, \'.\')))",
" { *q = \'\\0\';", /* e.g., strip .pml on original file */
- " sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, tprefix);",
+ " sprintf(fnm, \"%%s%%d.%%s\",",
+ " MyFile, whichtrail, tprefix);",
" *q = \'.\';",
" fd = fopen(fnm, \"r\");",
- " if (fd == NULL)",
- " { printf(\"pan: cannot find %%s%%d.%%s or %%s\\n\", ",
- " MyFile, whichtrail, tprefix, fnm);",
- " pan_exit(1);",
- " } }",
+ " }",
" } else",
" { sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
" fd = fopen(fnm, \"r\");",
@@ -318,34 +635,99 @@
" sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
" *q = \'.\';",
" fd = fopen(fnm, \"r\");",
- " if (fd == NULL)",
- " { printf(\"pan: cannot find %%s.%%s or %%s\\n\", ",
- " MyFile, tprefix, fnm);",
- " pan_exit(1);",
- " } } }",
+ " } }",
" if (fd == NULL)",
- " { printf(\"pan: cannot find trailfile %%s\\n\", fnm);",
+ " { if (try_core < NCORE)",
+ " { tprefix = MySuffix;",
+ " sprintf(tprefix, \"cpu%%d_trail\", try_core++);",
+ " goto try_again;",
+ " }",
+ " printf(\"pan: cannot find trailfile %%s\\n\", fnm);",
" pan_exit(1);",
" }",
+ "success:",
+ "#if NCORE>1 && defined(SEP_STATE)",
+ " { void set_root(void); /* for partial traces from local root */",
+ " set_root();",
+ " }",
+ "#endif",
" return fd;",
"}",
"",
"uchar do_transit(Trans *, short);",
+ "#ifdef PERMUTED",
+ "void set_permuted(int);",
+ "void set_reversed(int);",
+ "void set_rotated(int);",
+ "void set_randrot(int);",
+ "void (*p_reorder)(int) = set_permuted;",
+ "short p_rotate;",
+ "#endif",
"",
"void",
"getrail(void)",
"{ FILE *fd;",
- " char *q;",
- " int i, t_id, lastnever=-1; short II;",
+ " char *q, *pnm;",
+ " int i, t_id, lastnever = -1; short II;",
" Trans *t;",
" P0 *z;",
- "",
+ "#ifdef PERMUTED",
+ " char sbuf[128];",
+ " memset(sbuf, 0, sizeof(sbuf));",
+ "#endif",
" fd = findtrail(); /* exits if unsuccessful */",
" while (fscanf(fd, \"%%ld:%%d:%%d\\n\", &depth, &i, &t_id) == 3)",
" { if (depth == -1)",
- " printf(\"<<<<<START OF CYCLE>>>>>\\n\");",
+ " { printf(\"<<<<<START OF CYCLE>>>>>\\n\");",
+ " }",
+ "#ifdef PERMUTED",
" if (depth < 0)",
- " continue;",
+ " { switch (depth) {",
+ " case -5:",
+ " if (i && !t_reverse)",
+ " { strcat(sbuf, \"-t_reverse \");",
+ " }",
+ " break;",
+ " case -6:",
+ " if (i && p_reorder != set_permuted)",
+ " { strcat(sbuf, \"-p_permute \");",
+ " } else",
+ " if (t_id && p_reorder != set_reversed)",
+ " { strcat(sbuf, \"-p_reverse \");",
+ " }",
+ " break;",
+ " case -7:",
+ " if (i",
+ " && (p_reorder != set_rotated || p_rotate != t_id))",
+ " { char tmp[32];",
+ " sprintf(tmp, \"-p_rotate%%d \", t_id);",
+ " strcat(sbuf, tmp);",
+ " }",
+ " break;",
+ " case -8:",
+ " if (i && p_reorder != set_randrot)",
+ " { strcat(sbuf, \"-p_randrot \");",
+ " }",
+ " if (s_rand != ++t_id)",
+ " { char tmp[32];",
+ " sprintf(tmp, \"-RS%%u \", (uint) t_id-1);",
+ " strcat(sbuf, tmp);",
+ " }",
+ " break;",
+ " default:",
+ " continue;",
+ " }",
+ " }",
+ "#endif",
+ " if (depth < 0)",
+ " { continue;",
+ " }",
+ "#ifdef PERMUTED",
+ " if (strlen(sbuf) > 0)",
+ " { fprintf(efd, \"add: %%s\\n\", sbuf);",
+ " exit(1);",
+ " }",
+ "#endif",
" if (i > now._nr_pr)",
" { printf(\"pan: Error, proc %%d invalid pid \", i);",
" printf(\"transition %%d\\n\", t_id);",
@@ -352,16 +734,15 @@
" break;",
" }",
" II = i;",
- "",
" z = (P0 *)pptr(II);",
" for (t = trans[z->_t][z->_p]; t; t = t->nxt)",
- " if (t->t_id == t_id)",
+ " if (t->t_id == (T_ID) t_id)",
" break;",
" if (!t)",
" { for (i = 0; i < NrStates[z->_t]; i++)",
" { t = trans[z->_t][i];",
- " if (t && t->t_id == t_id)",
- " { printf(\" Recovered at state %%d\\n\", i);",
+ " if (t && t->t_id == (T_ID) t_id)",
+ " { printf(\"\\tRecovered at state %%d\\n\", i);",
" z->_p = i;",
" goto recovered;",
" } }",
@@ -368,6 +749,8 @@
" printf(\"pan: Error, proc %%d type %%d state %%d: \",",
" II, z->_t, z->_p);",
" printf(\"transition %%d not found\\n\", t_id);",
+ " printf(\"pan: list of possible transitions in this process:\\n\");",
+ " if (z->_t >= 0 && z->_t <= _NP_)",
" for (t = trans[z->_t][z->_p]; t; t = t->nxt)",
" printf(\" t_id %%d -- case %%d, [%%s]\\n\",",
" t->t_id, t->forw, t->tp);",
@@ -377,11 +760,13 @@
" q = transmognify(t->tp);",
" if (gui) simvals[0] = \'\\0\';",
+ " pnm = procname[z->_t];",
" this = pptr(II);",
" trpt->tau |= 1;", /* timeout always possible */
" if (!do_transit(t, II))",
" { if (onlyproc >= 0 && II != onlyproc)",
" goto moveon;",
+ " if (!verbose) break;",
" printf(\"pan: error, next transition UNEXECUTABLE on replay\\n\");",
" printf(\" most likely causes: missing c_track statements\\n\");",
" printf(\" or illegal side-effects in c_expr statements\\n\");",
@@ -391,16 +776,24 @@
" goto moveon;",
" if (verbose)",
- " { printf(\"depth: %%3ld proc: %%3d trans: %%3d (%%d procs) \",",
- " depth, II, t_id, now._nr_pr);",
- " printf(\"forw=%%3d [%%s]\\n\", t->forw, q);",
- "",
+ " { printf(\"%%3ld: proc %%2d (%%s) \", depth, II, pnm);",
+
+ " for (i = 0; src_all[i].src; i++)",
+ " if (src_all[i].tp == (int) z->_t)",
+ " { printf(\" %%s:%%d \",",
+ " find_source((int) z->_t, (int) z->_p),",
+ " src_all[i].src[z->_p]);",
+ " break;",
+ " }",
+
+ " printf(\"(state %%d) trans {%%d,%%d} [%%s]\\n\",",
+ " z->_p, t_id, t->forw, q?q:\"\");",
+
" c_globals();",
" for (i = 0; i < now._nr_pr; i++)",
" { c_locals(i, ((P0 *)pptr(i))->_t);",
" }",
- " } else",
- " if (strcmp(procname[z->_t], \":never:\") == 0)",
+ " } else if (Btypes[z->_t] == N_CLAIM)",
" { if (lastnever != (int) z->_p)",
" { for (i = 0; src_all[i].src; i++)",
" if (src_all[i].tp == (int) z->_t)",
@@ -413,8 +806,7 @@
" }",
" lastnever = z->_p;",
" goto sameas;",
- " } else",
- " if (strcmp(procname[z->_t], \":np_:\") != 0)",
+ " } else if (Btypes[z->_t] != 0) /* not :np_: */",
" {",
"sameas: if (no_rck) goto moveon;",
" if (coltrace)",
@@ -421,15 +813,16 @@
" { printf(\"%%ld: \", depth);",
" for (i = 0; i < II; i++)",
" printf(\"\\t\\t\");",
- " printf(\"%%s(%%d):\", procname[z->_t], II);",
+ " printf(\"%%s(%%d):\", pnm, II);",
" printf(\"[%%s]\\n\", q?q:\"\");",
" } else if (!silent)",
" { if (strlen(simvals) > 0) {",
" printf(\"%%3ld: proc %%2d (%%s)\", ",
- " depth, II, procname[z->_t]);",
+ " depth, II, pnm);",
" for (i = 0; src_all[i].src; i++)",
" if (src_all[i].tp == (int) z->_t)",
- " { printf(\" line %%3d \\\"pan_in\\\" \",",
+ " { printf(\" %%s:%%d \",",
+ " find_source((int) z->_t, (int) z->_p),",
" src_all[i].src[z->_p]);",
" break;",
" }",
@@ -436,15 +829,16 @@
" printf(\"(state %%d)\t[values: %%s]\\n\", z->_p, simvals);",
" }",
" printf(\"%%3ld: proc %%2d (%%s)\", ",
- " depth, II, procname[z->_t]);",
+ " depth, II, pnm);",
" for (i = 0; src_all[i].src; i++)",
" if (src_all[i].tp == (int) z->_t)",
- " { printf(\" line %%3d \\\"pan_in\\\" \",",
+ " { printf(\" %%s:%%d \",",
+ " find_source((int) z->_t, (int) z->_p),",
" src_all[i].src[z->_p]);",
" break;",
" }",
" printf(\"(state %%d)\t[%%s]\\n\", z->_p, q?q:\"\");",
- " printf(\"\\n\");",
+ " /* printf(\"\\n\"); */",
" } }",
"moveon: z->_p = t->st;",
" }",
@@ -462,19 +856,22 @@
" }",
" return -1;",
"}",
- "#ifdef VERI",
- "void check_claim(int);",
+ "",
+ "#if NCORE>1 && !defined(GLOB_HEAP)",
+ " #define SEP_HEAP /* version 5.1.2 */",
"#endif",
"",
"#ifdef BITSTATE",
-#ifndef POWOW
"int",
"bstore_mod(char *v, int n) /* hasharray size not a power of two */",
- "{ unsigned long x, y;",
- " unsigned int i = 1;",
- "",
- " d_hash((uchar *) v, n); /* sets j3, j4, K1, K2 */",
- " x = K2; y = j3;",
+ "{ ulong x, y;",
+ " uint i = 1;",
+ "#if defined(MURMUR) && (WS==8)",
+ " m_hash((uchar *) v, n); /* bstore_mod - sets j3_spin, j4_spin, K1, K2 */",
+ "#else",
+ " d_hash((uchar *) v, n); /* bstore_mod - sets j3_spin, j4_spin, K1, K2 */",
+ "#endif",
+ " x = K1; y = j3_spin;", /* was K2 before 5.1.1 */
" for (;;)",
" { if (!(SS[x%%udmem]&(1<<y))) break;", /* take the hit in speed */
" if (i == hfns) {",
@@ -483,8 +880,8 @@
"#endif",
" return 1;",
" }",
- " x = (x + K1 + i);", /* no mask, using mod */
- " y = (y + j4) & 7;",
+ " x = (x + K2 + i);", /* no mask, using mod - was K1 before 5.1.1 */
+ " y = (y + j4_spin) & 7;",
" i++;",
" }",
"#ifdef RANDSTOR",
@@ -493,8 +890,8 @@
" for (;;)",
" { SS[x%%udmem] |= (1<<y);",
" if (i == hfns) break;", /* done */
- " x = (x + K1 + i);", /* no mask */
- " y = (y + j4) & 7;",
+ " x = (x + K2 + i);", /* no mask - was K1 before 5.1.1 */
+ " y = (y + j4_spin) & 7;",
" i++;",
" }",
"#ifdef DEBUG",
@@ -505,14 +902,16 @@
" }",
" return 0;",
"}",
-#endif
"int",
"bstore_reg(char *v, int n) /* extended hashing, Peter Dillinger, 2004 */",
- "{ unsigned long x, y;",
- " unsigned int i = 1;",
- "",
- " d_hash((uchar *) v, n); /* sets j1-j4 */",
- " x = j2; y = j3;",
+ "{ ulong x, y;",
+ " uint i = 1;",
+ "#if defined(MURMUR) && (WS==8)",
+ " m_hash((uchar *) v, n); /* bstore_reg - sets j1_spin-j4_spin */",
+ "#else",
+ " d_hash((uchar *) v, n); /* bstore_reg - sets j1_spin-j4_spin */",
+ "#endif",
+ " x = j2_spin; y = j3_spin;",
" for (;;)",
" { if (!(SS[x]&(1<<y))) break;", /* at least one bit not set */
" if (i == hfns) {",
@@ -521,8 +920,8 @@
"#endif",
" return 1;",
" }",
- " x = (x + j1 + i) & nmask;",
- " y = (y + j4) & 7;",
+ " x = (x + j1_spin + i) & nmask;",
+ " y = (y + j4_spin) & 7;",
" i++;",
" }",
"#ifdef RANDSTOR",
@@ -531,8 +930,8 @@
" for (;;)",
" { SS[x] |= (1<<y);",
" if (i == hfns) break;", /* done */
- " x = (x + j1 + i) & nmask;",
- " y = (y + j4) & 7;",
+ " x = (x + j1_spin + i) & nmask;",
+ " y = (y + j4_spin) & 7;",
" i++;",
" }",
"#ifdef DEBUG",
@@ -543,8 +942,8 @@
" }",
" return 0;",
"}",
- "#endif",
- "unsigned long TMODE = 0666; /* file permission bits for trail files */",
+ "#endif", /* BITSTATE */
+ "ulong TMODE = 0666; /* file permission bits for trail files */",
"",
"int trcnt=1;",
"char snap[64], fnm[512];",
@@ -554,18 +953,34 @@
"{ int fd;",
" char *q;",
" char MyFile[512];",
+ " int w_flags = O_CREAT|O_WRONLY|O_TRUNC;",
"",
+ " if (exclusive == 1 && iterative == 0)",
+ " { w_flags |= O_EXCL;",
+ " }",
+ "",
" q = strrchr(TrailFile, \'/\');",
" if (q == NULL) q = TrailFile; else q++;",
" strcpy(MyFile, q); /* TrailFile is not a writable string */",
"",
" if (iterative == 0 && Nr_Trails++ > 0)",
+ " {",
+ "#ifdef PUTPID",
+ " sprintf(fnm, \"%%s_%%s_%%d_%%d.%%s\",",
+ " MyFile, progname, getpid(), Nr_Trails-1, tprefix);",
+ "#else",
" sprintf(fnm, \"%%s%%d.%%s\",",
" MyFile, Nr_Trails-1, tprefix);",
- " else",
+ "#endif",
+ " } else",
+ " {",
+ "#ifdef PUTPID",
+ " sprintf(fnm, \"%%s_%%s_%%d.%%s\", MyFile, progname, getpid(), tprefix);",
+ "#else",
" sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
- "",
- " if ((fd = creat(fnm, TMODE)) < 0)",
+ "#endif",
+ " }",
+ " if ((fd = open(fnm, w_flags, TMODE)) < 0)",
" { if ((q = strchr(MyFile, \'.\')))",
" { *q = \'\\0\';", /* strip .pml */
" if (iterative == 0 && Nr_Trails-1 > 0)",
@@ -574,91 +989,146 @@
" else",
" sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
" *q = \'.\';",
- " fd = creat(fnm, TMODE);",
+ " fd = open(fnm, w_flags, TMODE);",
" } }",
" if (fd < 0)",
" { printf(\"pan: cannot create %%s\\n\", fnm);",
" perror(\"cause\");",
" } else",
- " { printf(\"pan: wrote %%s\\n\", fnm);",
+ " {",
+ "#if NCORE>1 && (defined(SEP_STATE) || !defined(FULL_TRAIL))",
+ " void write_root(void); ",
+ " write_root();",
+ "#else",
+ " printf(\"pan: wrote %%s\\n\", fnm);",
+ "#endif",
" }",
" return fd;",
"}",
- 0
-};
-
-static char *Code2b[] = { /* breadth-first search option */
- "#ifdef BFS",
- "#define Q_PROVISO",
- "#ifndef INLINE_REV",
- "#define INLINE_REV",
- "#endif",
"",
- "typedef struct SV_Hold {",
- " State *sv;",
- " int sz;",
- " struct SV_Hold *nxt;",
- "} SV_Hold;",
- "",
- "typedef struct EV_Hold {",
- " char *sv;", /* Mask */
- " int sz;", /* vsize */
- " int nrpr;",
- " int nrqs;",
- "#if VECTORSZ>32000",
- " int *po;",
- "#else",
- " short *po;",
+ "#ifndef FREQ",
+ "#define FREQ (1000000)",
"#endif",
- " int *qo;",
- " uchar *ps, *qs;",
- " struct EV_Hold *nxt;",
- "} EV_Hold;",
+ "double freq = (double) FREQ;\n",
+
+ "#ifdef TRIX",
+ "void sv_populate(void);",
"",
- "typedef struct BFS_Trail {",
- " Trail *frame;",
- " SV_Hold *onow;",
- " EV_Hold *omask;",
- "#ifdef Q_PROVISO",
- " struct H_el *lstate;",
+ "void",
+ "re_populate(void) /* restore procs and chans from now._ids_ */",
+ "{ int i, cnt = 0;",
+ " char *b;",
+ "#ifdef V_TRIX",
+ " printf(\"%%4d: re_populate\\n\", depth);",
"#endif",
- " short boq;",
- " struct BFS_Trail *nxt;",
- "} BFS_Trail;",
+ " for (i = 0; i < now._nr_pr; i++, cnt++)",
+ " { b = now._ids_[cnt];",
+ " processes[i]->psize = what_p_size( ((P0 *)b)->_t );",
+ " memcpy(processes[i]->body, b, processes[i]->psize);",
+ "#ifdef TRIX_RIX",
+ " ((P0 *)pptr(i))->_pid = i;",
+ " if (BASE > 0 && h > 0)",
+ " { ((P0 *)pptr(i))->_pid -= BASE;",
+ " }",
+ "#endif",
+ "#ifndef BFS",
+ " processes[i]->modified = 1; /* re-populate */",
+ "#endif",
+ " }",
+ " for (i = 0; i < now._nr_qs; i++, cnt++)",
+ " { b = now._ids_[cnt];",
+ " channels[i]->psize = what_q_size( ((Q0 *)b)->_t );",
+ " memcpy(channels[i]->body, b, channels[i]->psize);",
+ "#ifndef BFS",
+ " channels[i]->modified = 1; /* re-populate */",
+ "#endif",
+ " }",
+ "}",
+ "#endif\n",
+
+ "#ifdef BFS", /* breadth-first search */
+ " #ifndef BFS_PAR",
+ " BFS_State *bfs_trail, *bfs_bot, *bfs_free;",
+ " SV_Hold *svfree;",
+ " #else",
+ " static ulong bfs_pre_allocated;",
+ " #endif",
+ " #ifdef BFS_DISK",
+ " #ifndef BFS_LIMIT",
+ " #define BFS_LIMIT 100000",
+ " #endif",
+ " #ifndef BFS_DSK_LIMIT",
+ " #define BFS_DSK_LIMIT 1000000",
+ " #endif",
+ " #if defined(WIN32) || defined(WIN64)",
+ " #define RFLAGS (O_RDONLY|O_BINARY)",
+ " #define WFLAGS (O_CREAT|O_WRONLY|O_TRUNC|O_BINARY)",
+ " #define RWFLAGS (O_RDWR|O_BINARY)",
+ " #else",
+ " #define RFLAGS (O_RDONLY)",
+ " #define WFLAGS (O_CREAT|O_WRONLY|O_TRUNC)",
+ " #define RWFLAGS (O_RDWR)",
+ " #endif",
"",
- "BFS_Trail *bfs_trail, *bfs_bot, *bfs_free;",
+ " long bfs_size_limit;",
+ " int bfs_dsk_write = -1;",
+ " int bfs_dsk_read = -1;",
+ " long bfs_dsk_writes, bfs_dsk_reads;",
+ " int bfs_dsk_seqno_w, bfs_dsk_seqno_r;",
+ " #endif",
"",
- "SV_Hold *svhold, *svfree;",
- "",
"uchar do_reverse(Trans *, short, uchar);",
"void snapshot(void);",
+ "#if 0",
+ "void",
+ "select_claim(int x) /* ignored in BFS mode */",
+ "{ if (verbose)",
+ " { printf(\"select %%d (ignored)\\n\", x);",
+ " }",
+ "}",
+ "#endif",
+ "Trail *ntrpt;",
"",
+ "#ifndef BFS_PAR",
"SV_Hold *",
"getsv(int n)",
- "{ SV_Hold *h = (SV_Hold *) 0, *oh;",
+ "{ SV_Hold *h;",
"",
- " oh = (SV_Hold *) 0;",
- " for (h = svfree; h; oh = h, h = h->nxt)",
- " { if (n == h->sz)",
- " { if (!oh)",
- " svfree = h->nxt;",
- " else",
- " oh->nxt = h->nxt;",
- " h->nxt = (SV_Hold *) 0;",
- " break;",
- " }",
- " if (n < h->sz)",
- " { h = (SV_Hold *) 0;",
- " break;",
- " }",
- " /* else continue */",
- " }",
- "",
- " if (!h)",
+ " if (svfree && n <= svfree->sz)",
+ " { h = svfree;",
+ " svfree = h->nxt;",
+ " h->nxt = (SV_Hold *) 0;",
+ " } else",
" { h = (SV_Hold *) emalloc(sizeof(SV_Hold));",
" h->sz = n;",
+ " #ifdef BFS_DISK",
+ " if (bfs_size_limit >= BFS_LIMIT)",
+ " { h->sv = (State *) 0; /* means: read disk */",
+ " bfs_dsk_writes++; /* count */",
+ " if (bfs_dsk_write < 0 /* file descriptor */",
+ " || bfs_dsk_writes%%BFS_DSK_LIMIT == 0)",
+ " { char dsk_nm[32];",
+ " if (bfs_dsk_write >= 0)",
+ " { (void) close(bfs_dsk_write);",
+ " }",
+ " sprintf(dsk_nm, \"pan_bfs_%%d.tmp\", bfs_dsk_seqno_w++);",
+ " bfs_dsk_write = open(dsk_nm, WFLAGS, 0644);",
+ " if (bfs_dsk_write < 0)",
+ " { Uerror(\"could not create tmp disk file\");",
+ " }",
+ " printf(\"pan: created disk file %%s\\n\", dsk_nm);",
+ " }",
+ " if (write(bfs_dsk_write, (char *) &now, n) != n)",
+ " { Uerror(\"aborting -- disk write failed (disk full?)\");",
+ " }",
+ " return h; /* no memcpy */",
+ " }", /* else */
+ " bfs_size_limit++;",
+ " #endif",
" h->sv = (State *) emalloc(sizeof(State) - VECTORSZ + n);",
" }",
+ "",
+ " memcpy((char *)h->sv, (char *)&now, n);",
" return h;",
"}",
"",
@@ -669,18 +1139,24 @@
"",
" for (h = kept; h; h = h->nxt)",
" if (n == h->sz",
+ "#if !defined(NOCOMP) && !defined(HC)",
" && (memcmp((char *) Mask, (char *) h->sv, n) == 0)",
+ "#endif",
" && (now._nr_pr == h->nrpr)",
" && (now._nr_qs == h->nrqs)",
- "#if VECTORSZ>32000",
+ " #ifdef TRIX",
+ " )",
+ " #else",
+ " #if VECTORSZ>32000",
" && (memcmp((char *) proc_offset, (char *) h->po, now._nr_pr * sizeof(int)) == 0)",
" && (memcmp((char *) q_offset, (char *) h->qo, now._nr_qs * sizeof(int)) == 0)",
- "#else",
+ " #else",
" && (memcmp((char *) proc_offset, (char *) h->po, now._nr_pr * sizeof(short)) == 0)",
" && (memcmp((char *) q_offset, (char *) h->qo, now._nr_qs * sizeof(short)) == 0)",
- "#endif",
- " && (memcmp((char *) proc_skip, (char *) h->ps, now._nr_pr * sizeof(uchar)) == 0)",
- " && (memcmp((char *) q_skip, (char *) h->qs, now._nr_qs * sizeof(uchar)) == 0))",
+ " #endif",
+ " && (memcmp((char *) proc_skip, (char *) h->ps, now._nr_pr * sizeof(uchar)) == 0)",
+ " && (memcmp((char *) q_skip, (char *) h->qs, now._nr_qs * sizeof(uchar)) == 0))",
+ " #endif",
" break;",
" if (!h)",
" { h = (EV_Hold *) emalloc(sizeof(EV_Hold));",
@@ -689,29 +1165,33 @@
" h->nrqs = now._nr_qs;",
"",
" h->sv = (char *) emalloc(n * sizeof(char));",
+ "#if !defined(NOCOMP) && !defined(HC)",
" memcpy((char *) h->sv, (char *) Mask, n);",
- "",
+ "#endif",
+ " #ifndef TRIX",
" if (now._nr_pr > 0)",
- " { h->po = (int *) emalloc(now._nr_pr * sizeof(int));",
- " h->ps = (int *) emalloc(now._nr_pr * sizeof(int));",
- "#if VECTORSZ>32000",
+ " { h->ps = (char *) emalloc(now._nr_pr * sizeof(int));",
+ " memcpy((char *) h->ps, (char *) proc_skip, now._nr_pr * sizeof(uchar));",
+ " #if VECTORSZ>32000",
+ " h->po = (char *) emalloc(now._nr_pr * sizeof(int));",
" memcpy((char *) h->po, (char *) proc_offset, now._nr_pr * sizeof(int));",
- "#else",
+ " #else",
+ " h->po = (char *) emalloc(now._nr_pr * sizeof(short));",
" memcpy((char *) h->po, (char *) proc_offset, now._nr_pr * sizeof(short));",
- "#endif",
- " memcpy((char *) h->ps, (char *) proc_skip, now._nr_pr * sizeof(uchar));",
+ " #endif",
" }",
" if (now._nr_qs > 0)",
- " { h->qo = (int *) emalloc(now._nr_qs * sizeof(int));",
- " h->qs = (int *) emalloc(now._nr_qs * sizeof(int));",
- "#if VECTORSZ>32000",
+ " { h->qs = (char *) emalloc(now._nr_qs * sizeof(int));",
+ " memcpy((char *) h->qs, (char *) q_skip, now._nr_qs * sizeof(uchar));",
+ " #if VECTORSZ>32000",
+ " h->qo = (char *) emalloc(now._nr_qs * sizeof(int));",
" memcpy((char *) h->qo, (char *) q_offset, now._nr_qs * sizeof(int));",
- "#else",
+ " #else",
+ " h->qo = (char *) emalloc(now._nr_qs * sizeof(short));",
" memcpy((char *) h->qo, (char *) q_offset, now._nr_qs * sizeof(short));",
- "#endif",
- " memcpy((char *) h->qs, (char *) q_skip, now._nr_qs * sizeof(uchar));",
+ " #endif",
" }",
- "",
+ " #endif",
" h->nxt = kept;",
" kept = h;",
" }",
@@ -724,9 +1204,9 @@
"",
" oh = (SV_Hold *) 0;",
" for (h = svfree; h; oh = h, h = h->nxt)",
- " if (h->sz >= p->sz)",
+ " { if (p->sz >= h->sz)",
" break;",
- "",
+ " }",
" if (!oh)",
" { p->nxt = svfree;",
" svfree = p;",
@@ -736,24 +1216,26 @@
" }",
"}",
"",
- "BFS_Trail *",
+ "BFS_State *",
"get_bfs_frame(void)",
- "{ BFS_Trail *t;",
+ "{ BFS_State *t;",
"",
" if (bfs_free)",
" { t = bfs_free;",
" bfs_free = bfs_free->nxt;",
- " t->nxt = (BFS_Trail *) 0;",
+ " t->nxt = (BFS_State *) 0;",
" } else",
- " { t = (BFS_Trail *) emalloc(sizeof(BFS_Trail));",
+ " { t = (BFS_State *) emalloc(sizeof(BFS_State));",
" }",
" t->frame = (Trail *) emalloc(sizeof(Trail));", /* always new */
+ " /* new because we keep a ptr to the frame of parent states */",
+ " /* used for reconstructing path and recovering failed rvs etc */",
" return t;",
"}",
"",
"void",
"push_bfs(Trail *f, int d)",
- "{ BFS_Trail *t;",
+ "{ BFS_State *t;",
"",
" t = get_bfs_frame();",
" memcpy((char *)t->frame, (char *)f, sizeof(Trail));",
@@ -760,12 +1242,14 @@
" t->frame->o_tt = d; /* depth */",
"",
" t->boq = boq;",
+ " #ifdef TRIX",
+ " sv_populate();",
+ " #endif",
" t->onow = getsv(vsize);",
- " memcpy((char *)t->onow->sv, (char *)&now, vsize);",
" t->omask = getsv_mask(vsize);",
- "#if defined(FULLSTACK) && defined(Q_PROVISO)",
- " t->lstate = Lstate;",
- "#endif",
+ " #if defined(FULLSTACK) && defined(Q_PROVISO)",
+ " t->lstate = Lstate; /* bfs */",
+ " #endif",
" if (!bfs_bot)",
" { bfs_bot = bfs_trail = t;",
" } else",
@@ -772,56 +1256,107 @@
" { bfs_bot->nxt = t;",
" bfs_bot = t;",
" }",
- "#ifdef CHECK",
- " printf(\"PUSH %%u (%%d)\\n\", t->frame, d);",
- "#endif",
+ " #ifdef VERBOSE",
+ " t->nr = nstates;",
+ " #endif",
+ " #ifdef CHECK",
+ " #ifdef VERBOSE",
+ " printf(\"PUSH %%lu (depth %%d, nr %%lu)\\n\", (ulong) t->frame, d, t->nr);",
+ " #else",
+ " printf(\"PUSH %%lu (depth %%d)\\n\", (ulong) t->frame, d);",
+ " #endif",
+ " #endif",
"}",
"",
"Trail *",
"pop_bfs(void)",
- "{ BFS_Trail *t;",
+ "{ BFS_State *t;",
"",
" if (!bfs_trail)",
- " return (Trail *) 0;",
- "",
+ " { return (Trail *) 0;",
+ " }",
" t = bfs_trail;",
" bfs_trail = t->nxt;",
" if (!bfs_trail)",
- " bfs_bot = (BFS_Trail *) 0;",
- "#if defined(Q_PROVISO) && !defined(BITSTATE) && !defined(NOREDUCE)",
- " if (t->lstate) t->lstate->tagged = 0;",
- "#endif",
- "",
+ " { bfs_bot = (BFS_State *) 0;",
+ " }",
+ " #if defined(Q_PROVISO) && !defined(BITSTATE) && !defined(NOREDUCE)",
+ " if (t->lstate) /* bfs */",
+ " { t->lstate->tagged = 0; /* bfs */",
+ " }",
+ " #endif",
" t->nxt = bfs_free;",
" bfs_free = t;",
"",
" vsize = t->onow->sz;",
" boq = t->boq;",
- "",
- " memcpy((uchar *) &now, (uchar *) t->onow->sv, vsize);",
+ " #ifdef BFS_DISK",
+ " if (t->onow->sv == (State *) 0)",
+ " { char dsk_nm[32];",
+ " bfs_dsk_reads++; /* count */",
+ " if (bfs_dsk_read >= 0 /* file descriptor */",
+ " && bfs_dsk_reads%%BFS_DSK_LIMIT == 0)",
+ " { (void) close(bfs_dsk_read);",
+ " sprintf(dsk_nm, \"pan_bfs_%%d.tmp\", bfs_dsk_seqno_r-1);",
+ " (void) unlink(dsk_nm);",
+ " bfs_dsk_read = -1;",
+ " }",
+ " if (bfs_dsk_read < 0)",
+ " { sprintf(dsk_nm, \"pan_bfs_%%d.tmp\", bfs_dsk_seqno_r++);",
+ " bfs_dsk_read = open(dsk_nm, RFLAGS);",
+ " if (bfs_dsk_read < 0)",
+ " { Uerror(\"could not open temp disk file\");",
+ " } }",
+ " if (read(bfs_dsk_read, (char *) &now, vsize) != vsize)",
+ " { Uerror(\"bad bfs disk file read\");",
+ " }",
+ " #ifndef NOVSZ",
+ " if (now._vsz != vsize)",
+ " { Uerror(\"disk read vsz mismatch\");",
+ " }",
+ " #endif",
+ " } else",
+ " #endif",
+ " { memcpy((uchar *) &now, (uchar *) t->onow->sv, vsize);",
+ " #ifndef NOVSZ",
+ " vsize = now._vsz;",
+ " #endif",
+ " }",
+ "#if !defined(NOCOMP) && !defined(HC)",
" memcpy((uchar *) Mask, (uchar *) t->omask->sv, vsize);",
-
+ "#endif",
+ " #ifdef TRIX",
+ " re_populate();",
+ " #else",
" if (now._nr_pr > 0)",
- "#if VECTORSZ>32000",
+ " #if VECTORSZ>32000",
" { memcpy((char *)proc_offset, (char *)t->omask->po, now._nr_pr * sizeof(int));",
- "#else",
+ " #else",
" { memcpy((char *)proc_offset, (char *)t->omask->po, now._nr_pr * sizeof(short));",
- "#endif",
+ " #endif",
" memcpy((char *)proc_skip, (char *)t->omask->ps, now._nr_pr * sizeof(uchar));",
" }",
" if (now._nr_qs > 0)",
- "#if VECTORSZ>32000",
+ " #if VECTORSZ>32000",
" { memcpy((uchar *)q_offset, (uchar *)t->omask->qo, now._nr_qs * sizeof(int));",
- "#else",
+ " #else",
" { memcpy((uchar *)q_offset, (uchar *)t->omask->qo, now._nr_qs * sizeof(short));",
- "#endif",
+ " #endif",
" memcpy((uchar *)q_skip, (uchar *)t->omask->qs, now._nr_qs * sizeof(uchar));",
" }",
-
- " freesv(t->onow); /* omask not freed */",
- "#ifdef CHECK",
- " printf(\"POP %%u (%%d)\\n\", t->frame, t->frame->o_tt);",
- "#endif",
+ " #endif",
+ " #ifdef BFS_DISK",
+ " if (t->onow->sv != (State *) 0)",
+ " #endif",
+ " { freesv(t->onow); /* omask not freed */",
+ " }",
+ " #ifdef CHECK",
+ " #ifdef VERBOSE",
+ " printf(\"POP %%lu (depth %%d, nr %%lu)\\n\", (ulong) t->frame, t->frame->o_tt, t->nr);",
+ " #else",
+ " printf(\"POP %%lu (depth %%d)\\n\", (ulong) t->frame, t->frame->o_tt);",
+ " #endif",
+ " #endif",
" return t->frame;",
"}",
"",
@@ -828,7 +1363,7 @@
"void",
"store_state(Trail *ntrpt, int shortcut, short oboq)",
"{",
- "#ifdef VERI",
+ " #ifdef VERI",
" Trans *t2 = (Trans *) 0;",
" uchar ot; int tt, E_state;",
" uchar o_opm = trpt->o_pm, *othis = this;",
@@ -835,72 +1370,85 @@
"",
" if (shortcut)",
" {",
- "#ifdef VERBOSE",
+ " #ifdef VERBOSE",
" printf(\"claim: shortcut\\n\");",
- "#endif",
+ " #endif",
" goto store_it; /* no claim move */",
" }",
"",
- " this = (((uchar *)&now)+proc_offset[0]); /* 0 = never claim */",
+ " this = pptr(0); /* 0 = never claim */",
" trpt->o_pm = 0;", /* to interpret else in never claim */
"",
" tt = (int) ((P0 *)this)->_p;",
" ot = (uchar) ((P0 *)this)->_t;",
"",
- "#ifdef HAS_UNLESS",
+ " #ifdef HAS_UNLESS",
" E_state = 0;",
- "#endif",
+ " #endif",
" for (t2 = trans[ot][tt]; t2; t2 = t2?t2->nxt:(Trans *)0)",
" {",
- "#ifdef HAS_UNLESS",
- " if (E_state > 0",
- " && E_state != t2->e_trans)",
- " break;",
- "#endif",
+ " #ifdef HAS_UNLESS",
+ " if (E_state > 0 && E_state != t2->e_trans)",
+ " { break;",
+ " }",
+ " #endif",
" if (do_transit(t2, 0))",
" {",
- "#ifdef VERBOSE",
+ " #ifdef VERBOSE",
" if (!reached[ot][t2->st])",
" printf(\"depth: %%d -- claim move from %%d -> %%d\\n\",",
" trpt->o_tt, ((P0 *)this)->_p, t2->st);",
- "#endif",
- "#ifdef HAS_UNLESS",
+ " #endif",
+ " #ifdef HAS_UNLESS",
" E_state = t2->e_trans;",
- "#endif",
+ " #endif",
" if (t2->st > 0)",
" { ((P0 *)this)->_p = t2->st;",
" reached[ot][t2->st] = 1;",
- "#ifndef NOCLAIM",
- " check_claim(t2->st);",
- "#endif",
+ " #ifndef NOCLAIM",
+ " if (stopstate[ot][t2->st])",
+ " { uerror(\"end state in claim reached\");",
+ " }",
+ " #endif",
" }",
" if (now._nr_pr == 0) /* claim terminated */",
" uerror(\"end state in claim reached\");",
"",
- "#ifdef PEG",
+ " #ifdef PEG",
" peg[t2->forw]++;",
- "#endif",
+ " #endif",
" trpt->o_pm |= 1;",
- " if (t2->atom&2)", /* atomic in claim */
- " Uerror(\"atomic in claim not supported in BFS mode\");",
+ " if (t2->atom&2)",
+ " { Uerror(\"atomic in claim not supported in BFS\");",
+ " }",
"store_it:",
"",
- "#endif", /* VERI */
+ " #endif", /* VERI */
"",
- "#ifdef BITSTATE",
- " if (!bstore((char *)&now, vsize))",
- "#else",
- "#ifdef MA",
- " if (!gstore((char *)&now, vsize, 0))",
- "#else",
- " if (!hstore((char *)&now, vsize))",
- "#endif",
- "#endif",
- " { nstates++;",
- "#ifndef NOREDUCE",
- " trpt->tau |= 64;", /* succ definitely outside stack */
- "#endif",
- "#if SYNC",
+ " #if defined(BITSTATE)",
+ " if (!b_store((char *)&now, vsize))",
+ " #elif defined(MA)",
+ " if (!g_store((char *)&now, vsize, 0))",
+ " #else",
+ " if (!h_store((char *)&now, vsize))",
+ " #endif",
+ " { static long sdone = (long) 0; long ndone;",
+ " nstates++;",
+ " #ifndef NOREDUCE",
+ " trpt->tau |= 64;", /* bfs: succ definitely outside stack */
+ " #endif",
+ " ndone = (ulong) (nstates/(freq));",
+ " if (ndone != sdone && mreached%%10 != 0)",
+ " { snapshot();",
+ " sdone = ndone;",
+ " #if defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(MA)",
+ " if (nstates > ((double)(1<<(ssize+1))))",
+ " { void resize_hashtable(void);",
+ " resize_hashtable();",
+ " }",
+ " #endif",
+ " }",
+ " #if SYNC",
" if (boq != -1)",
" midrv++;",
" else if (oboq != -1)",
@@ -908,26 +1456,29 @@
" x = (Trail *) trpt->ostate; /* pre-rv state */",
" if (x) x->o_pm |= 4; /* mark success */",
" }",
- "#endif",
+ " #endif",
" push_bfs(ntrpt, trpt->o_tt+1);",
" } else",
" { truncs++;",
- "#if !defined(NOREDUCE) && defined(FULLSTACK) && defined(Q_PROVISO)",
- "#if !defined(QLIST) && !defined(BITSTATE)",
- " if (Lstate && Lstate->tagged) trpt->tau |= 64;",
- "#else",
+ " #if defined(Q_PROVISO) && !defined(NOREDUCE) && defined(FULLSTACK)",
+ " #if !defined(BITSTATE)",
+ " if (Lstate && Lstate->tagged)",
+ " { trpt->tau |= 64;",
+ " }",
+ " #else",
" if (trpt->tau&32)",
- " { BFS_Trail *tprov;",
+ " { BFS_State *tprov;",
" for (tprov = bfs_trail; tprov; tprov = tprov->nxt)",
- " if (!memcmp((uchar *)&now, (uchar *)tprov->onow->sv, vsize))",
+ " if (tprov->onow->sv != (State *) 0",
+ " && memcmp((uchar *)&now, (uchar *)tprov->onow->sv, vsize) == 0)",
" { trpt->tau |= 64;",
" break; /* state is in queue */",
" } }",
- "#endif",
- "#endif",
+ " #endif",
+ " #endif",
" }",
- "#ifdef VERI",
+ " #ifdef VERI",
" ((P0 *)this)->_p = tt; /* reset claim */",
" if (t2)",
" do_reverse(t2, 0, 0);",
@@ -936,11 +1487,9 @@
" } }",
" this = othis;",
" trpt->o_pm = o_opm;",
- "#endif",
+ " #endif",
"}",
"",
- "Trail *ntrpt;", /* 4.2.8 */
- "",
"void",
"bfs(void)",
"{ Trans *t; Trail *otrpt, *x;",
@@ -950,7 +1499,7 @@
" short oboq = boq;",
"",
" ntrpt = (Trail *) emalloc(sizeof(Trail));",
- " trpt->ostate = (struct H_el *) 0;",
+ " trpt->ostate = (H_el *) 0;",
" trpt->tau = 0;",
"",
" trpt->o_tt = -1;",
@@ -958,65 +1507,59 @@
"",
" while ((otrpt = pop_bfs())) /* also restores now */",
" { memcpy((char *) trpt, (char *) otrpt, sizeof(Trail));",
- "#if defined(C_States) && (HAS_TRACK==1)",
+ " #if defined(C_States) && (HAS_TRACK==1)",
" c_revert((uchar *) &(now.c_state[0]));",
- "#endif",
+ " #endif",
" if (trpt->o_pm & 4)",
" {",
- "#ifdef VERBOSE",
+ " #ifdef VERBOSE",
" printf(\"Revisit of atomic not needed (%%d)\\n\",",
" trpt->o_pm);", /* at least 1 rv succeeded */
- "#endif",
+ " #endif",
" continue;",
" }",
- "#ifndef NOREDUCE",
+ " #ifndef NOREDUCE",
" nps = 0;",
- "#endif",
+ " #endif",
" if (trpt->o_pm == 8)",
" { revrv++;",
" if (trpt->tau&8)",
" {",
- "#ifdef VERBOSE",
+ " #ifdef VERBOSE",
" printf(\"Break atomic (pm:%%d,tau:%%d)\\n\",",
" trpt->o_pm, trpt->tau);",
- "#endif",
+ " #endif",
" trpt->tau &= ~8;",
" }",
- "#ifndef NOREDUCE",
+ " #ifndef NOREDUCE",
" else if (trpt->tau&32)", /* was a preselected move */
" {",
- "#ifdef VERBOSE",
+ " #ifdef VERBOSE",
" printf(\"Void preselection (pm:%%d,tau:%%d)\\n\",",
" trpt->o_pm, trpt->tau);",
- "#endif",
+ " #endif",
" trpt->tau &= ~32;",
" nps = 1; /* no preselection in repeat */",
" }",
- "#endif",
+ " #endif",
" }",
" trpt->o_pm &= ~(4|8);",
" if (trpt->o_tt > mreached)",
" { mreached = trpt->o_tt;",
" if (mreached%%10 == 0)",
- " { printf(\"Depth= %%7d States= %%7g \", mreached, nstates);",
- " printf(\"Transitions= %%7g \", nstates+truncs);",
- "#ifdef MA",
- " printf(\"Nodes= %%7d \", nr_states);",
- "#endif",
- " printf(\"Memory= %%-6.3f\\n\", memcnt/1000000.);",
- " fflush(stdout);",
+ " { snapshot();",
" } }",
" depth = trpt->o_tt;",
" if (depth >= maxdepth)",
" {",
- "#if SYNC",
+ " #if SYNC",
" Trail *x;",
" if (boq != -1)",
" { x = (Trail *) trpt->ostate;",
" if (x) x->o_pm |= 4; /* not failing */",
" }",
- "#endif",
+ " #endif",
" truncs++;",
" if (!warned)",
" { warned = 1;",
@@ -1023,16 +1566,15 @@
" printf(\"error: max search depth too small\\n\");",
" }",
" if (bounded)",
- " uerror(\"depth limit reached\");",
+ " { uerror(\"depth limit reached\");",
+ " }",
" continue;",
" }",
-
-/* PO */
- "#ifndef NOREDUCE",
+ " #ifndef NOREDUCE",
" if (boq == -1 && !(trpt->tau&8) && nps == 0)",
" for (II = now._nr_pr-1; II >= BASE; II -= 1)",
" {",
- "Pickup: this = pptr(II);",
+ "Pickup: this = pptr(II);",
" tt = (int) ((P0 *)this)->_p;",
" ot = (uchar) ((P0 *)this)->_t;",
" if (trans[ot][tt]->atom & 8)", /* safe */
@@ -1045,15 +1587,14 @@
" }",
" From = To = II;",
" trpt->tau |= 32; /* preselect marker */",
- "#ifdef DEBUG",
- " printf(\"%%3d: proc %%d PreSelected (tau=%%d)\\n\", ",
+ " #ifdef DEBUG",
+ " printf(\"%%3ld: proc %%d PreSelected (tau=%%d)\\n\", ",
" depth, II, trpt->tau);",
- "#endif",
+ " #endif",
" goto MainLoop;",
" } }",
" trpt->tau &= ~32;", /* not preselected */
- "#endif",
-/* PO */
+ " #endif", /* if !NOREDUCE */
"Repeat:",
" if (trpt->tau&8) /* atomic */",
" { From = To = (short ) trpt->pr;",
@@ -1066,32 +1607,44 @@
" _n = _m = 0;",
" for (II = From; II >= To; II -= 1)",
" {",
- " this = (((uchar *)&now)+proc_offset[II]);",
+ " this = pptr(II);",
" tt = (int) ((P0 *)this)->_p;",
" ot = (uchar) ((P0 *)this)->_t;",
- "#if SYNC",
+ " #if SYNC",
" /* no rendezvous with same proc */",
- " if (boq != -1 && trpt->pr == II) continue;",
- "#endif",
+ " if (boq != -1 && trpt->pr == II)",
+ " { continue;",
+ " }",
+ " #endif",
" ntrpt->pr = (uchar) II;",
" ntrpt->st = tt; ",
- " trpt->o_pm &= ~1; /* no move yet */",
- "#ifdef EVENT_TRACE",
+ " trpt->o_pm &= ~1; /* no move yet */",
+ " #ifdef EVENT_TRACE",
" trpt->o_event = now._event;",
- "#endif",
- "#ifdef HAS_PROVIDED",
- " if (!provided(II, ot, tt, t)) continue;",
- "#endif",
- "#ifdef HAS_UNLESS",
+ " #endif",
+
+ " #ifdef HAS_PRIORITY",
+ " if (!highest_priority(((P0 *)this)->_pid, II, t))",
+ " { continue;",
+ " }",
+ " #else",
+ " #ifdef HAS_PROVIDED",
+ " if (!provided(II, ot, tt, t))",
+ " { continue;",
+ " }",
+ " #endif",
+ " #endif",
+
+ " #ifdef HAS_UNLESS",
" E_state = 0;",
- "#endif",
+ " #endif",
" for (t = trans[ot][tt]; t; t = t->nxt)",
" {",
- "#ifdef HAS_UNLESS",
+ " #ifdef HAS_UNLESS",
" if (E_state > 0",
" && E_state != t->e_trans)",
" break;",
- "#endif",
+ " #endif",
" ntrpt->o_t = t;",
"",
" oboq = boq;",
@@ -1101,136 +1654,147 @@
"",
" trpt->o_pm |= 1; /* we moved */",
" (trpt+1)->o_m = _m; /* for unsend */",
- "#ifdef PEG",
+ " #ifdef PEG",
" peg[t->forw]++;",
- "#endif",
- "#ifdef CHECK",
- " printf(\"%%3d: proc %%d exec %%d, \",",
+ " #endif",
+ " #ifdef CHECK",
+ " printf(\"%%3ld: proc %%d exec %%d, \",",
" depth, II, t->forw);",
" printf(\"%%d to %%d, %%s %%s %%s\",",
" tt, t->st, t->tp,",
" (t->atom&2)?\"atomic\":\"\",",
" (boq != -1)?\"rendez-vous\":\"\");",
- "#ifdef HAS_UNLESS",
+ " #ifdef HAS_UNLESS",
" if (t->e_trans)",
" printf(\" (escapes to state %%d)\", t->st);",
- "#endif",
+ " #endif",
" printf(\" %%saccepting [tau=%%d]\\n\",",
" (trpt->o_pm&2)?\"\":\"non-\", trpt->tau);",
- "#endif",
- "#ifdef HAS_UNLESS",
+ " #endif",
+ " #ifdef HAS_UNLESS",
" E_state = t->e_trans;",
- "#if SYNC>0",
+ " #if SYNC>0",
" if (t->e_trans > 0 && (boq != -1 /* || oboq != -1 */))",
- " { fprintf(efd, \"error:\tthe use of rendezvous stmnt in the escape clause\\n\");",
+ " { fprintf(efd, \"error:\ta rendezvous stmnt in the escape clause\\n\");",
" fprintf(efd, \"\tof an unless stmnt is not compatible with -DBFS\\n\");",
" pan_exit(1);",
" }",
- "#endif",
- "#endif",
- " if (t->st > 0) ((P0 *)this)->_p = t->st;",
+ " #endif",
+ " #endif",
+ " if (t->st > 0)",
+ " { ((P0 *)this)->_p = t->st;",
+ " }",
"",
- " /* ptr to pred: */ ntrpt->ostate = (struct H_el *) otrpt;",
+ " /* ptr to pred: */ ntrpt->ostate = (H_el *) otrpt;",
" ntrpt->st = tt;",
" if (boq == -1 && (t->atom&2)) /* atomic */",
" ntrpt->tau = 8; /* record for next move */",
" else",
" ntrpt->tau = 0;",
- "",
" store_state(ntrpt, (boq != -1 || (t->atom&2)), oboq);",
- "#ifdef EVENT_TRACE",
+ " #ifdef EVENT_TRACE",
" now._event = trpt->o_event;",
- "#endif",
- "",
+ " #endif",
" /* undo move and continue */",
" trpt++; /* this is where ovals and ipt are set */",
" do_reverse(t, II, _m); /* restore now. */",
" trpt--;",
- "#ifdef CHECK",
- " printf(\"%%3d: proc %%d \", depth, II);",
+ " #ifdef CHECK",
+ " enter_critical(GLOBAL_LOCK); /* verbose mode */",
+ " #if NCORE>1",
+ " printf(\"cpu%%d: \", core_id);",
+ " #endif",
+ " printf(\"%%3lu: proc %%d \", depth, II);",
" printf(\"reverses %%d, %%d to %%d,\",",
" t->forw, tt, t->st);",
- " printf(\" %%s [abit=%%d,adepth=%%d,\",",
+ " printf(\" %%s [abit=%%d,adepth=%%ld,\",",
" t->tp, now._a_t, A_depth);",
" printf(\"tau=%%d,%%d]\\n\",",
" trpt->tau, (trpt-1)->tau);",
- "#endif",
+ " leave_critical(GLOBAL_LOCK);",
+ " #endif",
" reached[ot][t->st] = 1;",
- " reached[ot][tt] = 1;",
+ " reached[ot][tt] = 1;",
"",
" ((P0 *)this)->_p = tt;",
" _n |= _m;",
" } }",
-/* PO */
- "#ifndef NOREDUCE",
+ " #ifndef NOREDUCE", /* with PO */
" /* preselected - no succ definitely outside stack */",
" if ((trpt->tau&32) && !(trpt->tau&64))",
" { From = now._nr_pr-1; To = BASE;",
- "#ifdef DEBUG",
- " printf(\"%%3d: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
+ " #ifdef DEBUG",
+ " cpu_printf(\"%%3ld: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
" depth, II+1, (int) _n, trpt->tau);",
- "#endif",
+ " #endif",
" _n = 0; trpt->tau &= ~32;",
" if (II >= BASE)",
- " goto Pickup;",
+ " { goto Pickup;",
+ " }",
" goto MainLoop;",
" }",
" trpt->tau &= ~(32|64);",
- "#endif",
-/* PO */
+ " #endif", /* PO */
" if (_n != 0)",
- " continue;",
- "#ifdef DEBUG",
- " printf(\"%%3d: no move [II=%%d, tau=%%d, boq=%%d, _nr_pr=%%d]\\n\",",
+ " { continue;",
+ " }",
+ " #ifdef DEBUG",
+ " printf(\"%%3ld: no move [II=%%d, tau=%%d, boq=%%d, _nr_pr=%%d]\\n\",",
" depth, II, trpt->tau, boq, now._nr_pr);",
- "#endif",
+ " #endif",
" if (boq != -1)",
" { failedrv++;",
- " x = (Trail *) trpt->ostate; /* pre-rv state */",
- " if (!x) continue; /* root state */",
+ " x = (Trail *) trpt->ostate; /* pre-rv state */",
+ " if (!x)",
+ " { continue; /* root state */",
+ " }",
" if ((x->tau&8) || (x->tau&32)) /* break atomic or preselect at parent */",
" { x->o_pm |= 8; /* mark failure */",
- " this = (((uchar *)&now)+proc_offset[otrpt->pr]);",
- "#ifdef VERBOSE",
+ " this = pptr(otrpt->pr);",
+ " #ifdef VERBOSE",
" printf(\"\\treset state of %%d from %%d to %%d\\n\",",
" otrpt->pr, ((P0 *)this)->_p, otrpt->st);",
- "#endif",
+ " #endif",
" ((P0 *)this)->_p = otrpt->st;",
" unsend(boq); /* retract rv offer */",
" boq = -1;",
" push_bfs(x, x->o_tt);",
- "#ifdef VERBOSE",
+ " #ifdef VERBOSE",
" printf(\"failed rv, repush with %%d\\n\", x->o_pm);",
- "#endif",
+ " #endif",
" }",
- "#ifdef VERBOSE",
- " else printf(\"failed rv, tau at parent: %%d\\n\", x->tau);",
- "#endif",
+ " #ifdef VERBOSE",
+ " else",
+ " { printf(\"failed rv, tau at parent: %%d\\n\", x->tau);",
+ " }",
+ " #endif",
" } else if (now._nr_pr > 0)",
" {",
" if ((trpt->tau&8)) /* atomic */",
" { trpt->tau &= ~(1|8); /* 1=timeout, 8=atomic */",
- "#ifdef DEBUG",
- " printf(\"%%3d: atomic step proc %%d blocks\\n\",",
+ " #ifdef DEBUG",
+ " printf(\"%%3ld: atomic step proc %%d blocks\\n\",",
" depth, II+1);",
- "#endif",
+ " #endif",
" goto Repeat;",
" }",
"",
" if (!(trpt->tau&1)) /* didn't try timeout yet */",
" { trpt->tau |= 1;",
- "#ifdef DEBUG",
- " printf(\"%%d: timeout\\n\", depth);",
- "#endif",
+ " #ifdef DEBUG",
+ " printf(\"%%ld: timeout\\n\", depth);",
+ " #endif",
" goto MainLoop;",
" }",
- "#ifndef VERI",
+ " #ifndef VERI",
" if (!noends && !a_cycles && !endstate())",
- " uerror(\"invalid end state\");",
- "#endif",
+ " { uerror(\"invalid end state\");",
+ " }",
+ " #endif",
" } }",
"}",
+ "#endif", /* !BFS_PAR */
"",
"void",
"putter(Trail *trpt, int fd)",
@@ -1252,19 +1816,27 @@
"}",
"",
"void",
- "nuerror(char *str)",
+ "n_ewrite(int fd, char *s, int n)",
+ "{ if (write(fd, s, strlen(s)) != strlen(s))",
+ " { printf(\"pan: error writing %%s\\n\", fnm);",
+ " pan_exit(1);",
+ " }",
+ "}",
+ "",
+ "void",
+ "nuerror(void)",
"{ int fd = make_trail();",
" int j;",
"",
" if (fd < 0) return;",
- "#ifdef VERI",
- " sprintf(snap, \"-2:%%d:-2\\n\", VERI);",
- " write(fd, snap, strlen(snap));",
- "#endif",
- "#ifdef MERGED",
- " sprintf(snap, \"-4:-4:-4\\n\");",
- " write(fd, snap, strlen(snap));",
- "#endif",
+ " #ifdef VERI",
+ " sprintf(snap, \"-2:%%d:-2\\n\", (uchar) ((P0 *)pptr(0))->_t);",
+ " n_ewrite(fd, snap, strlen(snap));",
+ " #endif",
+ " #ifdef MERGED",
+ " sprintf(snap, \"-4:-4:-4\\n\");",
+ " n_ewrite(fd, snap, strlen(snap));",
+ " #endif",
" trcnt = 1;",
" putter(trpt, fd);",
" if (ntrpt->o_t)", /* 4.2.8 -- Alex example, missing last transition */
@@ -1271,14 +1843,11 @@
" { sprintf(snap, \"%%d:%%d:%%d\\n\",",
" trcnt++, ntrpt->pr, ntrpt->o_t->t_id);",
" j = strlen(snap);",
- " if (write(fd, snap, j) != j)",
- " { printf(\"pan: error writing %%s\\n\", fnm);",
- " pan_exit(1);",
- " } }",
+ " n_ewrite(fd, snap, j);",
+ " }",
" close(fd);",
" if (errors >= upto && upto != 0)",
- " {",
- " wrapup();",
+ " { wrapup();",
" }",
"}",
"#endif", /* BFS */
@@ -1285,8 +1854,141 @@
0,
};
-static char *Code2c[] = {
+static const char *Code2d[] = {
+ "clock_t start_time;",
+ "#if NCORE>1",
+ "clock_t crash_stamp;",
+ "#endif",
+ "#if !defined(WIN32) && !defined(WIN64)",
+ "struct tms start_tm;",
+ "#endif",
+ "",
+ "#if SYNC",
+ "extern int q_zero(int);",
+ "extern int not_RV(int);",
+ "#endif",
+ "",
"void",
+ "start_timer(void)",
+ "{",
+ "#if defined(WIN32) || defined(WIN64)",
+ " start_time = clock();",
+ "#else",
+ " start_time = times(&start_tm);",
+ "#endif",
+ "}",
+ "",
+ "double delta_time;",
+ "",
+ "void",
+ "report_time(void)",
+ "{",
+ " printf(\"\\npan: elapsed time %%.3g seconds\\n\", delta_time);",
+ " if (delta_time > 0.01)",
+ " { printf(\"pan: rate %%9.8g states/second\\n\", nstates/delta_time);",
+ " if (verbose)",
+ " { printf(\"pan: avg transition delay %%.5g usec\\n\",",
+ " delta_time/(nstates+truncs));",
+ " } }",
+ "}",
+ "",
+ "void",
+ "stop_timer(int report)",
+ "{ clock_t stop_time;",
+ "#if !defined(WIN32) && !defined(WIN64)",
+ " struct tms stop_tm;",
+ " stop_time = times(&stop_tm);",
+ " delta_time = ((double) (stop_time - start_time)) / ((double) sysconf(_SC_CLK_TCK));",
+ "#else",
+ " stop_time = clock();",
+ " delta_time = ((double) (stop_time - start_time)) / ((double) CLOCKS_PER_SEC);",
+ "#endif",
+ " if (readtrail || delta_time < 0.00) return;",
+ "#if NCORE>1",
+ " if (core_id == 0 && nstates > (double) 0)",
+ " { printf(\"\\ncpu%%d: elapsed time %%.3g seconds (%%g states visited)\\n\",",
+ " core_id, delta_time, nstates);",
+ " if (delta_time > 0.01)",
+ " { printf(\"cpu%%d: rate %%g states/second\\n\", core_id, nstates/delta_time);",
+ " }",
+ " { void check_overkill(void);",
+ " check_overkill();",
+ " } }",
+ "#else",
+ " if (report)",
+ " { report_time();",
+ " }",
+ "#endif",
+ "}",
+ "",
+ "#if NCORE>1",
+ "#ifdef T_ALERT",
+ "double t_alerts[17];",
+ "",
+ "void",
+ "crash_report(void)",
+ "{ int i;",
+ " printf(\"crash alert intervals:\\n\");",
+ " for (i = 0; i < 17; i++)",
+ " { printf(\"%%d\\t%%g\\n\", i, t_alerts[i]);",
+ "} }",
+ "#endif",
+ "",
+ "void",
+ "crash_reset(void)",
+ "{ /* false alarm */",
+ " if (crash_stamp != (clock_t) 0)",
+ " {",
+ "#ifdef T_ALERT",
+ " double delta_time;",
+ " int i;",
+ "#if defined(WIN32) || defined(WIN64)",
+ " delta_time = ((double) (clock() - crash_stamp)) / ((double) CLOCKS_PER_SEC);",
+ "#else",
+ " delta_time = ((double) (times(&start_tm) - crash_stamp)) / ((double) sysconf(_SC_CLK_TCK));",
+ "#endif",
+ " for (i = 0; i < 16; i++)",
+ " { if (delta_time <= (i*30))",
+ " { t_alerts[i] = delta_time;",
+ " break;",
+ " } }",
+ " if (i == 16) t_alerts[i] = delta_time;",
+ "#endif",
+ " if (verbose)",
+ " printf(\"cpu%%d: crash alert off\\n\", core_id);",
+ " }",
+ " crash_stamp = (clock_t) 0;",
+ "}",
+ "",
+ "int",
+ "crash_test(double maxtime)",
+ "{ double delta_time;",
+ " if (crash_stamp == (clock_t) 0)",
+ " { /* start timing */",
+ "#if defined(WIN32) || defined(WIN64)",
+ " crash_stamp = clock();",
+ "#else",
+ " crash_stamp = times(&start_tm);",
+ "#endif",
+ " if (verbose)",
+ " { printf(\"cpu%%d: crash detection\\n\", core_id);",
+ " }",
+ " return 0;",
+ " }",
+ "#if defined(WIN32) || defined(WIN64)",
+ " delta_time = ((double) (clock() - crash_stamp)) / ((double) CLOCKS_PER_SEC);",
+ "#else",
+ " delta_time = ((double) (times(&start_tm) - crash_stamp)) / ((double) sysconf(_SC_CLK_TCK));",
+ "#endif",
+ " return (delta_time >= maxtime);",
+ "}",
+ "#endif",
+ "",
+ "#ifdef BFS_PAR",
+ "int ncores = 0;",
+ "#endif",
+ "",
+ "void",
"do_the_search(void)",
"{ int i;",
" depth = mreached = 0;",
@@ -1300,11 +2002,13 @@
" if (!(trpt->o_pm&2)",
" && accpstate[ptr->_t][ptr->_p])",
" { trpt->o_pm |= 2;",
+ " break;",
" }",
"#else",
" if (!(trpt->o_pm&4)",
" && progstate[ptr->_t][ptr->_p])",
" { trpt->o_pm |= 4;",
+ " break;",
" }",
"#endif",
" }",
@@ -1319,21 +2023,21 @@
" }",
"#endif",
"#endif",
- "#ifndef NOCOMP",
+ "#if !defined(NOCOMP) && !defined(HC)",
" Mask[0] = Mask[1] = 1; /* _nr_pr, _nr_qs */",
" if (!a_cycles)",
" { i = &(now._a_t) - (uchar *) &now;",
" Mask[i] = 1; /* _a_t */",
" }",
- "#ifndef NOFAIR",
- " if (!fairness)",
- " { int j = 0;",
- " i = &(now._cnt[0]) - (uchar *) &now;",
- " while (j++ < NFAIR)",
- " Mask[i++] = 1; /* _cnt[] */",
- " }",
+ " #ifndef NOFAIR",
+ " if (!fairness)",
+ " { int j = 0;",
+ " i = &(now._cnt[0]) - (uchar *) &now;",
+ " while (j++ < NFAIR)",
+ " Mask[i++] = 1; /* _cnt[] */",
+ " }",
+ " #endif",
"#endif",
- "#endif",
"#ifndef NOFAIR",
" if (fairness",
" && (a_cycles && (trpt->o_pm&2)))",
@@ -1340,12 +2044,19 @@
" { now._a_t = 2; /* set the A-bit */",
" now._cnt[0] = now._nr_pr + 1;", /* NEW: +1 */
"#ifdef VERBOSE",
- " printf(\"%%3d: fairness Rule 1, cnt=%%d, _a_t=%%d\\n\",",
+ " printf(\"%%3ld: fairness Rule 1, cnt=%%d, _a_t=%%d\\n\",",
" depth, now._cnt[now._a_t&1], now._a_t);",
"#endif",
" }",
"#endif",
+ " c_stack_start = (char *) &i; /* meant to be read-only */",
+
+ "#if defined(HAS_CODE) && defined (C_INIT)",
+ " C_INIT; /* initialization of data that must precede fork() */",
+ " c_init_done++;",
+ "#endif",
+
"#if defined(C_States) && (HAS_TRACK==1)",
" /* capture initial state of tracked C objects */",
" c_update((uchar *) &(now.c_state[0]));",
@@ -1354,17 +2065,30 @@
"#ifdef HAS_CODE",
" if (readtrail) getrail(); /* no return */",
"#endif",
+ "#ifndef BFS_PAR",
+ " start_timer();",
+ "#endif",
"#ifdef BFS",
- " bfs();",
+ " #ifdef BFS_PAR",
+ " bfs_main(ncores,0);",
+ " #else",
+ " bfs();",
+ " #endif",
"#else",
- "#if defined(C_States) && defined(HAS_STACK) && (HAS_TRACK==1)",
- " /* initial state of tracked & unmatched objects */",
- " c_stack((uchar *) &(svtack->c_stack[0]));",
- "#endif",
- "#ifdef RANDOMIZE",
- " srand(123);",
- "#endif",
- " new_state(); /* start 1st DFS */",
+ " #if defined(C_States) && defined(HAS_STACK) && (HAS_TRACK==1)",
+ " /* initial state of tracked & unmatched objects */",
+ " c_stack((uchar *) &(svtack->c_stack[0]));",
+ " #endif",
+
+ " #if defined(P_RAND) || defined(T_RAND)",
+ " srand(s_rand+HASH_NR);", /* do_the_search */
+ " #endif",
+
+ " #if NCORE>1",
+ " mem_get();",
+ " #else",
+ " new_state(); /* start 1st DFS */",
+ " #endif",
"#endif",
"}",
@@ -1373,42 +2097,41 @@
"do_reverse(Trans *t, short II, uchar M)",
"{ uchar _m = M;",
" int tt = (int) ((P0 *)this)->_p;",
- "#include REVERSE_MOVES",
+ "#include BACKWARD_MOVES",
"R999: return _m;",
"}",
"#endif",
"#ifndef INLINE",
- "#ifdef EVENT_TRACE",
+ " #ifdef EVENT_TRACE",
"static char _tp = 'n'; static int _qid = 0;",
- "#endif",
+ " #endif",
"uchar",
"do_transit(Trans *t, short II)",
"{ uchar _m = 0;",
" int tt = (int) ((P0 *)this)->_p;",
- "#ifdef M_LOSS",
+ " #ifdef M_LOSS",
" uchar delta_m = 0;",
- "#endif",
- "#ifdef EVENT_TRACE",
+ " #endif",
+ " #ifdef EVENT_TRACE",
" short oboq = boq;",
" uchar ot = (uchar) ((P0 *)this)->_t;",
- " if (ot == EVENT_TRACE) boq = -1;",
+ " if (II == -EVENT_TRACE) boq = -1;",
"#define continue { boq = oboq; return 0; }",
- "#else",
+ " #else",
"#define continue return 0",
"#ifdef SEPARATE",
" uchar ot = (uchar) ((P0 *)this)->_t;",
"#endif",
- "#endif",
+ " #endif",
"#include FORWARD_MOVES",
"P999:",
- "#ifdef EVENT_TRACE",
- " if (ot == EVENT_TRACE) boq = oboq;",
- "#endif",
+ " #ifdef EVENT_TRACE",
+ " if (II == -EVENT_TRACE) boq = oboq;",
+ " #endif",
" return _m;",
- "#undef continue",
+ " #undef continue",
"}",
-
"#ifdef EVENT_TRACE",
"void",
"require(char tp, int qid)",
@@ -1417,67 +2140,65 @@
"",
" if (now._event != endevent)",
" for (t = trans[EVENT_TRACE][now._event]; t; t = t->nxt)",
- " { if (do_transit(t, EVENT_TRACE))",
+ " { if (do_transit(t, -EVENT_TRACE))",
" { now._event = t->st;",
" reached[EVENT_TRACE][t->st] = 1;",
- "#ifdef VERBOSE",
+ " #ifdef VERBOSE",
" printf(\" event_trace move to -> %%d\\n\", t->st);",
- "#endif",
- "#ifndef BFS",
- "#ifndef NP",
+ " #endif",
+ " #ifndef BFS",
+ " #ifndef NP",
" if (accpstate[EVENT_TRACE][now._event])",
" (trpt+1)->o_pm |= 2;",
- "#else",
+ " #else",
" if (progstate[EVENT_TRACE][now._event])",
" (trpt+1)->o_pm |= 4;",
- "#endif",
- "#endif",
- "#ifdef NEGATED_TRACE",
+ " #endif",
+ " #endif",
+ " #ifdef NEGATED_TRACE",
" if (now._event == endevent)",
" {",
- "#ifndef BFS",
+ " #ifndef BFS",
" depth++; trpt++;",
- "#endif",
+ " #endif",
" uerror(\"event_trace error (all events matched)\");",
- "#ifndef BFS",
+ " #ifndef BFS",
" trpt--; depth--;",
- "#endif",
+ " #endif",
" break;",
" }",
- "#endif",
+ " #endif",
" for (t = t->nxt; t; t = t->nxt)",
- " { if (do_transit(t, EVENT_TRACE))",
+ " { if (do_transit(t, -EVENT_TRACE))",
" Uerror(\"non-determinism in event-trace\");",
" }",
" return;",
" }",
- "#ifdef VERBOSE",
+ " #ifdef VERBOSE",
" else",
" printf(\" event_trace miss '%%c' -- %%d, %%d, %%d\\n\",",
" tp, qid, now._event, t->forw);",
- "#endif",
+ " #endif",
" }",
- "#ifdef NEGATED_TRACE",
+ " #ifdef NEGATED_TRACE",
" now._event = endevent; /* only 1st try will count -- fixed 4.2.6 */",
- "#else",
- "#ifndef BFS",
+ " #else",
+ " #ifndef BFS",
" depth++; trpt++;",
- "#endif",
+ " #endif",
" uerror(\"event_trace error (no matching event)\");",
- "#ifndef BFS",
+ " #ifndef BFS",
" trpt--; depth--;",
- "#endif",
- "#endif",
+ " #endif",
+ " #endif",
"}",
"#endif",
-
"int",
"enabled(int iam, int pid)",
"{ Trans *t; uchar *othis = this;",
" int res = 0; int tt; uchar ot;",
- "#ifdef VERI",
- " /* if (pid > 0) */ pid++;",
- "#endif",
+ "",
+ " pid += BASE;",
" if (pid == iam)",
" Uerror(\"used: enabled(pid=thisproc)\");",
" if (pid < 0 || pid >= (int) now._nr_pr)",
@@ -1496,21 +2217,132 @@
" return res;",
"}",
"#endif",
+ "",
+ "#ifdef HAS_PRIORITY",
+ "int",
+ "highest_priority(int pid, short nII, Trans *t)",
+ "{ int i = pid; uchar *othis = this;",
+ "",
+ "#ifdef VERI",
+ " if (nII == 0)",
+ " { return 1;", /* never claim */
+ " }",
+ "#endif",
+ "#ifdef HAS_PROVIDED",
+ " i = pid+BASE;", /* uncorrected process number */
+ "#endif",
+ " if (i < 0",
+ " || i >= (int) now._nr_pr",
+ "#ifdef HAS_PROVIDED",
+ " || !provided(i, (uchar) ((P0 *)this)->_t, (int) ((P0 *)this)->_p, t)",
+ "#endif",
+ " )",
+ " { return 0;",
+ " }",
+ "",
+ " for (i = BASE; i < now._nr_pr; i++)", /* all except never, if present */
+ " { this = pptr(i);",
+ " if (i != pid+BASE",
+ " && ((P0 *)this)->_priority > ((P0 *)pptr(pid+BASE))->_priority",
+ "#ifdef HAS_PROVIDED",
+ " && provided(i, (uchar) ((P0 *)this)->_t, (int) ((P0 *)this)->_p, 0)",
+ "#endif",
+ " && enabled(i+1, i-BASE))", /* enabled adds back BASE in 2nd arg */
+ " { this = othis;",
+ " return 0;",
+ " } }",
+ " this = othis;",
+ " return 1;",
+ "}",
+ "int",
+ "get_priority(int pid)",
+ "{ pid += BASE; /* 6.2.7 */",
+ " if (pid < 0 || pid >= (int) now._nr_pr)",
+ " return 0;",
+ " return ((P0 *)pptr(pid))->_priority;",
+ "}",
+ "int",
+ "set_priority(int pid, int pr)",
+ "{ pid += BASE; /* 6.2.7 */",
+ " if (pid < 0 || pid >= (int) now._nr_pr)",
+ " {",
+ " #ifdef VERBOSE",
+ " printf(\"warning: bad pid %%d, no such process (set_priority)\\n\", pid);",
+ " #endif",
+ " return 1;",
+ " }",
+ " if (pr < 1 || pr > 255)",
+ " { Uerror(\"priority is out of range\");",
+ " }",
+
+ " if (!TstOnly)",
+ " { (trpt+1)->o_priority = ",
+ " (((P0 *)pptr(pid))->_priority & 255) | (pid << 8);",
+ " ((P0 *)pptr(pid))->_priority = pr;",
+ " }",
+
+ " return 1;", /* always executable */
+ "}",
+ "#endif",
+ "",
"void",
+ "snap_time(void)",
+ "{ clock_t stop_time;",
+ " double delta_time;",
+ "#if !defined(WIN32) && !defined(WIN64)",
+ " struct tms stop_tm;",
+ " stop_time = times(&stop_tm);",
+ " delta_time = ((double) (stop_time - start_time)) / ((double) sysconf(_SC_CLK_TCK));",
+ "#else",
+ " stop_time = clock();",
+ " delta_time = ((double) (stop_time - start_time)) / ((double) CLOCKS_PER_SEC);",
+ "#endif",
+ " if (delta_time > 0.01)",
+ " { printf(\"t= %%8.3g \", delta_time);",
+ " printf(\"R= %%7.0g\", nstates/delta_time);",
+ " }",
+ " printf(\"\\n\");",
+ " if (quota > 0.1 && delta_time > quota)",
+ " { printf(\"Time limit of %%6.3g minutes exceeded\\n\", quota/60.0);",
+ "#if NCORE>1",
+ " fflush(stdout);",
+ " leave_critical(GLOBAL_LOCK);",
+ " sudden_stop(\"time-limit\");",
+ " exit(1);",
+ "#endif",
+ " wrapup();",
+ " }",
+ "}",
+ "void",
"snapshot(void)",
- "{ static long sdone = (long) 0;",
- " long ndone = (unsigned long) nstates/1000000;",
- " if (ndone == sdone) return;",
- " sdone = ndone;",
- " printf(\"Depth= %%7d States= %%7g \", mreached, nstates);",
- " printf(\"Transitions= %%7g \", nstates+truncs);",
+ "{",
+ "#ifdef BFS_PAR",
+ " e_critical(BFS_GLOB); /* bfs_par / snapshot */",
+ " printf(\"cpu%%d: \", who_am_i);",
+ "#endif",
+ "#if NCORE>1",
+ " enter_critical(GLOBAL_LOCK); /* ncore / snapshot */",
+ " printf(\"cpu%%d: \", core_id);",
+ "#endif",
+ " printf(\"Depth= %%7ld States= %%8.3g \",",
+ "#if NCORE>1",
+ " (long) (nr_handoffs * z_handoff) +",
+ "#endif",
+ " mreached, nstates);",
+ " printf(\"Transitions= %%8.3g \", nstates+truncs);",
"#ifdef MA",
- " printf(\"Nodes= %%7d \", nr_states);",
+ " printf(\"Nodes= %%7lu \", nr_states);",
"#endif",
- " printf(\"Memory= %%-6.3f\\n\", memcnt/1000000.);",
+ " printf(\"Memory= %%9.3f\\t\", memcnt/1048576.);",
+ " snap_time();",
" fflush(stdout);",
+ "#if NCORE>1",
+ " leave_critical(GLOBAL_LOCK);",
+ "#endif",
+ "#ifdef BFS_PAR",
+ " x_critical(BFS_GLOB);",
+ "#endif",
"}",
-
"#ifdef SC",
"void",
"stack2disk(void)",
@@ -1552,46 +2384,246 @@
"#endif",
"uchar *",
- "Pptr(int x)", /* as a fct, to avoid a problem with the p9 compiler */
- "{ if (x < 0 || x >= MAXPROC || !proc_offset[x])", /* does not exist */
+ "Pptr(int x)",
+ "{ if (x < 0 || x >= MAXPROC", /* does not exist */
+ "#ifdef TRIX",
+ " || !processes[x])",
+ "#else",
+ " || !proc_offset[x])",
+ "#endif",
" return noptr;",
" else",
" return (uchar *) pptr(x);",
+ "}\n",
+ "uchar *",
+ "Qptr(int x)",
+ "{ if (x < 0 || x >= MAXQ",
+ "#ifdef TRIX",
+ " || !channels[x])",
+ "#else",
+ " || !q_offset[x])",
+ "#endif",
+ " return noqptr;",
+ " else",
+ " return (uchar *) qptr(x);",
+ "}\n",
+ "",
+ "#if NCLAIMS>1",
+ "void",
+ "select_claim(int n)",
+ "{ int m, i;",
+ " if (n < 0 || n >= NCLAIMS)",
+ " { uerror(\"non-existing claim\");",
+ " } else",
+ " { m = ((Pclaim *)pptr(0))->_n;",
+ " if (verbose)",
+ " { printf(\"%%d: Claim %%s (%%d), from state %%d\\n\",",
+ " (int) depth, procname[spin_c_typ[n]],",
+ " n, ((Pclaim *)pptr(0))->c_cur[n]);",
+ " } else",
+ " { printf(\"pan: ltl formula %%s\\n\",",
+ " procname[spin_c_typ[n]]);",
+ " }",
+ " ((Pclaim *)pptr(0))->c_cur[m] = ((Pclaim *)pptr(0))->_p;",
+ " ((Pclaim *)pptr(0))->_t = spin_c_typ[n];",
+ " ((Pclaim *)pptr(0))->_p = ((Pclaim *)pptr(0))->c_cur[n];",
+ " ((Pclaim *)pptr(0))->_n = n;",
+ " for (i = 0; src_all[i].src != (short *) 0; i++)",
+ " { if (src_all[i].tp == spin_c_typ[n])",
+ " { src_claim = src_all[i].src;",
+ " break;",
+ " } }",
+ " if (src_all[i].src == (short *) 0)",
+ " { uerror(\"cannot happen: src_ln ref\");",
+ " } }",
"}",
+ "#else",
+ "void",
+ "select_claim(int n)",
+ "{ if (n != 0) uerror(\"non-existing claim\");",
+ "}",
+ "#endif",
+
"int qs_empty(void);",
+ "#if !defined(BFS) && (!defined(BITSTATE) || !defined(MA))",
+ "#ifdef NSUCC",
+ "int N_succ[512];",
+ "void",
+ "tally_succ(int cnt)",
+ "{ if (cnt < 512) N_succ[cnt]++;",
+ " else printf(\"tally_succ: cnt %%d exceeds range\\n\", cnt);",
+ "}",
+ "",
+ "void",
+ "dump_succ(void)",
+ "{ int i; double sum = 0.0;",
+ " double w_avg = 0.0;",
+ " printf(\"Successor counts:\\n\");",
+ " for (i = 0; i < 512; i++)",
+ " { sum += (double) N_succ[i];",
+ " }",
+ " for (i = 0; i < 512; i++)",
+ " { if (N_succ[i] > 0)",
+ " { printf(\"%%3d\t%%10d\t(%%.4g %%%% of total)\\n\",",
+ " i, N_succ[i], (100.0 * (double) N_succ[i])/sum);",
+ " w_avg += (double) i * (double) N_succ[i];",
+ " } }",
+ " if (sum > N_succ[0])",
+ " printf(\"mean %%.4g (without 0: %%.4g)\\n\", w_avg / sum, w_avg / (sum - (double) N_succ[0]));",
+ "}",
+ "#endif",
+ "",
+ "#ifdef P_REVERSE",
+ " #define FROM_P (BASE)",
+ " #define UPTO_P (now._nr_pr-1)",
+ " #define MORE_P (II <= To)", /* p.o. only */
+ " #define INI_P (From-1)", /* fairness only */
+ " #define CNT_P (1 + (To - From))", /* P_RAND start */
+ " #define NDONE_P (From <= To)", /* P_RAND continue */
+ " #define ALL_P (II = From; II <= To; II++)",
+ "#else",
+ " #define FROM_P (now._nr_pr-1)",
+ " #define UPTO_P (BASE)",
+ " #define MORE_P (II >= BASE)",
+ " #define INI_P (From+1)",
+ " #define CNT_P (1 + (From - To))",
+ " #define NDONE_P (From >= To)",
+ " #define ALL_P (II = From; II >= To; II--)",
+ "#endif",
+ "",
+ "#ifdef PERMUTED",
+ " #define CONTINUE0 { if (reversing&2) { II = oII; } continue; }",
+ " #define CONTINUE { if (reversing&2) { p_reorder(seed); II = oII; } continue; }",
+ "#else",
+ " #define CONTINUE0 { continue; }",
+ " #define CONTINUE { continue; }",
+ "#endif",
+ "#ifdef PERMUTED",
+ "uchar _permutation_[256];",
+ "void",
+ "set_reversed(int unused)",
+ "{ int i, n = now._nr_pr;",
+ " #ifdef VERBOSE",
+ " printf(\"%%ld: Set_reversed\\n\", depth);",
+ " #endif",
+ " #if defined(VERI) && !defined(NOCLAIM)",
+ " for (i = 1; i < n; i++)",
+ " { _permutation_[i] = n-i;",
+ " }",
+ " #else",
+ " for (i = 0; i < n; i++)",
+ " { _permutation_[i] = n-1-i;",
+ " }",
+ " #endif",
+ "}",
+ "void",
+ "set_rotated(int unused)",
+ "{ int i, n = now._nr_pr;",
+ " #ifdef VERBOSE",
+ " printf(\"%%ld: Set_rotated %%d\\n\", depth, p_rotate);",
+ " #endif",
+ " #if defined(VERI) && !defined(NOCLAIM)",
+ " for (i = 1; i < n; i++)",
+ " { _permutation_[i] = 1+(i-1+p_rotate)%%(n-1);",
+ " }",
+ " #else",
+ " for (i = 0; i < n; i++)",
+ " { _permutation_[i] = (i+p_rotate)%%n;",
+ " }",
+ " #endif",
+ "}",
+ "void",
+ "set_randrot(int unused)",
+ "{",
+ " if (now._nr_pr > 1)",
+ " { p_rotate = 1+rand()%%(now._nr_pr-1);",
+ " } else",
+ " { p_rotate = 0;",
+ " }",
+ " set_rotated(0);",
+ "}",
+ "void",
+ "set_permuted(int T)",
+ "{ /* permute nrs 1..n-1, leave 0 in place */",
+ " int i, j, k, n = now._nr_pr;",
+ " char tmp, *in = &(_permutation_[0]);",
+ " #ifdef VERBOSE",
+ " printf(\"%%ld: Set_permuted %%d\\n\", depth, T);",
+ " #endif",
+ " srand(T);", /* set_permuted */
+ " for (i = 0; i < n; i++)",
+ " { in[i] = i;",
+ " }",
+ " if (n > 1)",
+ " { for (i = 0; i < n; i++)",
+ " {",
+ " #if defined(VERI) && !defined(NOCLAIM)",
+ " j = 1 + rand()%%(n-1);",
+ " k = 1 + rand()%%(n-1);",
+ " #else",
+ " j = rand()%%(n);",
+ " k = rand()%%(n);",
+ " #endif",
+ " tmp = in[j];",
+ " in[j] = in[k];",
+ " in[k] = tmp;",
+ " } }",
+ "}",
+ "",
+ " #ifdef VERBOSE",
+ " short",
+ " get_permuted(int x)",
+ " { printf(\"%%ld: Get_permuted %%d -> %%d\\n\",",
+ " depth, x, _permutation_[x]);",
+ " return (short) _permutation_[x];",
+ " }",
+ " #else",
+ " #define get_permuted(x) (short) _permutation_[x]",
+ " #endif",
+ "",
+ "#endif",
"/*",
" * new_state() is the main DFS search routine in the verifier",
" * it has a lot of code ifdef-ed together to support",
" * different search modes, which makes it quite unreadable.",
- " * if you are studying the code, first use the C preprocessor",
+ " * if you are studying the code, use the C preprocessor",
" * to generate a specific version from the pan.c source,",
" * e.g. by saying:",
" * gcc -E -DNOREDUCE -DBITSTATE pan.c > ppan.c",
- " * and then study the resulting file, rather than this one",
+ " * and then study the resulting file, instead of this version",
" */",
- "#if !defined(BFS) && (!defined(BITSTATE) || !defined(MA))",
+ "",
"void",
"new_state(void)",
"{ Trans *t;",
" uchar _n, _m, ot;",
- "#ifdef RANDOMIZE",
+ "#ifdef T_RAND",
" short ooi, eoi;",
"#endif",
+ "#ifdef PERMUTED",
+ " short oII; uint seed;",
+ "#endif",
"#ifdef M_LOSS",
" uchar delta_m = 0;",
"#endif",
" short II, JJ = 0, kk;",
" int tt;",
- " short From = now._nr_pr-1, To = BASE;",
+ " short From = FROM_P, To = UPTO_P;",
+ "#ifdef BCS",
+ " trpt->sched_limit = 0; /* at depth=0 only */",
+ "#endif",
"Down:",
"#ifdef CHECK",
- " printf(\"%%d: Down - %%s\",",
- " depth, (trpt->tau&4)?\"claim\":\"program\");",
- " printf(\" %%saccepting [pids %%d-%%d]\\n\",",
+ " cpu_printf(\"%%d: Down - %%s %%saccepting [pids %%d-%%d]\\n\",",
+ " depth, (trpt->tau&4)?\"claim\":\"program\",",
" (trpt->o_pm&2)?\"\":\"non-\", From, To);",
"#endif",
+ "#ifdef P_RAND",
+ " trpt->p_skip = -1;",
+ "#endif",
+
"#ifdef SC",
" if (depth > hiwater)",
" { stack2disk();",
@@ -1599,7 +2631,7 @@
" hiwater += DDD;",
" trpt -= DDD;",
" if(verbose)",
- " printf(\"zap %%d: %%d (maxdepth now %%d)\\n\",",
+ " printf(\"zap %%ld: %%ld (maxdepth now %%ld)\\n\",",
" CNT1, hiwater, maxdepth);",
" }",
"#endif",
@@ -1608,23 +2640,54 @@
"#if defined(FULLSTACK) && defined(MA)",
" trpt->proviso = 0;",
"#endif",
- " if (depth >= maxdepth)",
- " { truncs++;",
+ "#ifdef NSUCC",
+ " trpt->n_succ = 0;",
+ "#endif",
+ "#if NCORE>1",
+ " if (mem_hand_off())",
+ " {",
"#if SYNC",
- " (trpt+1)->o_n = 1; /* not a deadlock */",
+ " (trpt+1)->o_n = 1; /* not a deadlock: as below */",
"#endif",
- " if (!warned)",
+ "#ifndef LOOPSTATE",
+ " (trpt-1)->tau |= 16; /* worstcase guess: as below */",
+ "#endif",
+ "#if NCORE>1 && defined(FULL_TRAIL)",
+ " if (upto > 0)",
+ " { Pop_Stack_Tree();",
+ " }",
+ "#endif",
+ " goto Up;",
+ " }",
+ "#endif",
+
+ " if (depth >= maxdepth)",
+ " { if (!warned)",
" { warned = 1;",
" printf(\"error: max search depth too small\\n\");",
" }",
- " if (bounded) uerror(\"depth limit reached\");",
- " (trpt-1)->tau |= 16; /* worstcase guess */",
+ " if (bounded)",
+ " { uerror(\"depth limit reached\");",
+ " }",
+ " truncs++;",
+ "#if SYNC",
+ " (trpt+1)->o_n = 1; /* not a deadlock */",
+ "#endif",
+ "#ifndef LOOPSTATE",
+ " (trpt-1)->tau |= 16; /* worstcase guess */",
+ "#endif",
+
+ "#if NCORE>1 && defined(FULL_TRAIL)",
+ " if (upto > 0)",
+ " { Pop_Stack_Tree();",
+ " }",
+ "#endif",
" goto Up;",
" }",
"AllOver:",
- "#if defined(FULLSTACK) && !defined(MA)",
+ "#if (defined(FULLSTACK) && !defined(MA)) || NCORE>1",
" /* if atomic or rv move, carry forward previous state */",
- " trpt->ostate = (trpt-1)->ostate;", /* was: = (struct H_el *) 0;*/
+ " trpt->ostate = (trpt-1)->ostate;",
"#endif",
"#ifdef VERI",
" if ((trpt->tau&4) || ((trpt-1)->tau&128))",
@@ -1631,51 +2694,115 @@
"#endif",
" if (boq == -1) { /* if not mid-rv */",
"#ifndef SAFETY",
- " /* this check should now be redundant",
- " * because the seed state also appears",
- " * on the 1st dfs stack and would be",
- " * matched in hstore below",
- " */",
+#if 0
+ we want to skip nrpr, nrqs, _a_t and cnt[NFAIR] (in the case of fairness)
+ this is calculated in S_A, but S_A subtracts 2 bytes,
+ because nrpr and nrqs are masked in the default state comparisons
+ so we add those two bytes back here
+ -- in default comparisons (h_store) we skip _a_t and cnt in the
+ -- first comparison to find a match on the base-state
+ -- the _a_t and cnt fields are then separately updated if there was
+ -- a match on the base state
+#endif
" if ((now._a_t&1) && depth > A_depth)",
- " { if (!memcmp((char *)&A_Root, ",
- " (char *)&now, vsize))",
+ " { int delta = S_A + 2;",
+ " if (!memcmp((char *)&A_Root + delta, ",
+ " (char *)&now + delta, vsize - delta))",
" {",
- " depthfound = A_depth;",
- "#ifdef CHECK",
- " printf(\"matches seed\\n\");",
- "#endif",
- "#ifdef NP",
- " uerror(\"non-progress cycle\");",
- "#else",
- " uerror(\"acceptance cycle\");",
- "#endif",
- " goto Up;",
+ "#ifndef NOFAIR",
+ " if (fairness && now._cnt[1] != 1) /* was > 1 */",
+ " {",
+ " #ifdef CHECK",
+ " printf(\"\tfairness count non-zero\\n\");",
+ " #endif",
+ " /* treat as new state */",
+ " } else",
+ "#endif",
+ " { depthfound = A_depth;",
+ " #ifdef CHECK",
+ " printf(\"matches seed\\n\");",
+ " #endif",
+ " #ifdef NP",
+ " uerror(\"non-progress cycle\");",
+ " #else",
+ " uerror(\"acceptance cycle\");",
+ " #endif",
+ " #if NCORE>1 && defined(FULL_TRAIL)",
+ " if (upto > 0)",
+ " { Pop_Stack_Tree();",
+ " }",
+ " #endif",
+ " goto Up;",
+ " } }",
+ " #ifdef CHECK",
+ " else",
+ " {",
+ " printf(\"not seed\\n\");",
" }",
- "#ifdef CHECK",
- " printf(\"not seed\\n\");",
- "#endif",
+ " #endif",
" }",
"#endif",
" if (!(trpt->tau&8)) /* if no atomic move */",
" {",
+ "#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+ " uchar was_last = now._last;",
+ " now._last = 0; /* value not stored */",
+ "#endif",
"#ifdef BITSTATE",
"#ifdef CNTRSTACK", /* -> bitstate, reduced, safety */
- " II = bstore((char *)&now, vsize);",
- " trpt->j6 = j1; trpt->j7 = j2;",
- " JJ = LL[j1] && LL[j2];",
+ " #if defined(BCS) && defined(STORE_CTX)",
+ " { int xj;",
+ " for (xj = trpt->sched_limit; xj <= sched_max; xj++)",
+ " { now._ctx = xj;",
+ " II = b_store((char *)&now, vsize);",
+ " trpt->j6 = j1_spin; trpt->j7 = j2_spin;",
+ " JJ = LL[j1_spin] && LL[j2_spin];",
+ " if (II != 0) { break; }",
+ " }",
+ " now._ctx = 0; /* just in case */",
+ " }",
+ " #else",
+ " II = b_store((char *)&now, vsize);",
+ " trpt->j6 = j1_spin; trpt->j7 = j2_spin;",
+ " JJ = LL[j1_spin] && LL[j2_spin];",
+ " #endif",
"#else",
- "#ifdef FULLSTACK",
- " JJ = onstack_now();", /* sets j1 */
- "#else",
- "#ifndef NOREDUCE",
- " JJ = II; /* worstcase guess for p.o. */",
- "#endif",
- "#endif",
- " II = bstore((char *)&now, vsize);", /* sets j1-j4 */
+ " #ifdef FULLSTACK", /* b_store after onstack_now, to preserve j1-j4 */
+ " #if defined(BCS) && defined(STORE_CTX)",
+ " { int xj;",
+ " now._ctx = 0;",
+ " JJ = onstack_now();", /* mangles j1 */
+ " for (xj = trpt->sched_limit; xj <= sched_max; xj++)",
+ " { now._ctx = xj;",
+ " II = b_store((char *)&now, vsize);", /* sets j1-j4 */
+ " if (II != 0) { break; }",
+ " }",
+ " now._ctx = 0;",
+ " }",
+ " #else",
+ " JJ = onstack_now();", /* mangles j1 */
+ " II = b_store((char *)&now, vsize);", /* sets j1-j4 */
+ " #endif",
+ " #else",
+ " #if defined(BCS) && defined(STORE_CTX)",
+ " { int xj;",
+ " for (xj = trpt->sched_limit; xj <= sched_max; xj++)",
+ " { now._ctx = xj;",
+ " II = b_store((char *)&now, vsize);", /* sets j1-j4 */
+ " JJ = II; /* worstcase guess for p.o. - order corrected in 5.2.1 */",
+ " if (II != 0) { break; }",
+ " }",
+ " now._ctx = 0;",
+ " }",
+ " #else",
+ " II = b_store((char *)&now, vsize);", /* sets j1-j4 */
+ " JJ = II; /* worstcase guess for p.o. - order corrected in 5.2.1 */",
+ " #endif",
+ " #endif",
"#endif",
"#else",
"#ifdef MA",
- " II = gstore((char *)&now, vsize, 0);",
+ " II = g_store((char *)&now, vsize, 0);",
"#ifndef FULLSTACK",
" JJ = II;",
"#else",
@@ -1682,7 +2809,8 @@
" JJ = (II == 2)?1:0;",
"#endif",
"#else",
- " II = hstore((char *)&now, vsize);",
+ " II = h_store((char *)&now, vsize);",
+ " /* @hash j1_spin II */",
"#ifdef FULLSTACK",
" JJ = (II == 2)?1:0;",
"#endif",
@@ -1689,28 +2817,39 @@
"#endif",
"#endif",
" kk = (II == 1 || II == 2);",
+ /* actually, BCS implies HAS_LAST */
+ "#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+ " now._last = was_last; /* restore value */",
+ "#endif",
+
/* II==0 new state */
/* II==1 old state */
/* II==2 on current dfs stack */
/* II==3 on 1st dfs stack */
"#ifndef SAFETY",
-
- " if (!fairness && a_cycles)",
+ /* with multicore we don't know which stack its on */
+ /* with HC there's a small chance of a false match - example fifoq 2012 */
+ "#if !defined(HC) && (NCORE==1 || defined (SEP_STATE))",
" if (II == 2 && ((trpt->o_pm&2) || ((trpt-1)->o_pm&2)))",
- " { II = 3; /* Schwoon & Esparza 2005, Gastin&Moro 2004 */",
- "#ifdef VERBOSE",
+ " #ifndef NOFAIR",
+ " if (a_cycles && !fairness) /* 5.1.6 -- example by Hirofumi Watanabe */",
+ " #endif",
+ " if (depth > A_depth) /* forum example by adl */",
+ " {",
+ " II = 3; /* Schwoon & Esparza 2005, Gastin&Moro 2004 */",
+ "#ifdef VERBOSE",
" printf(\"state match on dfs stack\\n\");",
- "#endif",
+ "#endif",
" goto same_case;",
" }",
+ "#endif",
-
"#if defined(FULLSTACK) && defined(BITSTATE)",
" if (!JJ && (now._a_t&1) && depth > A_depth)",
- " { int oj1 = j1;",
+ " { int oj1 = j1_spin;",
" uchar o_a_t = now._a_t;",
" now._a_t &= ~(1|16|32);", /* 1st stack */
- " if (onstack_now())", /* changes j1 */
+ " if (onstack_now())", /* changes j1_spin */
" { II = 3;",
"#ifdef VERBOSE",
" printf(\"state match on 1st dfs stack\\n\");",
@@ -1717,17 +2856,17 @@
"#endif",
" }",
" now._a_t = o_a_t;", /* restore */
- " j1 = oj1;",
+ " j1_spin = oj1;",
" }",
"#endif",
" if (II == 3 && a_cycles && (now._a_t&1))",
" {",
"#ifndef NOFAIR",
- " if (fairness && now._cnt[1] > 1) /* was != 0 */",
+ " if (fairness && now._cnt[1] != 1) /* was > 1 */",
" {",
- "#ifdef VERBOSE",
+ " #ifdef CHECK",
" printf(\"\tfairness count non-zero\\n\");",
- "#endif",
+ " #endif",
" II = 0;", /* treat as new state */
" } else",
"#endif",
@@ -1741,6 +2880,11 @@
"#else",
" uerror(\"acceptance cycle\");",
"#endif",
+ "#if NCORE>1 && defined(FULL_TRAIL)",
+ " if (upto > 0)",
+ " { Pop_Stack_Tree();",
+ " }",
+ "#endif",
" goto Up;",
" }",
" }",
@@ -1747,41 +2891,103 @@
"#endif",
"#ifndef NOREDUCE",
- "#ifndef SAFETY",
+ " #ifndef SAFETY",
+ " #if NCORE>1 && !defined(SEP_STATE) && defined(V_PROVISO)",
+ " if (II != 0 && (!Lstate || Lstate->cpu_id < core_id))",
+ " { (trpt-1)->tau |= 16;", /* treat as a stack state */
+ " }",
+ " #endif",
" if ((II && JJ) || (II == 3))",
" { /* marker for liveness proviso */",
- " (trpt-1)->tau |= 16;",
+ " #ifndef LOOPSTATE",
+ " (trpt-1)->tau |= 16;", /* truncated on stack */
+ " #endif",
" truncs2++;",
" }",
"#else",
+ " #if NCORE>1 && !defined(SEP_STATE) && defined(V_PROVISO)",
+ " if (!(II != 0 && (!Lstate || Lstate->cpu_id < core_id)))",
+ " { /* treat as stack state */",
+ " (trpt-1)->tau |= 16;",
+ " } else",
+ " { /* treat as non-stack state */",
+ " (trpt-1)->tau |= 64;",
+ " }",
+ " #endif",
" if (!II || !JJ)",
" { /* successor outside stack */",
" (trpt-1)->tau |= 64;",
" }",
- "#endif",
+ " #endif",
"#endif",
+ "#if defined(BCS) && (defined(NOREDUCE) || !defined(SAFETY))",
+ /* needed for BCS - cover cases where it would not otherwise be set */
+ " if (!II || !JJ)",
+ " { (trpt-1)->tau |= 64;",
+ " }",
+ "#endif",
" if (II)",
" { truncs++;",
+ "#if NCORE>1 && defined(FULL_TRAIL)",
+ " if (upto > 0)",
+ " { Pop_Stack_Tree();",
+ " if (depth == 0)",
+ " { return;",
+ " } }",
+ "#endif",
" goto Up;",
" }",
" if (!kk)",
- " { nstates++;",
- " if ((unsigned long) nstates%%1000000 == 0)",
- " snapshot();",
+ " { static long sdone = (long) 0; long ndone;",
+ " nstates++;",
+ "#if defined(ZAPH) && defined(BITSTATE)",
+ " zstates += (double) hfns;",
+ "#endif",
+ " ndone = (ulong) (nstates/(freq));",
+ " if (ndone != sdone)",
+ " { snapshot();",
+ " sdone = ndone;",
+ "#if defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(MA)",
+ " if (nstates > ((double)(ONE_L<<(ssize+1))))",
+ " { void resize_hashtable(void);",
+ " resize_hashtable();",
+ " }",
+ "#endif",
+ "#if defined(ZAPH) && defined(BITSTATE)",
+ " if (zstates > ((double)(ONE_L<<(ssize-2))))",
+ " { /* more than half the bits set */",
+ " void zap_hashtable(void);",
+ " zap_hashtable();",
+ " zstates = 0;",
+ " }",
+ "#endif",
+ " }",
"#ifdef SVDUMP",
" if (vprefix > 0)",
+ " #ifdef SHO", /* Store Hash Only */
+ " /* always use the same hashfunction, for consistency across runs */",
+ " if (HASH_NR != 0)",
+ " { int oh = HASH_NR;",
+ " HASH_NR = 0;",
+ " d_hash((uchar *) &now, vsize); /* SHO - set K1 */",
+ " HASH_NR = oh;",
+ " }",
+ " if (write(svfd, (uchar *) &K1, sizeof(ulong)) != sizeof(ulong))",
+ " #else",
" if (write(svfd, (uchar *) &now, vprefix) != vprefix)",
- " { fprintf(efd, \"writing %%s.svd failed\\n\", Source);",
+ " #endif",
+ " { fprintf(efd, \"writing %%s.svd failed\\n\", PanSource);",
" wrapup();",
" }",
"#endif",
"#if defined(MA) && defined(W_XPT)",
- " if ((unsigned long) nstates%%W_XPT == 0)",
+ " if ((ulong) nstates%%W_XPT == 0)",
" { void w_xpoint(void);",
" w_xpoint();",
" }",
"#endif",
" }",
+
"#if defined(FULLSTACK) || defined(CNTRSTACK)",
" onstack_put();",
"#ifdef DEBUG2",
@@ -1793,10 +2999,13 @@
" printf(\"%%d: putting\\n\", depth);",
"#endif",
"#endif",
+ "#else",
+ " #if NCORE>1",
+ " trpt->ostate = Lstate;",
+ " #endif",
"#endif",
" } }",
-
" if (depth > mreached)",
" mreached = depth;",
"#ifdef VERI",
@@ -1809,40 +3018,56 @@
"#endif",
"#ifdef VERI",
" if (now._nr_pr == 0) /* claim terminated */",
- " uerror(\"end state in claim reached\");",
- " check_claim(((P0 *)pptr(0))->_p);",
+ " { uerror(\"end state in claim reached\");",
+ " }",
+ " if (stopstate[((Pclaim *)pptr(0))->_t][((Pclaim *)pptr(0))->_p])",
+ " { uerror(\"end state in claim reached\");",
+ " }",
"Stutter:",
" if (trpt->tau&4) /* must make a claimmove */",
" {",
-
- "#ifndef NOFAIR",
+ " #ifndef NOFAIR",
" if ((now._a_t&2) /* A-bit set */",
" && now._cnt[now._a_t&1] == 1)",
" { now._a_t &= ~2;",
" now._cnt[now._a_t&1] = 0;",
" trpt->o_pm |= 16;",
- "#ifdef DEBUG",
+ "#ifdef DEBUG",
" printf(\"%%3d: fairness Rule 3.: _a_t = %%d\\n\",",
- " depth, now._a_t);",
- "#endif",
+ " (int) depth, now._a_t);",
+ "#endif",
" }",
- "#endif",
-
+ " #endif",
" II = 0; /* never */",
" goto Veri0;",
" }",
"#endif",
+ "#ifdef PERMUTED",
+ " if (reversing&2)",
+ " { seed = rand();",
+ " p_reorder(seed);",
+ " }",
+ "#endif",
"#ifndef NOREDUCE",
" /* Look for a process with only safe transitions */",
" /* (special rules apply in the 2nd dfs) */",
-"#ifdef SAFETY",
- " if (boq == -1 && From != To)",
-"#else",
- "/* implied: #ifdef FULLSTACK */",
" if (boq == -1 && From != To",
+ "",
+ "#ifdef SAFETY",
+ " #if NCORE>1",
+ " && (depth < z_handoff)", /* not for border states */
+ " #endif",
+ " )",
+ "#else",
+ " #if NCORE>1",
+ " && ((a_cycles) || (!a_cycles && depth < z_handoff))",
+ " #endif",
+ " #ifdef BCS",
+ " && (sched_max > 0 || depth > BASE)", /* no po in initial state if -L0 */
+ " #endif",
" && (!(now._a_t&1)",
" || (a_cycles &&",
- "#ifndef BITSTATE",
+ " #ifndef BITSTATE",
"#ifdef MA",
"#ifdef VERI",
" !((trpt-1)->proviso))",
@@ -1852,12 +3077,12 @@
"#else",
"#ifdef VERI",
" (trpt-1)->ostate &&",
- " !(((char *)&((trpt-1)->ostate->state))[0] & 128))",
+ " !(((char *)&((trpt-1)->ostate->state))[0] & 128))", /* proviso bit in _a_t */
"#else",
" !(((char *)&(trpt->ostate->state))[0] & 128))",
"#endif",
"#endif",
- "#else",
+ " #else",
"#ifdef VERI",
" (trpt-1)->ostate &&",
" (trpt-1)->ostate->proviso == 0)",
@@ -1864,51 +3089,46 @@
"#else",
" trpt->ostate->proviso == 0)",
"#endif",
- "#endif",
+ " #endif",
" ))",
- "/* #endif */",
-"#endif",
- " for (II = From; II >= To; II -= 1)",
- " {",
- "Resume: /* pick up here if preselect fails */",
- " this = pptr(II);",
- " tt = (int) ((P0 *)this)->_p;",
- " ot = (uchar) ((P0 *)this)->_t;",
- " if (trans[ot][tt]->atom & 8)",
- " { t = trans[ot][tt];",
- " if (t->qu[0] != 0)",
- " { Ccheck++;",
- " if (!q_cond(II, t))",
- " continue;",
- " Cholds++;",
- " }",
- " From = To = II;",
+ "#endif", /* SAFETY */
+ " /* attempt Partial Order Reduction as preselect moves */",
+ "#ifdef BCS",
+ " if (trpt->sched_limit < sched_max)", /* po only if we can switch */
+ "#endif",
+ " { for ALL_P {", /* PO preselect */
+ "Resume: /* pick up here if preselect fails */",
+ " this = pptr(II);",
+ " tt = (int) ((P0 *)this)->_p;",
+ " ot = (uchar) ((P0 *)this)->_t;",
+ " if (trans[ot][tt]->atom & 8)",
+ " { t = trans[ot][tt];",
+ " if (t->qu[0] != 0)",
+ " { Ccheck++;",
+ " if (!q_cond(II, t))",
+ " { continue;",
+ " }",
+ " Cholds++;",
+ " }",
+ " From = To = II; /* preselect process */",
"#ifdef NIBIS",
- " t->om = 0;",
+ " t->om = 0;",
"#endif",
- " trpt->tau |= 32; /* preselect marker */",
- "#ifdef DEBUG",
- "#ifdef NIBIS",
- " printf(\"%%3d: proc %%d Pre\", depth, II);",
- " printf(\"Selected (om=%%d, tau=%%d)\\n\", ",
- " t->om, trpt->tau);",
- "#else",
- " printf(\"%%3d: proc %%d PreSelected (tau=%%d)\\n\", ",
- " depth, II, trpt->tau);",
- "#endif",
- "#endif",
- " goto Again;",
- " }",
- " }",
+ " trpt->tau |= 32; /* preselect marker */",
+ "#ifdef DEBUG",
+ " printf(\"%%3ld: proc %%d PreSelected (tau=%%d)\\n\", ",
+ " depth, II, trpt->tau);",
+ "#endif",
+ " goto Again;",
+ " } else",
+ " { continue;",
+ " } } }",
" trpt->tau &= ~32;",
"#endif",
"#if !defined(NOREDUCE) || (defined(ETIM) && !defined(VERI))",
"Again:",
"#endif",
- " /* The Main Expansion Loop over Processes */",
-
- " trpt->o_pm &= ~(8|16|32|64); /* fairness-marks */",
-
+ " trpt->o_pm &= ~(8|16|32|64); /* clear fairness-marks */",
"#ifndef NOFAIR",
" if (fairness && boq == -1",
"#ifdef VERI",
@@ -1917,36 +3137,136 @@
" && !(trpt->tau&8))",
" { /* A_bit = 1; Cnt = N in acc states with A_bit 0 */",
" if (!(now._a_t&2))", /* A-bit not set */
- " {",
- " if (a_cycles && (trpt->o_pm&2))",
+ " { if (a_cycles && (trpt->o_pm&2))",
" { /* Accepting state */",
" now._a_t |= 2;",
- " now._cnt[now._a_t&1] = now._nr_pr + 1;", /* NEW +1 */
+ " now._cnt[now._a_t&1] = now._nr_pr + 1;",
" trpt->o_pm |= 8;",
"#ifdef DEBUG",
- " printf(\"%%3d: fairness Rule 1: cnt=%%d, _a_t=%%d\\n\",",
+ " printf(\"%%3ld: fairness Rule 1: cnt=%%d, _a_t=%%d\\n\",",
" depth, now._cnt[now._a_t&1], now._a_t);",
"#endif",
" }",
" } else", /* A-bit set */
" { /* A_bit = 0 when Cnt 0 */",
- " if (now._cnt[now._a_t&1] == 1)", /* NEW: 1 iso 0 */
- " { now._a_t &= ~2;", /* reset a-bit */
- " now._cnt[now._a_t&1] = 0;", /* NEW: reset cnt */
+ " if (now._cnt[now._a_t&1] == 1)",
+ " { now._a_t &= ~2;", /* reset a-bit */
+ " now._cnt[now._a_t&1] = 0;",
" trpt->o_pm |= 16;",
"#ifdef DEBUG",
- " printf(\"%%3d: fairness Rule 3: _a_t = %%d\\n\",",
+ " printf(\"%%3ld: fairness Rule 3: _a_t = %%d\\n\",",
" depth, now._a_t);",
"#endif",
" } } }",
"#endif",
- " for (II = From; II >= To; II -= 1)",
- " {",
+ "#ifdef BCS", /* bounded context switching */
+ " trpt->bcs = trpt->b_pno = 0; /* initial */",
+ " if (From != To /* not a PO or atomic move */",
+ " && depth > BASE) /* there is a prior move */",
+ " { trpt->b_pno = now._last + BASE;",
+ " trpt->bcs = B_PHASE1;",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: BCS phase 1 proc %%d limit %%d\\n\",",
+ " depth, trpt->b_pno, trpt->sched_limit);",
+ " #endif",
+ " /* allow only process b_pno to move in this phase */",
+ " }",
+ "c_switch: /* jumps here with bcs == B_PHASE2 with or wo B_FORCED added */",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: BCS c_switch phase=%%d pno=%%d [forced %%d]\\n\",",
+ " depth, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);",
+ " #endif",
+ "#endif",
+
+ "#ifdef P_RAND",
+ " trpt->p_left = CNT_P;",
+ " if (trpt->p_left > 1)",
+ " { trpt->p_skip = rand() %% (trpt->p_left);",
+ " } else",
+ " { trpt->p_skip = -1;",
+ " }",
+ "r_switch:",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: P_RAND r_switch p_skip=%%d p_left=%%d\\n\",",
+ " depth, trpt->p_skip, trpt->p_left);",
+ " #endif",
+ "#endif",
+
+ " for ALL_P {", /* Main Loop */
+ "#ifdef PERMUTED",
+ " if (reversing&2)",
+ " { oII = II;",
+ " if (From != To)", /* not atomic or preselected */
+ " { II = get_permuted(II);",
+ " } }",
+ "#endif",
+ "#ifdef P_RAND",
+ " if (trpt->p_skip >= 0)",
+ " { trpt->p_skip--; /* skip random nr of procs */",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: P_RAND skipping %%d [new p_skip=%%d p_left=%%d]\\n\",",
+ " depth, II, trpt->p_skip, trpt->p_left);",
+ " #endif",
+ " CONTINUE0;",
+ " }",
+ " if (trpt->p_left == 0)",
+ " {",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: P_RAND done at %%d\\n\", depth, II);",
+ " #endif",
+ " break; /* done */",
+ " }",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: P_RAND explore %%d [p_left=%%d]\\n\",",
+ " depth, II, trpt->p_left);",
+ " #endif",
+ " trpt->p_left--;",
+ "#endif",
+
"#if SYNC",
" /* no rendezvous with same proc */",
- " if (boq != -1 && trpt->pr == II) continue;",
+ " if (boq != -1 && trpt->pr == II)",
+ " { CONTINUE0;",
+ " }",
"#endif",
+
+ "#ifdef BCS", /* never claim with II==0 cannot get here */
+ " if ((trpt->bcs & B_PHASE1)",
+ " && trpt->b_pno != II)",
+ " {",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: BCS NotPre II=%%d bcs=%%d pno=%%d [forced %%d]\\n\",",
+ " depth, II, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);",
+ " #endif",
+ " CONTINUE0;", /* avoid context switch */
+ " }",
+ " #ifdef VERBOSE",
+ " else if ((trpt->bcs & B_PHASE1) && trpt->b_pno == II)",
+ " printf(\"%%3ld: BCS IsPre II=%%d bcs=%%d pno=%%d [forced %%d]\\n\",",
+ " depth, II, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);",
+ " #endif",
+
+ " if (trpt->bcs & B_PHASE2) /* 2nd phase */",
+ " { if (trpt->b_pno == II) /* was already done in phase 1 */",
+ " {",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: BCS NoRepeat II=%%d bcs=%%d pno=%%d [forced %%d]\\n\",",
+ " depth, II, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);",
+ " #endif",
+ " CONTINUE0;",
+ " }",
+ " if (!(trpt->bcs & B_FORCED) /* unless forced */",
+ " && trpt->sched_limit >= sched_max)",
+ " {",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: BCS Bound II=%%d bcs=%%d pno=%%d [forced %%d]\\n\",",
+ " depth, II, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);",
+ " #endif",
+ " CONTINUE0; /* enforce bound */",
+ " } }",
+ "#endif",
+
"#ifdef VERI",
"Veri0:",
"#endif",
@@ -1967,8 +3287,10 @@
" { if (t->qu[0] == 0", /* unconditional */
" || q_cond(II, t))", /* true condition */
" { _m = t->om;",
- " if (_m>_n||(_n>3&&_m!=0)) _n=_m;",
- " continue; /* did it before */",
+ " if (_m>_n||(_n>3&&_m!=0))",
+ " { _n=_m;",
+ " }",
+ " CONTINUE0; /* did it before */",
" } }",
"#endif",
" trpt->o_pm &= ~1; /* no move in this pid yet */",
@@ -1990,7 +3312,7 @@
" now._cnt[now._a_t&1] = 1;",
"#endif",
"#ifdef DEBUG",
- " printf(\"%%3d: proc %%d fairness \", depth, II);",
+ " printf(\"%%3ld: proc %%d fairness \", depth, II);",
" printf(\"Rule 2: --cnt to %%d (%%d)\\n\",",
" now._cnt[now._a_t&1], now._a_t);",
"#endif",
@@ -1997,9 +3319,19 @@
" trpt->o_pm |= (32|64);",
" }",
"#endif",
- "#ifdef HAS_PROVIDED",
- " if (!provided(II, ot, tt, t)) continue;",
+
+ "#ifdef HAS_PRIORITY",
+ " if (!highest_priority(((P0 *)this)->_pid, II, t))",
+ " { CONTINUE0;",
+ " }",
+ "#else",
+ " #ifdef HAS_PROVIDED",
+ " if (!provided(II, ot, tt, t))",
+ " { CONTINUE0;",
+ " }",
+ " #endif",
"#endif",
+
" /* check all trans of proc II - escapes first */",
"#ifdef HAS_UNLESS",
" trpt->e_state = 0;",
@@ -2007,27 +3339,31 @@
" (trpt+1)->pr = (uchar) II;", /* for uerror */
" (trpt+1)->st = tt;",
- "#ifdef RANDOMIZE",
+ "#ifdef T_RAND",
" for (ooi = eoi = 0, t = trans[ot][tt]; t; t = t->nxt, ooi++)",
- " if (strcmp(t->tp, \"else\") == 0)",
- " eoi++;",
- "",
- " if (eoi)",
+ " { if (strcmp(t->tp, \"else\") == 0",
+ " #ifdef HAS_UNLESS",
+ " || t->e_trans != 0",
+ " #endif",
+ " )",
+ " { eoi++;", /* no break, must count ooi */
+ " } }",
+ " if (eoi > 0)",
" { t = trans[ot][tt];",
- "#ifdef VERBOSE",
- " printf(\"randomizer: suppressed, saw else\\n\");",
- "#endif",
- " } else",
+ " #ifdef VERBOSE",
+ " printf(\"randomizer: suppressed, saw else or escape\\n\");",
+ " #endif",
+ " } else if (ooi > 0)",
" { eoi = rand()%%ooi;",
- "#ifdef VERBOSE",
+ " #ifdef VERBOSE",
" printf(\"randomizer: skip %%d in %%d\\n\", eoi, ooi);",
- "#endif",
+ " #endif",
" for (t = trans[ot][tt]; t; t = t->nxt)",
" if (eoi-- <= 0) break;",
" }",
- "DOMORE:",
+ "domore:",
" for ( ; t && ooi > 0; t = t->nxt, ooi--)",
- "#else",
+ "#else", /* ie dont randomize */
" for (t = trans[ot][tt]; t; t = t->nxt)",
"#endif",
" {",
@@ -2045,50 +3381,84 @@
" break;",
" }",
"#endif",
+ " #if defined(TRIX) && !defined(TRIX_ORIG) && !defined(BFS)",
+ " (trpt+1)->p_bup = now._ids_[II];",
+ " #endif",
" (trpt+1)->o_t = t;", /* for uerror */
"#ifdef INLINE",
"#include FORWARD_MOVES",
"P999: /* jumps here when move succeeds */",
"#else",
- " if (!(_m = do_transit(t, II))) continue;",
+ " if (!(_m = do_transit(t, II)))",
+ " { continue;",
+ " }",
"#endif",
+ "#ifdef BCS",
+ " if (depth > BASE", /* has prior move */
+ " && II >= BASE", /* not claim */
+ " && From != To", /* not atomic or po */
+ " #ifndef BCS_NOFIX",
+ " /* added 5.2.5: prior move was not po */",
+ " && !((trpt-(BASE+1))->tau & 32)",
+ " #endif",
+ " && boq == -1", /* not rv */
+ " && (trpt->bcs & B_PHASE2)",
+ " && trpt->b_pno != II /* context switch */", /* redundant */
+ " && !(trpt->bcs & B_FORCED)) /* unless forced */",
+ " { (trpt+1)->sched_limit = 1 + trpt->sched_limit;",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: up sched count to %%d\\n\", depth, (trpt+1)->sched_limit);",
+ " #endif",
+ " } else",
+ " { (trpt+1)->sched_limit = trpt->sched_limit;",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: keep sched count at %%d\\n\", depth, (trpt+1)->sched_limit);",
+ " #endif",
+ " }",
+ "#endif",
" if (boq == -1)",
-"#ifdef CTL",
+ "#ifdef CTL",
" /* for branching-time, can accept reduction only if */",
" /* the persistent set contains just 1 transition */",
" { if ((trpt->tau&32) && (trpt->o_pm&1))",
- " trpt->tau |= 16;",
+ " trpt->tau |= 16;", /* CTL */
" trpt->o_pm |= 1; /* we moved */",
" }",
-"#else",
+ "#else",
" trpt->o_pm |= 1; /* we moved */",
-"#endif",
+ "#endif",
+
+ "#ifdef LOOPSTATE",
+ " if (loopstate[ot][tt])",
+ " {",
+ "#ifdef VERBOSE",
+ " printf(\"exiting from loopstate:\\n\");",
+ "#endif",
+ " trpt->tau |= 16;", /* exiting loopstate */
+ " cnt_loops++;",
+ " }",
+ "#endif",
+
"#ifdef PEG",
" peg[t->forw]++;",
"#endif",
-
"#if defined(VERBOSE) || defined(CHECK)",
"#if defined(SVDUMP)",
- " printf(\"%%3d: proc %%d exec %%d \\n\", ",
- " depth, II, t->t_id);",
+ " cpu_printf(\"%%3ld: proc %%d exec %%d \\n\", depth, II, t->t_id);",
"#else",
- " printf(\"%%3d: proc %%d exec %%d, \", ",
- " depth, II, t->forw);",
- " printf(\"%%d to %%d, %%s %%s %%s\", ",
- " tt, t->st, t->tp,",
+ " cpu_printf(\"%%3ld: proc %%d exec %%d, %%d to %%d, %%s %%s %%s %%saccepting [tau=%%d]\\n\", ",
+ " depth, II, t->forw, tt, t->st, t->tp,",
" (t->atom&2)?\"atomic\":\"\",",
- " (boq != -1)?\"rendez-vous\":\"\");",
- "#ifdef HAS_UNLESS",
- " if (t->e_trans)",
- " printf(\" (escapes to state %%d)\",",
- " t->st);",
- "#endif",
- " printf(\" %%saccepting [tau=%%d]\\n\",",
+ " (boq != -1)?\"rendez-vous\":\"\",",
" (trpt->o_pm&2)?\"\":\"non-\", trpt->tau);",
+ "#ifdef HAS_UNLESS",
+ " if (t->e_trans)",
+ " cpu_printf(\"\\t(escape to state %%d)\\n\", t->st);",
"#endif",
- "#ifdef RANDOMIZE",
- " printf(\" randomizer %%d\\n\", ooi);",
"#endif",
+ "#ifdef T_RAND",
+ " cpu_printf(\"\\t(randomizer %%d)\\n\", ooi);",
+ "#endif",
"#endif",
"#ifdef HAS_LAST",
@@ -2143,9 +3513,16 @@
" trpt->o_ot = ot; trpt->o_tt = tt;",
" trpt->o_To = To; trpt->o_m = _m;",
" trpt->tau = 0;",
-"#ifdef RANDOMIZE",
+ "#ifdef PERMUTED",
+ " if (reversing&2)",
+ " { trpt->seed = seed;",
+ " trpt->oII = oII;",
+ " }",
+ "#endif",
+
+ "#if defined(T_RAND) && !defined(BFS)",
" trpt->oo_i = ooi;",
-"#endif",
+ "#endif",
" if (boq != -1 || (t->atom&2))",
" { trpt->tau |= 8;",
"#ifdef VERI",
@@ -2171,32 +3548,78 @@
" if (boq == -1 && (t->atom&2))",
" { From = To = II; nlinks++;",
" } else",
- " { From = now._nr_pr-1; To = BASE;",
+ " { From = FROM_P; To = UPTO_P;",
" }",
+ "#if NCORE>1 && defined(FULL_TRAIL)",
+ " if (upto > 0)",
+ " { Push_Stack_Tree(II, t->t_id);",
+ " }",
+ "#endif",
+ "#ifdef TRIX",
+ " if (processes[II])", /* last move could have been a delproc */
+ " { processes[II]->modified = 1; /* transition in II */",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: process %%d modified\\n\", depth, II);",
+ " } else",
+ " { printf(\"%%4d: process %%d modified but gone (%%p)\\n\",",
+ " depth, II, trpt);",
+ " #endif",
+ " }",
+ "#endif",
" goto Down; /* pseudo-recursion */",
"Up:",
+ "#ifdef TRIX",
+ " #ifndef TRIX_ORIG",
+ " #ifndef BFS",
+ " now._ids_[trpt->pr] = trpt->p_bup;",
+ " #endif",
+ " #else",
+ " if (processes[trpt->pr])",
+ " {",
+ " processes[trpt->pr]->modified = 1; /* reverse move */",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: unmodify pr %%d (%%p)\\n\",",
+ " depth, trpt->pr, trpt);",
+ " } else",
+ " { printf(\"%%4d: unmodify pr %%d (gone) (%%p)\\n\",",
+ " depth, trpt->pr, trpt);",
+ " #endif",
+ " }",
+ " #endif",
+ "#endif",
"#ifdef CHECK",
- " printf(\"%%d: Up - %%s\\n\", depth,",
- " (trpt->tau&4)?\"claim\":\"program\");",
+ " cpu_printf(\"%%d: Up - %%s\\n\", depth,",
+ " (trpt->tau&4)?\"claim\":\"program\");",
"#endif",
- "#ifdef MA",
- " if (depth <= 0) return;",
- " /* e.g., if first state is old, after a restart */",
+ "#if NCORE>1",
+ " iam_alive();",
+ " #ifdef USE_DISK",
+ " mem_drain();",
+ " #endif",
"#endif",
+ "#if defined(MA) || NCORE>1",
+ " if (depth <= 0) return;",
+ " /* e.g., if first state is old, after a restart */",
+ "#endif",
"#ifdef SC",
- " if (CNT1 > CNT2",
- " && depth < hiwater - (HHH-DDD) + 2)",
- " {",
- " trpt += DDD;",
- " disk2stack();",
- " maxdepth -= DDD;",
- " hiwater -= DDD;",
- "if(verbose)",
- "printf(\"unzap %%d: %%d\\n\", CNT2, hiwater);",
- " }",
+ " if (CNT1 > CNT2",
+ " && depth < hiwater - (HHH-DDD) - 2)", /* 5.1.6: was + 2 */
+ " {",
+ " trpt += DDD;",
+ " disk2stack();",
+ " maxdepth -= DDD;",
+ " hiwater -= DDD;",
+ " if(verbose)",
+ " printf(\"unzap %%ld: %%ld\\n\", CNT2, hiwater);",
+ " }",
"#endif",
+ "#ifndef SAFETY", /* moved earlier in version 5.2.5 */
+ " if ((now._a_t&1) && depth <= A_depth)",
+ " return; /* to checkcycles() */",
+ "#endif",
+
"#ifndef NOFAIR",
" if (trpt->o_pm&128) /* fairness alg */",
" { now._cnt[now._a_t&1] = trpt->bup.oval;",
@@ -2203,7 +3626,7 @@
" _n = 1; trpt->o_pm &= ~128;",
" depth--; trpt--;",
"#if defined(VERBOSE) || defined(CHECK)",
- " printf(\"%%3d: reversed fairness default move\\n\", depth);",
+ " printf(\"%%3ld: reversed fairness default move\\n\", depth);",
"#endif",
" goto Q999;",
" }",
@@ -2211,7 +3634,7 @@
"#ifdef HAS_LAST",
"#ifdef VERI",
- " { int d; Trail *trl;",
+ " { long d; Trail *trl;",
" now._last = 0;",
" for (d = 1; d < depth; d++)",
" { trl = getframe(depth-d); /* was (trpt-d) */",
@@ -2226,45 +3649,56 @@
"#ifdef EVENT_TRACE",
" now._event = trpt->o_event;",
"#endif",
- "#ifndef SAFETY",
- " if ((now._a_t&1) && depth <= A_depth)",
- " return; /* to checkcycles() */",
- "#endif",
" t = trpt->o_t; _n = trpt->o_n;",
" ot = trpt->o_ot; II = trpt->pr;",
- " tt = trpt->o_tt; this = pptr(II);",
+ " tt = trpt->o_tt; this = Pptr(II);",
" To = trpt->o_To; _m = trpt->o_m;",
-"#ifdef RANDOMIZE",
+ "#ifdef PERMUTED",
+ " if (reversing&2)",
+ " { seed = trpt->seed;",
+ " oII = trpt->oII;",
+ " }",
+ "#endif",
+ "#if defined(T_RAND) && !defined(BFS)",
" ooi = trpt->oo_i;",
-"#endif",
+ "#endif",
"#ifdef INLINE_REV",
" _m = do_reverse(t, II, _m);",
"#else",
- "#include REVERSE_MOVES",
+ "#include BACKWARD_MOVES",
"R999: /* jumps here when done */",
"#endif",
"#ifdef VERBOSE",
- " printf(\"%%3d: proc %%d \", depth, II);",
- " printf(\"reverses %%d, %%d to %%d,\",",
- " t->forw, tt, t->st);",
- " printf(\" %%s [abit=%%d,adepth=%%d,\", ",
- " t->tp, now._a_t, A_depth);",
- " printf(\"tau=%%d,%%d]\\n\", ",
- " trpt->tau, (trpt-1)->tau);",
+ " cpu_printf(\"%%3ld: proc %%d reverses %%d, %%d to %%d\\n\",",
+ " depth, II, t->forw, tt, t->st);",
+ " cpu_printf(\"\\t%%s [abit=%%d,adepth=%%ld,tau=%%d,%%d]\\n\", ",
+ " t->tp, now._a_t, A_depth, trpt->tau, (trpt-1)->tau);",
"#endif",
"#ifndef NOREDUCE",
" /* pass the proviso tags */",
" if ((trpt->tau&8) /* rv or atomic */",
" && (trpt->tau&16))",
- " (trpt-1)->tau |= 16;",
- "#ifdef SAFETY",
+ " (trpt-1)->tau |= 16;", /* pass upward */
+ " #ifdef SAFETY",
" if ((trpt->tau&8) /* rv or atomic */",
" && (trpt->tau&64))",
" (trpt-1)->tau |= 64;",
+ " #endif",
"#endif",
+
+ "#if defined(BCS) && (defined(NOREDUCE) || !defined(SAFETY))",
+ /* for BCS, cover cases where 64 is otherwise not handled */
+ " if ((trpt->tau&8)",
+ " && (trpt->tau&64))",
+ " (trpt-1)->tau |= 64;",
"#endif",
+
" depth--; trpt--;",
+ "",
+ "#ifdef NSUCC",
+ " trpt->n_succ++;",
+ "#endif",
"#ifdef NIBIS",
" (trans[ot][tt])->om = _m; /* head of list */",
"#endif",
@@ -2271,16 +3705,7 @@
" /* i.e., not set if rv fails */",
" if (_m)",
- " {",
- "#if defined(VERI) && !defined(NP)",
- " if (II == 0 && verbose && !reached[ot][t->st])",
- " {",
- " printf(\"depth %%d: Claim reached state %%d (line %%d)\\n\",",
- " depth, t->st, src_claim [t->st]);",
- " fflush(stdout);",
- " }",
- "#endif",
- " reached[ot][t->st] = 1;",
+ " { reached[ot][t->st] = 1;",
" reached[ot][tt] = 1;",
" }",
"#ifdef HAS_UNLESS",
@@ -2291,19 +3716,19 @@
" ((P0 *)this)->_p = tt;",
" } /* all options */",
- "#ifdef RANDOMIZE",
+ "#ifdef T_RAND",
" if (!t && ooi > 0)", /* means we skipped some initial options */
" { t = trans[ot][tt];",
- "#ifdef VERBOSE",
+ " #ifdef VERBOSE",
" printf(\"randomizer: continue for %%d more\\n\", ooi);",
- "#endif",
- " goto DOMORE;",
+ " #endif",
+ " goto domore;",
" }",
- "#ifdef VERBOSE",
+ " #ifdef VERBOSE",
" else",
" printf(\"randomizer: done\\n\");",
+ " #endif",
"#endif",
- "#endif",
"#ifndef NOFAIR",
" /* Fairness: undo Rule 2 */",
@@ -2312,12 +3737,12 @@
" { if (trpt->o_pm&1)",/* it didn't block */
" {",
"#ifdef VERI",
- " if (now._cnt[now._a_t&1] == 1)", /* NEW: 1 iso 0 */
- " now._cnt[now._a_t&1] = 2;", /* NEW: 2 iso 1*/
+ " if (now._cnt[now._a_t&1] == 1)",
+ " now._cnt[now._a_t&1] = 2;",
"#endif",
" now._cnt[now._a_t&1] += 1;",
"#ifdef VERBOSE",
- " printf(\"%%3d: proc %%d fairness \", depth, II);",
+ " printf(\"%%3ld: proc %%d fairness \", depth, II);",
" printf(\"undo Rule 2, cnt=%%d, _a_t=%%d\\n\",",
" now._cnt[now._a_t&1], now._a_t);",
"#endif",
@@ -2326,32 +3751,77 @@
" { if (_n > 0)", /* a prev proc didn't */
" {", /* start over */
" trpt->o_pm &= ~64;",
- " II = From+1;",
+ " II = INI_P;", /* after loop incr II == From */
" } } }",
"#endif",
-
"#ifdef VERI",
- " if (II == 0) break; /* never claim */",
+ " if (II == 0)",
+ " { break; /* never claim */",
+ " }",
"#endif",
- " } /* all processes */",
+ " CONTINUE;",
+ " } /* ALL_P */",
+ "#ifdef NSUCC",
+ " tally_succ(trpt->n_succ);",
+ "#endif",
+
+ "#ifdef P_RAND",
+ " if (trpt->p_left > 0 && NDONE_P)",
+ " { trpt->p_skip = -1; /* probably rendundant */",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: P_RAND -- explore remainder\\n\", depth);",
+ " #endif",
+ " goto r_switch; /* explore the remaining procs */",
+ " } else",
+ " {",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: P_RAND -- none left\\n\", depth);",
+ " #endif",
+ " }",
+ "#endif",
+
+ "#ifdef BCS",
+ " if (trpt->bcs & B_PHASE1)",
+ " { trpt->bcs = B_PHASE2; /* start 2nd phase */",
+ " if (_n == 0 || !(trpt->tau&64)) /* pre-move unexecutable or led to stackstate */",
+ " { trpt->bcs |= B_FORCED; /* forced switch */",
+ " }",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: BCS move to phase 2, _n=%%d %%s\\n\", depth, _n,",
+ " (trpt->bcs & B_FORCED)?\"forced\":\"free\");",
+ " #endif",
+ " From = FROM_P; To = UPTO_P;",
+ " goto c_switch;",
+ " }",
+ "",
+ " if (_n == 0 /* no process could move */",
+ " && II >= BASE /* not the never claim */",
+ " && trpt->sched_limit >= sched_max)",
+ " { _n = 1;",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: BCS not a deadlock\\n\", depth);",
+ " #endif",
+ " }",
+ "#endif",
+
"#ifndef NOFAIR",
" /* Fairness: undo Rule 2 */",
" if (trpt->o_pm&32) /* remains if proc blocked */",
" {",
"#ifdef VERI",
- " if (now._cnt[now._a_t&1] == 1)", /* NEW: 1 iso 0 */
- " now._cnt[now._a_t&1] = 2;", /* NEW: 2 iso 1 */
+ " if (now._cnt[now._a_t&1] == 1)",
+ " now._cnt[now._a_t&1] = 2;",
"#endif",
" now._cnt[now._a_t&1] += 1;",
"#ifdef VERBOSE",
- " printf(\"%%3d: proc -- fairness \", depth);",
+ " printf(\"%%3ld: proc -- fairness \", depth);",
" printf(\"undo Rule 2, cnt=%%d, _a_t=%%d\\n\",",
" now._cnt[now._a_t&1], now._a_t);",
"#endif",
" trpt->o_pm &= ~32;",
" }",
-"#ifndef NP",
+ "#ifndef NP",
/* 12/97 non-progress cycles cannot be created
* by stuttering extension, here or elsewhere
*/
@@ -2361,12 +3831,8 @@
" && !(trpt->tau&4) /* in program move */",
"#endif",
" && !(trpt->tau&8) /* not an atomic one */",
- "#ifdef OTIM",
- " && ((trpt->tau&1) || endstate())",
- "#else",
- "#ifdef ETIM",
- " && (trpt->tau&1) /* already tried timeout */",
- "#endif",
+ "#ifdef ETIM",
+ " && (trpt->tau&1) /* already tried timeout */",
"#endif",
"#ifndef NOREDUCE",
" /* see below */",
@@ -2382,14 +3848,14 @@
"#else",
" trpt->tau = 0;",
"#endif",
- " From = now._nr_pr-1; To = BASE;",
+ " From = FROM_P; To = UPTO_P;",
"#if defined(VERBOSE) || defined(CHECK)",
- " printf(\"%%3d: fairness default move \", depth);",
+ " printf(\"%%3ld: fairness default move \", depth);",
" printf(\"(all procs block)\\n\");",
"#endif",
" goto Down;",
" }",
-"#endif",
+ "#endif",
"Q999: /* returns here with _n>0 when done */;",
" if (trpt->o_pm&8)",
@@ -2397,7 +3863,7 @@
" now._cnt[now._a_t&1] = 0;",
" trpt->o_pm &= ~8;",
"#ifdef VERBOSE",
- " printf(\"%%3d: fairness undo Rule 1, _a_t=%%d\\n\",",
+ " printf(\"%%3ld: fairness undo Rule 1, _a_t=%%d\\n\",",
" depth, now._a_t);",
"#endif",
" }",
@@ -2406,7 +3872,7 @@
" now._cnt[now._a_t&1] = 1;", /* NEW: restore cnt */
" trpt->o_pm &= ~16;",
"#ifdef VERBOSE",
- " printf(\"%%3d: fairness undo Rule 3, _a_t=%%d\\n\",",
+ " printf(\"%%3ld: fairness undo Rule 3, _a_t=%%d\\n\",",
" depth, now._a_t);",
"#endif",
" }",
@@ -2414,35 +3880,41 @@
"#ifndef NOREDUCE",
"#ifdef SAFETY",
- " /* preselected move - no successors outside stack */",
- " if ((trpt->tau&32) && !(trpt->tau&64))",
- " { From = now._nr_pr-1; To = BASE;",
- "#ifdef DEBUG",
- " printf(\"%%3d: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
- " depth, II+1, _n, trpt->tau);",
- "#endif",
+ " #ifdef LOOPSTATE",
+ " /* at least one move that was preselected at this */",
+ " /* level, blocked or was a loop control flow point */",
+ " if ((trpt->tau&32) && (_n == 0 || (trpt->tau&16)))",
+ " #else",
+ " /* preselected move - no successors outside stack */",
+ " if ((trpt->tau&32) && !(trpt->tau&64))",
+ " #endif",
+ " { From = FROM_P; To = UPTO_P; /* undo From == To */",
+ " #ifdef DEBUG",
+ " printf(\"%%3ld: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
+ " depth, II+1, _n, trpt->tau);",
+ " #endif",
" _n = 0; trpt->tau &= ~(16|32|64);",
- " if (II >= BASE) /* II already decremented */",
- " goto Resume;",
- " else",
- " goto Again;",
- " }",
+
+ " if (MORE_P) /* II already restored and updated */",
+ " { goto Resume;",
+ " } else",
+ " { goto Again;",
+ " } }",
"#else",
" /* at least one move that was preselected at this */",
" /* level, blocked or truncated at the next level */",
- "/* implied: #ifdef FULLSTACK */",
" if ((trpt->tau&32) && (_n == 0 || (trpt->tau&16)))",
" {",
- "#ifdef DEBUG",
- " printf(\"%%3d: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
- " depth, II+1, (int) _n, trpt->tau);",
- "#endif",
+ " #ifdef DEBUG",
+ " printf(\"%%3ld: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
+ " depth, II+1, (int) _n, trpt->tau);",
+ " #endif",
" if (a_cycles && (trpt->tau&16))",
" { if (!(now._a_t&1))",
" {",
- "#ifdef DEBUG",
- " printf(\"%%3d: setting proviso bit\\n\", depth);",
- "#endif",
+ " #ifdef DEBUG",
+ " printf(\"%%3ld: setting proviso bit\\n\", depth);",
+ " #endif",
"#ifndef BITSTATE",
"#ifdef MA",
"#ifdef VERI",
@@ -2466,19 +3938,18 @@
" trpt->ostate->proviso = 1;",
"#endif",
"#endif",
- " From = now._nr_pr-1; To = BASE;",
+ " From = FROM_P; To = UPTO_P;",
" _n = 0; trpt->tau &= ~(16|32|64);",
" goto Again; /* do full search */",
" } /* else accept reduction */",
" } else",
- " { From = now._nr_pr-1; To = BASE;",
+ " { From = FROM_P; To = UPTO_P;",
" _n = 0; trpt->tau &= ~(16|32|64);",
- " if (II >= BASE) /* already decremented */",
- " goto Resume;",
- " else",
- " goto Again;",
- " } }",
- "/* #endif */",
+ " if (MORE_P) /* II already updated */",
+ " { goto Resume;",
+ " } else",
+ " { goto Again;",
+ " } } }",
"#endif",
"#endif",
@@ -2485,8 +3956,8 @@
" if (_n == 0 || ((trpt->tau&4) && (trpt->tau&2)))",
" {",
"#ifdef DEBUG",
- " printf(\"%%3d: no move [II=%%d, tau=%%d, boq=%%d]\\n\",",
- " depth, II, trpt->tau, boq);",
+ " cpu_printf(\"%%3ld: no move [II=%%d, tau=%%d, boq=%%d]\\n\",",
+ " depth, II, trpt->tau, boq);",
"#endif",
"#if SYNC",
" /* ok if a rendez-vous fails: */",
@@ -2494,18 +3965,14 @@
"#endif",
" /* ok if no procs or we're at maxdepth */",
" if ((now._nr_pr == 0 && (!strict || qs_empty()))",
- "#ifdef OTIM",
- " || endstate()",
- "#endif",
- " || depth >= maxdepth-1) goto Done;",
+ " || depth >= maxdepth-1) goto Done; /* undo change from 5.2.3 */",
" if ((trpt->tau&8) && !(trpt->tau&4))",
" { trpt->tau &= ~(1|8);",
" /* 1=timeout, 8=atomic */",
- " From = now._nr_pr-1; To = BASE;",
+ " From = FROM_P; To = UPTO_P;",
"#ifdef DEBUG",
- " printf(\"%%3d: atomic step proc %%d \", depth, II+1);",
- " printf(\"unexecutable\\n\");",
+ " cpu_printf(\"%%3ld: atomic step proc %%d unexecutable\\n\", depth, II+1);",
"#endif",
"#ifdef VERI",
" trpt->tau |= 4; /* switch to claim */",
@@ -2524,9 +3991,9 @@
"#endif",
" { trpt->tau |= 1;",
" trpt->tau &= ~2;",
- "#ifdef DEBUG",
- " printf(\"%%d: timeout\\n\", depth);",
- "#endif",
+ " #ifdef DEBUG",
+ " cpu_printf(\"%%d: timeout\\n\", depth);",
+ " #endif",
" goto Stutter;",
" } }",
" else",
@@ -2534,18 +4001,22 @@
" if ((trpt->tau&8)",
" && !((trpt-1)->tau&4))",
"/* blocks inside an atomic */ goto BreakOut;",
- "#ifdef DEBUG",
- " printf(\"%%d: req timeout\\n\",",
+ " #ifdef DEBUG",
+ " cpu_printf(\"%%d: req timeout\\n\",",
" depth);",
- "#endif",
+ " #endif",
" (trpt-1)->tau |= 2; /* request */",
+ " #if NCORE>1 && defined(FULL_TRAIL)",
+ " if (upto > 0)",
+ " { Pop_Stack_Tree();",
+ " }",
+ " #endif",
" goto Up;",
" }",
"#else",
-
- "#ifdef DEBUG",
- " printf(\"%%d: timeout\\n\", depth);",
- "#endif",
+ " #ifdef DEBUG",
+ " cpu_printf(\"%%d: timeout\\n\", depth);",
+ " #endif",
" trpt->tau |= 1;",
" goto Again;",
"#endif",
@@ -2560,7 +4031,7 @@
" { trpt->tau |= 4; /* claim stuttering */",
" trpt->tau |= 128; /* stutter mark */",
"#ifdef DEBUG",
- " printf(\"%%d: claim stutter\\n\", depth);",
+ " cpu_printf(\"%%d: claim stutter\\n\", depth);",
"#endif",
" goto Stutter;",
" }",
@@ -2585,6 +4056,47 @@
"Done:",
" if (!(trpt->tau&8)) /* not in atomic seqs */",
" {",
+
+"#ifndef MA",
+ "#if defined(FULLSTACK) || defined(CNTRSTACK)",
+ "#ifdef VERI",
+ " if (boq == -1",
+ " && (((trpt->tau&4) && !(trpt->tau&128))",
+ " || ( (trpt-1)->tau&128)))",
+ "#else",
+ " if (boq == -1)",
+ "#endif",
+ " {",
+ "#ifdef DEBUG2",
+ "#if defined(FULLSTACK)",
+ " printf(\"%%ld: zapping %%u (%%d)\\n\",",
+ " depth, trpt->ostate,",
+ " (trpt->ostate)?trpt->ostate->tagged:0);",
+ "#endif",
+ "#endif",
+ " onstack_zap();",
+ " }",
+ "#endif",
+"#else",
+ "#ifdef VERI",
+ " if (boq == -1",
+ " && (((trpt->tau&4) && !(trpt->tau&128))",
+ " || ( (trpt-1)->tau&128)))",
+ "#else",
+ " if (boq == -1)",
+ "#endif",
+ " {",
+ "#ifdef DEBUG",
+ " printf(\"%%ld: zapping\\n\", depth);",
+ "#endif",
+ " onstack_zap();",
+ "#ifndef NOREDUCE",
+ " if (trpt->proviso)",
+ " g_store((char *) &now, vsize, 1);",
+ "#endif",
+ " }",
+"#endif",
+
"#ifndef SAFETY",
" if (_n != 0", /* we made a move */
"#ifdef VERI",
@@ -2601,7 +4113,7 @@
" if (fairness)", /* implies a_cycles */
" {",
"#ifdef VERBOSE",
- " printf(\"Consider check %%d %%d...\\n\",",
+ " cpu_printf(\"Consider check %%d %%d...\\n\",",
" now._a_t, now._cnt[0]);",
"#endif",
#if 0
@@ -2624,47 +4136,16 @@
" checkcycles();",
" }",
"#endif",
-"#ifndef MA",
- "#if defined(FULLSTACK) || defined(CNTRSTACK)",
- "#ifdef VERI",
- " if (boq == -1",
- " && (((trpt->tau&4) && !(trpt->tau&128))",
- " || ( (trpt-1)->tau&128)))",
- "#else",
- " if (boq == -1)",
- "#endif",
- " {",
- "#ifdef DEBUG2",
- "#if defined(FULLSTACK)",
- " printf(\"%%d: zapping %%u (%%d)\\n\",",
- " depth, trpt->ostate,",
- " (trpt->ostate)?trpt->ostate->tagged:0);",
- "#endif",
- "#endif",
- " onstack_zap();",
+ " }",
+ " if (depth > 0)",
+ " {",
+ "#if NCORE>1 && defined(FULL_TRAIL)",
+ " if (upto > 0)",
+ " { Pop_Stack_Tree();",
" }",
"#endif",
-"#else",
- "#ifdef VERI",
- " if (boq == -1",
- " && (((trpt->tau&4) && !(trpt->tau&128))",
- " || ( (trpt-1)->tau&128)))",
- "#else",
- " if (boq == -1)",
- "#endif",
- " {",
- "#ifdef DEBUG",
- " printf(\"%%d: zapping\\n\", depth);",
- "#endif",
- " onstack_zap();",
- "#ifndef NOREDUCE",
- " if (trpt->proviso)",
- " gstore((char *) &now, vsize, 1);",
- "#endif",
- " }",
-"#endif",
+ " goto Up;",
" }",
- " if (depth > 0) goto Up;",
"}\n",
"#else",
"void new_state(void) { /* place holder */ }",
@@ -2671,7 +4152,7 @@
"#endif", /* BFS */
"",
"void",
- "assert(int a, char *s, int ii, int tt, Trans *t)",
+ "spin_assert(int a, char *s, int ii, int tt, Trans *t)",
"{",
" if (!a && !noasserts)",
" { char bad[1024];",
@@ -2688,169 +4169,214 @@
"int",
"Boundcheck(int x, int y, int a1, int a2, Trans *a3)",
"{",
- " assert((x >= 0 && x < y), \"- invalid array index\",",
+ " spin_assert((x >= 0 && x < y), \"- invalid array index\",",
" a1, a2, a3);",
" return x;",
"}",
"#endif",
+ "int do_hashgen = 0;",
"void",
"wrap_stats(void)",
"{",
" if (nShadow>0)",
- " printf(\"%%8g states, stored (%%g visited)\\n\",",
+ " printf(\"%%9.8g states, stored (%%g visited)\\n\",",
" nstates - nShadow, nstates);",
" else",
- " printf(\"%%8g states, stored\\n\", nstates);",
+ " printf(\"%%9.8g states, stored\\n\", nstates);",
+ "#ifdef BFS_PAR",
+ " if (bfs_punt > 0)",
+ " printf(\"%%9.8g states lost (lack of queue memory)\\n\", (double) bfs_punt);",
+ "#endif",
"#ifdef BFS",
- "#if SYNC",
+ " #if SYNC",
" printf(\" %%8g nominal states (- rv and atomic)\\n\", nstates-midrv-nlinks+revrv);",
" printf(\" %%8g rvs succeeded\\n\", midrv-failedrv);",
- "#else",
+ " #else",
" printf(\" %%8g nominal states (stored-atomic)\\n\", nstates-nlinks);",
- "#endif",
- "#ifdef DEBUG",
+ " #endif",
+ " #ifdef DEBUG",
" printf(\" %%8g midrv\\n\", midrv);",
" printf(\" %%8g failedrv\\n\", failedrv);",
" printf(\" %%8g revrv\\n\", revrv);",
+ " #endif",
"#endif",
- "#endif",
- " printf(\"%%8g states, matched\\n\", truncs);",
+ " printf(\"%%9.8g states, matched\\n\", truncs);",
"#ifdef CHECK",
- " printf(\"%%8g matches within stack\\n\",truncs2);",
+ " printf(\"%%9.8g matches within stack\\n\",truncs2);",
"#endif",
" if (nShadow>0)",
- " printf(\"%%8g transitions (= visited+matched)\\n\",",
+ " printf(\"%%9.8g transitions (= visited+matched)\\n\",",
" nstates+truncs);",
" else",
- " printf(\"%%8g transitions (= stored+matched)\\n\",",
+ " printf(\"%%9.8g transitions (= stored+matched)\\n\",",
" nstates+truncs);",
- " printf(\"%%8g atomic steps\\n\", nlinks);",
+ " printf(\"%%9.8g atomic steps\\n\", nlinks);",
" if (nlost) printf(\"%%g lost messages\\n\", (double) nlost);",
"",
"#ifndef BITSTATE",
- " printf(\"hash conflicts: %%g (resolved)\\n\", hcmp);",
+ " #ifndef MA",
+ " printf(\"hash conflicts: %%9.8g (resolved)\\n\", hcmp);",
+ " #if !defined(AUTO_RESIZE) && !defined(BFS_PAR)",
+ " if (hcmp > (double) (1<<ssize))",
+ " { printf(\"hint: increase hashtable-size (-w) to reduce runtime\\n\");",
+ " }",
+ " #endif",
+ " #if defined(BFS_PAR) && defined(HC)",
+ " { double fp = (100. * (double) nstates)/((double) ((ulong) (1<<ssize)));",
+ " int fi = 0;",
+ " printf(\"the hash table is %%3.3g %%%% filled\", fp);",
+ " if (fp > 1.0)",
+ " { fp = 100. / fp;",
+ " while (fp > 2.) { fi++; fp /= 2.; }",
+ " if (fi > 0)",
+ " { printf(\" (hint: rerun with -w%%d to reduce runtime)\",",
+ " ssize-fi);",
+ " } }",
+ " printf(\"\\n\");",
+ " }",
+ " #endif",
+ " #endif",
"#else",
"#ifdef CHECK",
" printf(\"%%8g states allocated for dfs stack\\n\", ngrabs);",
"#endif",
- " printf(\"\\nhash factor: %%4g (best if > 100.)\\n\\n\",",
- " (double)(1<<(ssize-8)) / (double) nstates * 256.0);",
- " printf(\"bits set per state: %%u (-k%%u)\\n\", hfns, hfns);",
- "#if 0",
-#ifndef POWOW
" if (udmem)",
- " printf(\"total bits available: %%8g (-M%%ld)\\n\",",
- " ((double) udmem) * 8.0, udmem/(1024L*1024L));",
+ " printf(\"\\nhash factor: %%4g (best if > 100.)\\n\\n\",",
+ " (double)(((double) udmem) * 8.0) / (double) nstates);",
" else",
-#endif
- " printf(\"total bits available: %%8g (-w%%d)\\n\",",
- " ((double) (1L << (ssize-4)) * 16.0), ssize);",
+ " printf(\"\\nhash factor: %%4g (best if > 100.)\\n\\n\",",
+ " ((double)(((ulong)1)<<(ssize-10)) / (double) nstates) * 1024.0);",
+ /* the -10 and *1024 stuff is to avoid overflow */
+ " printf(\"bits set per state: %%u (-k%%u)\\n\", hfns, hfns);",
+ " if (do_hashgen)",
+ " printf(\"hash polynomial used: 0x%%.8x\\n\", HASH_CONST[HASH_NR]);",
+ " if (s_rand != 12345)",
+ " printf(\"random seed used: %%u\\n\", (uint) (s_rand-1));",
"#endif",
-"#ifdef COVEST",
- " /* this code requires compilation with -lm on some systems */",
- " { double pow(double, double);",
- " double log(double);",
- " unsigned int best_k;",
- " double i, n = 30000.0L;",
- " double f, p, q, m, c, est = 0.0L, k = (double)hfns;",
- " c = (double) nstates / n;",
- " m = (double) (1<<(ssize-8)) * 256.0L / c;",
- " p = 1.0L - (k / m); q = 1.0L;",
- " for (i = 0.0L; i - est < n; i += 1.0L)",
- " { q *= p;",
- " est += pow(1.0L - q, k);",
- " }",
- " f = m/i;",
- " est *= c;",
- " i *= c;",
- " /* account for loss from enhanced double hashing */",
- " if (hfns > 2) est += i * pow(0.5, (double) ssize * 2.0);",
- "",
- " if (f < 1.134) best_k = 1;",
- " else if (f < 2.348) best_k = 2;",
- " else if (f < 3.644) best_k = 3;",
- " else best_k = (unsigned int) (pow(3.8L,1.0L/(f+4.2L))*f*.69315L + 0.99999999L);",
- "",
- " if (best_k != hfns && best_k > ssize)",
- " best_k = (unsigned int) 1.0 + ssize/log((double)best_k / (double)ssize + 3.0);",
- "",
- " if (best_k > 32)",
- " best_k = 1 + (unsigned int) (32.0/log((double)best_k/35.0));",
- "",
- " if (est * (double) nstates < 1.0)",
- " { printf(\"prob. of omissions: negligible\\n\");",
- " return; /* no hints needed */",
- " }",
- "",
- " if (best_k != hfns)",
- " { printf(\"hint: repeating the search with -k%%u \", best_k);",
- " printf(\"may increase accuracy\\n\");",
- " } else",
- " { printf(\"hint: the current setting for -k (-k%%d) \", hfns);",
- " printf(\"is likely to be optimal for -w%%d\\n\", ssize);",
- " }",
- " if (ssize < 32)",
- " { printf(\"hint: increasing -w above -w%%d \", ssize);",
- " printf(\"will increase accuracy (max is -w34)\\n\");",
- " printf(\"(in xspin, increase Estimated State Space Size)\\n\");",
- " } }",
-"#endif",
+ "#if defined(BFS_DISK) && !defined(BFS_PAR)",
+ " printf(\"bfs disk reads: %%ld writes %%ld -- diff %%ld\\n\",",
+ " bfs_dsk_reads, bfs_dsk_writes, bfs_dsk_writes-bfs_dsk_reads);",
+ " if (bfs_dsk_read >= 0) (void) close(bfs_dsk_read);",
+ " if (bfs_dsk_write >= 0) (void) close(bfs_dsk_write);",
+ " (void) unlink(\"pan_bfs_dsk.tmp\");",
"#endif",
"}",
+ "",
"void",
"wrapup(void)",
- "{",
- "#if defined(BITSTATE) || !defined(NOCOMP)",
- " double nr1, nr2, nr3 = 0.0, nr4, nr5 = 0.0;",
- "#if !defined(MA) && (defined(MEMCNT) || defined(MEMLIM))",
- " int mverbose = 1;",
- "#else",
- " int mverbose = verbose;",
+ "{ double nr1, nr2, nr3 = 0.0, nr4, nr5 = 0.0;",
+ "#ifdef BFS_PAR",
+ " if (who_am_i != 0)",
+ " { pan_exit(0);",
+ " }",
"#endif",
+ "#if NCORE>1",
+ " if (verbose) cpu_printf(\"wrapup -- %%d error(s)\\n\", errors);",
+ " if (core_id != 0)",
+ " {",
+ " #ifdef USE_DISK",
+ " void dsk_stats(void);",
+ " dsk_stats();",
+ " #endif",
+ " if (search_terminated != NULL)",
+ " { *search_terminated |= 2; /* wrapup */",
+ " }",
+ " exit(0); /* normal termination, not an error */",
+ " }",
"#endif",
-
+ "#if !defined(WIN32) && !defined(WIN64)",
" signal(SIGINT, SIG_DFL);",
- " printf(\"(%%s)\\n\", Version);",
+ "#endif",
+ " printf(\"\\n(%%s)\\n\", SpinVersion);",
" if (!done) printf(\"Warning: Search not completed\\n\");",
+ "#if defined(BFS_PAR) && !defined(BITSTATE)",
+ " if (bfs_punt > 0) printf(\"Warning: Search incomplete\\n\");",
+ "#endif",
"#ifdef SC",
" (void) unlink((const char *)stackfile);",
"#endif",
+ "#ifdef BFS_PAR",
+ " printf(\" + Multi-Core (using %%d cores)\\n\", Cores);",
+ " #ifdef BFS_SEP_HASH",
+ " printf(\" + Separate Hash Tables\\n\");",
+ " #endif",
+ " #ifdef BFS_DISK",
+ " printf(\" + Disk storage\\n\");",
+ " #endif",
+ "#endif",
+ "#if NCORE>1",
+ " if (a_cycles)",
+ " { printf(\" + Multi-Core (NCORE=%%d)\\n\", NCORE);",
+ " } else",
+ " { printf(\" + Multi-Core (NCORE=%%d -z%%ld)\\n\", NCORE, z_handoff);",
+ " }",
+ "#endif",
"#ifdef BFS",
- " printf(\" + Using Breadth-First Search\\n\");",
+ " printf(\" + Breadth-First Search\\n\");",
"#endif",
"#ifndef NOREDUCE",
" printf(\" + Partial Order Reduction\\n\");",
"#endif",
-#if 0
- "#ifdef Q_PROVISO",
- " printf(\" + Queue Proviso\\n\");",
+ "#ifdef PERMUTED",
+ " printf(\" + Process Scheduling Permutation\\n\");",
"#endif",
-#endif
+ "#ifdef P_REVERSE",
+ " printf(\" + Reverse Depth-First Search Order\\n\");",
+ "#endif",
+ " if (t_reverse)",
+ " printf(\" + Reverse Transition Ordering\\n\");",
+ "#ifdef T_RAND",
+ " printf(\" + Randomized Transition Ordering\\n\");",
+ "#endif",
+ "#ifdef P_RAND",
+ " printf(\" + Randomized Process Ordering\\n\");",
+ "#endif",
+ "#ifdef BCS",
+ " printf(\" + Scheduling Restriction (-L%%d)\\n\", sched_max);",
+ "#endif",
+ "#ifdef TRIX",
+ " printf(\" + Tree Index Compression\\n\");",
+ "#endif",
"#ifdef COLLAPSE",
" printf(\" + Compression\\n\");",
"#endif",
"#ifdef MA",
" printf(\" + Graph Encoding (-DMA=%%d)\\n\", MA);",
- "#ifdef R_XPT",
- " printf(\" Restarted from checkpoint %%s.xpt\\n\", Source);",
+ " #ifdef R_XPT",
+ " printf(\" Restarted from checkpoint %%s.xpt\\n\", PanSource);",
+ " #endif",
"#endif",
- "#endif",
"#ifdef CHECK",
- "#ifdef FULLSTACK",
+ " #ifdef FULLSTACK",
" printf(\" + FullStack Matching\\n\");",
- "#endif",
- "#ifdef CNTRSTACK",
+ " #endif",
+ " #ifdef CNTRSTACK",
" printf(\" + CntrStack Matching\\n\");",
- "#endif",
+ " #endif",
"#endif",
+ "#ifdef PERMUTED",
+ " if (reversing & 2)",
+ " { if (p_reorder == set_permuted)",
+ " { printf(\" + Permuted\\n\");",
+ " }",
+ " if (p_reorder == set_reversed)",
+ " { printf(\" + Reversed\\n\");",
+ " }",
+ " if (p_reorder == set_rotated)",
+ " { printf(\" + Rotated %%d\\n\", p_rotate);",
+ " }",
+ " if (p_reorder == set_randrot)",
+ " { printf(\" + RandRotated\\n\");",
+ " } }",
+ "#endif",
"#ifdef BITSTATE",
" printf(\"\\nBit statespace search for:\\n\");",
"#else",
- "#ifdef HC",
+ " #ifdef HC",
" printf(\"\\nHash-Compact %%d search for:\\n\", HC);",
- "#else",
+ " #else",
" printf(\"\\nFull statespace search for:\\n\");",
- "#endif",
+ " #endif",
"#endif",
"#ifdef EVENT_TRACE",
"#ifdef NEGATED_TRACE",
@@ -2860,7 +4386,8 @@
"#endif",
"#endif",
"#ifdef VERI",
- " printf(\"\tnever claim \t+\\n\");",
+ " printf(\"\tnever claim \t+\");",
+ " printf(\" (%%s)\\n\", procname[((Pclaim *)pptr(0))->_t]);",
" printf(\"\tassertion violations\t\");",
" if (noasserts)",
" printf(\"- (disabled by -A flag)\\n\");",
@@ -2889,7 +4416,11 @@
" fairness?\"en\":\"dis\");",
" else printf(\"- (not selected)\\n\");",
"#else",
+ " #if !defined(BFS_PAR) || !defined(L_BOUND)",
" printf(\"\tcycle checks \t- (disabled by -DSAFETY)\\n\");",
+ " #else",
+ " printf(\"\tcycle checks \t+ (bound %%d)\\n\", L_bound);",
+ " #endif",
"#endif",
"#ifdef VERI",
" printf(\"\tinvalid end states\t- \");",
@@ -2905,9 +4436,13 @@
" else",
" printf(\"+\\n\\n\");",
"#endif",
- " printf(\"State-vector %%d byte, depth reached %%d\", ",
- " hmax, mreached);",
+ " printf(\"State-vector %%d byte, depth reached %%ld\", hmax,",
+ "#if NCORE>1",
+ " (nr_handoffs * z_handoff) +",
+ "#endif",
+ " mreached);",
" printf(\", errors: %%d\\n\", errors);",
+ " fflush(stdout);",
"#ifdef MA",
" if (done)",
" { extern void dfa_stats(void);",
@@ -2920,124 +4455,196 @@
" wrap_stats();",
"#ifdef CHECK",
" printf(\"stackframes: %%d/%%d\\n\\n\", smax, svmax);",
- " printf(\"stats: fa %%d, fh %%d, zh %%d, zn %%d - \",",
+ " printf(\"stats: fa %%ld, fh %%ld, zh %%ld, zn %%ld - \",",
" Fa, Fh, Zh, Zn);",
- " printf(\"check %%d holds %%d\\n\", Ccheck, Cholds);",
- " printf(\"stack stats: puts %%d, probes %%d, zaps %%d\\n\",",
+ " printf(\"check %%ld holds %%ld\\n\", Ccheck, Cholds);",
+ " printf(\"stack stats: puts %%ld, probes %%ld, zaps %%ld\\n\",",
" PUT, PROBE, ZAPS);",
"#else",
" printf(\"\\n\");",
"#endif",
"",
- "#if defined(BITSTATE) || !defined(NOCOMP)",
+ "#if !defined(BITSTATE) && defined(NOCOMP)",
+ " if (!verbose) { goto jump_here; }", /* added 5.2.0 */
+ "#endif",
+ "",
+ "#if 1", /* omitted 5.2.0: defined(BITSTATE) || !defined(NOCOMP) */
" nr1 = (nstates-nShadow)*",
- " (double)(hmax+sizeof(struct H_el)-sizeof(unsigned));",
- "#ifdef BFS",
+ " (double)(hmax+sizeof(H_el)-sizeof(unsigned));",
+ " #ifdef BFS",
" nr2 = 0.0;",
- "#else",
+ " #else",
" nr2 = (double) ((maxdepth+3)*sizeof(Trail));",
- "#endif",
+ " #endif",
- "#ifndef BITSTATE",
+ " #ifndef BITSTATE",
"#if !defined(MA) || defined(COLLAPSE)",
- " nr3 = (double) (1L<<ssize)*sizeof(struct H_el *);",
+ " nr3 = (double) (ONE_L<<ssize)*sizeof(H_el *);",
"#endif",
- "#else",
-#ifndef POWOW
+ " #else",
" if (udmem)",
" nr3 = (double) (udmem);",
" else",
-#endif
- " nr3 = (double) (1L<<(ssize-3));",
+ " nr3 = (double) (ONE_L<<(ssize-3));",
"#ifdef CNTRSTACK",
- " nr3 += (double) (1L<<(ssize-3));",
+ " nr5 = (double) (ONE_L<<(ssize-3));",
"#endif",
"#ifdef FULLSTACK",
- " nr5 = (double) (maxdepth*sizeof(struct H_el *));",
+ " nr5 = (double) (maxdepth*sizeof(H_el *));",
"#endif",
- "#endif",
+ " #endif",
+
" nr4 = (double) (svmax * (sizeof(Svtack) + hmax))",
- " + (double) (smax * (sizeof(Stack) + Maxbody));",
+ " + (double) (smax * (sizeof(_Stack) + Maxbody * sizeof(char)));",
"#ifndef MA",
- " if (mverbose || memcnt < nr1+nr2+nr3+nr4+nr5)",
+ " if (1 /* verbose || memcnt < nr1+nr2+nr3+nr4+nr5 */)",
"#endif",
" { double remainder = memcnt;",
" double tmp_nr = memcnt-nr3-nr4-(nr2-fragment)-nr5;",
+ "",
+ " #if NCORE>1 && !defined(SEP_STATE)",
+ " tmp_nr -= ((double) NCORE * LWQ_SIZE) + GWQ_SIZE;",
+ " #endif",
" if (tmp_nr < 0.0) tmp_nr = 0.;",
" printf(\"Stats on memory usage (in Megabytes):\\n\");",
- " printf(\"%%-6.3f\tequivalent memory usage for states\",",
- " nr1/1000000.);",
+ " printf(\"%%9.3f\tequivalent memory usage for states\",",
+ " nr1/1048576.); /* 1024*1024=1048576 */",
" printf(\" (stored*(State-vector + overhead))\\n\");",
- "#ifdef BITSTATE",
-#ifndef POWOW
+ " #if NCORE>1 && !defined(WIN32) && !defined(WIN64)",
+ " printf(\"%%9.3f\tshared memory reserved for state storage\\n\",",
+ " mem_reserved/1048576.);",
+ " #ifdef SEP_HEAP",
+ " printf(\"\t\tin %%d local heaps of %%7.3f MB each\\n\",",
+ " NCORE, mem_reserved/(NCORE*1048576.));",
+ " #endif",
+ " printf(\"\\n\");",
+ " #endif",
+ " #ifdef BITSTATE",
" if (udmem)",
- " printf(\"%%-6.3f\tmemory used for hash array (-M%%ld)\\n\",",
- " nr3/1000000., udmem/(1024L*1024L));",
+ " printf(\"%%9.3f\tmemory used for hash array (-M%%ld)\\n\",",
+ " nr3/1048576., udmem/(1024L*1024L));",
" else",
-#endif
- " printf(\"%%-6.3f\tmemory used for hash array (-w%%d)\\n\",",
- " nr3/1000000., ssize);",
+ " printf(\"%%9.3f\tmemory used for hash array (-w%%d)\\n\",",
+ " nr3/1048576., ssize);",
" if (nr5 > 0.0)",
- " printf(\"%%-6.3f\tmemory used for bit stack\\n\",",
- " nr5/1000000.);",
+ " printf(\"%%9.3f\tmemory used for bit stack\\n\",",
+ " nr5/1048576.);",
" remainder = remainder - nr3 - nr5;",
- "#else",
- " printf(\"%%-6.3f\tactual memory usage for states\",",
- " tmp_nr/1000000.);",
- " remainder = remainder - tmp_nr;",
- " printf(\" (\");",
- " if (tmp_nr > 0.)",
- " { if (tmp_nr > nr1) printf(\"unsuccessful \");",
- " printf(\"compression: %%.2f%%%%)\\n\",",
- " (100.0*tmp_nr)/nr1);",
- " } else",
- " printf(\"less than 1k)\\n\");",
- "#ifndef MA",
- " if (tmp_nr > 0.)",
- " { printf(\"\tState-vector as stored = %%.0f byte\",",
- " (tmp_nr)/(nstates-nShadow) -",
- " (double) (sizeof(struct H_el) - sizeof(unsigned)));",
- " printf(\" + %%ld byte overhead\\n\",",
- " sizeof(struct H_el)-sizeof(unsigned));",
+ " #else",
+ " #ifndef USE_TDH",
+ " printf(\"%%9.3f\tactual memory usage for states\",",
+ " tmp_nr/1048576.);",
+ " remainder -= tmp_nr;",
+ " if (tmp_nr > 0.)",
+ " { if (tmp_nr < nr1) ",
+ " { printf(\" (compression: %%.2f%%%%)\\n\",",
+ " (100.0*tmp_nr)/nr1);",
+ " } else",
+ " { printf(\"\\n\");",
+ " }",
+ " } else",
+ " { printf(\" (less than 1k)\\n\");",
+ " }",
+ " #ifndef MA",
+ " if (tmp_nr > 0. && tmp_nr < nr1)",
+ " { printf(\" \tstate-vector as stored = %%.0f byte\",",
+ " (tmp_nr)/(nstates-nShadow) -",
+ " (double) (sizeof(H_el) - sizeof(unsigned)));",
+ " printf(\" + %%ld byte overhead\\n\",",
+ " (long int) sizeof(H_el)-sizeof(unsigned));",
+ " }",
+ " #endif",
+ " #endif",
+ " #if !defined(MA) || defined(COLLAPSE)",
+ " #ifdef BFS_PAR",
+ " printf(\"%%9.3f\tshared memory used for hash table (-w%%d)\\n\",",
+ " ((double) bfs_pre_allocated)/1048576., ssize);",
+ " #else",
+ " printf(\"%%9.3f\tmemory used for hash table (-w%%d)\\n\",",
+ " nr3/1048576., ssize);",
+ " remainder -= nr3;",
+ " #endif",
+ " #endif",
+ " #endif",
+ " #ifndef BFS",
+ " printf(\"%%9.3f\tmemory used for DFS stack (-m%%ld)\\n\",",
+ " nr2/1048576., maxdepth);",
+ " remainder -= nr2;",
+ " #endif",
+ " #if NCORE>1",
+ " remainder -= ((double) NCORE * LWQ_SIZE) + GWQ_SIZE;",
+ " printf(\"%%9.3f\tshared memory used for work-queues\\n\",",
+ " (GWQ_SIZE + (double) NCORE * LWQ_SIZE) /1048576.);",
+ " printf(\"\t\tin %%d queues of %%7.3f MB each\",",
+ " NCORE, (double) LWQ_SIZE /1048576.);",
+ " #ifndef NGQ",
+ " printf(\" + a global q of %%7.3f MB\\n\",",
+ " (double) GWQ_SIZE / 1048576.);",
+ " #else",
+ " printf(\"\\n\");",
+ " #endif",
+ " #endif",
+ " if (remainder - fragment > 1048576.)",
+ " { printf(\"%%9.3f\tother (proc and chan stacks)\\n\",",
+ " (remainder-fragment)/1048576.);",
" }",
- "#endif",
- "#if !defined(MA) || defined(COLLAPSE)",
- " printf(\"%%-6.3f\tmemory used for hash table (-w%%d)\\n\",",
- " nr3/1000000., ssize);",
- " remainder = remainder - nr3;",
- "#endif",
- "#endif",
- "#ifndef BFS",
- " printf(\"%%-6.3f\tmemory used for DFS stack (-m%%ld)\\n\",",
- " nr2/1000000., maxdepth);",
- " remainder = remainder - nr2;",
- "#endif",
- " if (remainder - fragment > 0.0)",
- " printf(\"%%-6.3f\tother (proc and chan stacks)\\n\",",
- " (remainder-fragment)/1000000.);",
- " if (fragment > 0.0)",
- " printf(\"%%-6.3f\tmemory lost to fragmentation\\n\",",
- " fragment/1000000.);",
- " printf(\"%%-6.3f\ttotal actual memory usage\\n\\n\",",
- " memcnt/1000000.);",
+ " if (fragment > 1048576.)",
+ " { printf(\"%%9.3f\tmemory lost to fragmentation\\n\",",
+ " fragment/1048576.);",
+ " }",
+ " #ifdef BFS_PAR",
+ " printf(\"%%9.3f\ttotal non-shared memory usage\\n\\n\",",
+ " memcnt/1048576.);",
+ " #else",
+ " printf(\"%%9.3f\ttotal actual memory usage\\n\\n\",",
+ " memcnt/1048576.);",
+ " #endif",
" }",
- "#ifndef MA",
+ " #ifndef MA",
" else",
- "#endif",
+ " #endif",
"#endif",
- "#ifndef MA",
- " printf(\"%%-6.3f\tmemory usage (Mbyte)\\n\\n\",",
- " memcnt/1000000.);",
- "#endif",
+
+ "#if !defined(BITSTATE) && defined(NOCOMP)",
+ "jump_here:",
+ "#endif",
+ "#ifndef MA",
+ " printf(\"%%9.3f\tmemory usage (Mbyte)\\n\",",
+ " memcnt/1048576.);",
+ "#endif",
+ "#ifdef BFS_PAR",
+ " bfs_report_mem();",
+ "#else",
+ " printf(\"\\n\");",
+ "#endif",
"#ifdef COLLAPSE",
- " printf(\"nr of templates: [ globals chans procs ]\\n\");",
+ " printf(\"nr of templates: [ 0:globals 1:chans 2:procs ]\\n\");",
" printf(\"collapse counts: [ \");",
" { int i; for (i = 0; i < 256+2; i++)",
" if (ncomps[i] != 0)",
- " printf(\"%%d \", ncomps[i]);",
+ " printf(\"%%d:%%lu \", i, ncomps[i]);",
" printf(\"]\\n\");",
" }",
"#endif",
+ " #ifdef TRIX",
+ " if (verbose)",
+ " { int i;",
+ " printf(\"TRIX counts:\\n\");",
+ " printf(\" processes: \");",
+ " for (i = 0; i < MAXPROC; i++)",
+ " if (_p_count[i] != 0)",
+ " { printf(\"%%3d:%%ld \",",
+ " i, _p_count[i]);",
+ " }",
+ " printf(\"\\n channels : \");",
+ " for (i = 0; i < MAXQ; i++)",
+ " if (_c_count[i] != 0)",
+ " { printf(\"%%3d:%%ld \",",
+ " i, _c_count[i]);",
+ " }",
+ " printf(\"\\n\\n\");",
+ " }",
+ " #endif",
" if ((done || verbose) && !no_rck) do_reach();",
"#ifdef PEG",
@@ -3053,21 +4660,90 @@
"#ifdef SVDUMP",
" if (vprefix > 0) close(svfd);",
"#endif",
+ "#ifdef LOOPSTATE",
+ " printf(\"%%g loopstates hit\\n\", cnt_loops);",
+ "#endif",
+ "#ifdef NSUCC",
+ " dump_succ();",
+ "#endif",
+ "#if NCORE>1 && defined(T_ALERT)",
+ " crash_report();",
+ "#endif",
+ "#ifndef BFS_PAR",
" pan_exit(0);",
+ "#endif",
"}\n",
"void",
"stopped(int arg)",
- "{ printf(\"Interrupted\\n\");",
+ "{",
+ "#ifdef BFS_PAR",
+ " bfs_shutdown(\"interrupted\");",
+ "#endif",
+ " printf(\"Interrupted\\n\");",
+ "#if NCORE>1",
+ " was_interrupted = 1;",
+ "#endif",
" wrapup();",
" pan_exit(0);",
"}",
+ "",
"/*",
- " * based on Bob Jenkins hash-function from 1996",
- " * see: http://www.burtleburtle.net/bob/",
+ " * super fast hash, based on Paul Hsieh's function",
+ " * http://www.azillionmonkeys.com/qed/hash.html",
" */",
+ "#include <stdint.h>", /* for uint32_t etc */
+ " #undef get16bits",
+ " #if defined(__GNUC__) && defined(__i386__)",
+ " #define get16bits(d) (*((const uint16_t *) (d)))",
+ " #else",
+ " #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\\",
+ " +(uint32_t)(((const uint8_t *)(d))[0]) )",
+ " #endif",
"",
-"#if defined(HASH64) || defined(WIN64)",
- /* 64-bit Jenkins hash: http://burtleburtle.net/bob/c/lookup8.c */
+ "void",
+ "d_sfh(uchar *s, int len)", /* sets one 32-bit number, in K1 */
+ "{ uint32_t h = len, tmp;",
+ " int rem;",
+ "",
+ " rem = len & 3;",
+ " len >>= 2;",
+ "",
+ " for ( ; len > 0; len--)",
+ " { h += get16bits(s);",
+ " tmp = (get16bits(s+2) << 11) ^ h;",
+ " h = (h << 16) ^ tmp;",
+ " s += 2*sizeof(uint16_t);",
+ " h += h >> 11;",
+ " }",
+ " switch (rem) {",
+ " case 3: h += get16bits(s);",
+ " h ^= h << 16;",
+ " h ^= s[sizeof(uint16_t)] << 18;",
+ " h += h >> 11;",
+ " break;",
+ " case 2: h += get16bits(s);",
+ " h ^= h << 11;",
+ " h += h >> 17;",
+ " break;",
+ " case 1: h += *s;",
+ " h ^= h << 10;",
+ " h += h >> 1;",
+ " break;",
+ " }",
+ " h ^= h << 3;",
+ " h += h >> 5;",
+ " h ^= h << 4;",
+ " h += h >> 17;",
+ " h ^= h << 25;",
+ " h += h >> 6;",
+ "",
+ " K1 = h;",
+ "}",
+ "",
+ "#if WS>4",
+ "/* 64-bit Jenkins hash, 1997",
+ " * http://burtleburtle.net/bob/c/lookup8.c",
+ " */",
"#define mix(a,b,c) \\",
"{ a -= b; a -= c; a ^= (c>>43); \\",
" b -= c; b -= a; b ^= (a<<9); \\",
@@ -3082,56 +4758,231 @@
" b -= c; b -= a; b ^= (a<<18); \\",
" c -= a; c -= b; c ^= (b>>22); \\",
"}",
-"#else",
+ "#else",
+ "/* 32-bit Jenkins hash, 2006",
+ " * http://burtleburtle.net/bob/c/lookup3.c",
+ " */",
+ "#define rot(x,k) (((x)<<(k))|((x)>>(32-(k))))",
+ "",
"#define mix(a,b,c) \\",
- "{ a -= b; a -= c; a ^= (c>>13); \\",
- " b -= c; b -= a; b ^= (a<<8); \\",
- " c -= a; c -= b; c ^= (b>>13); \\",
- " a -= b; a -= c; a ^= (c>>12); \\",
- " b -= c; b -= a; b ^= (a<<16); \\",
- " c -= a; c -= b; c ^= (b>>5); \\",
- " a -= b; a -= c; a ^= (c>>3); \\",
- " b -= c; b -= a; b ^= (a<<10); \\",
- " c -= a; c -= b; c ^= (b>>15); \\",
+ "{ a -= c; a ^= rot(c, 4); c += b; \\",
+ " b -= a; b ^= rot(a, 6); a += c; \\",
+ " c -= b; c ^= rot(b, 8); b += a; \\",
+ " a -= c; a ^= rot(c,16); c += b; \\",
+ " b -= a; b ^= rot(a,19); a += c; \\",
+ " c -= b; c ^= rot(b, 4); b += a; \\",
"}",
-"#endif",
- "void",
- "d_hash(uchar *Cp, int Om) /* double bit hash - Jenkins */",
- "{ unsigned long a = 0x9e3779b9, b, c = 0, len, length;",
- " unsigned long *k = (unsigned long *) Cp;",
"",
- " length = len = (unsigned long) ((unsigned long) Om + WS-1)/WS;",
+ "#define final(a,b,c) \\",
+ "{ c ^= b; c -= rot(b,14); \\",
+ " a ^= c; a -= rot(c,11); \\",
+ " b ^= a; b -= rot(a,25); \\",
+ " c ^= b; c -= rot(b,16); \\",
+ " a ^= c; a -= rot(c,4); \\",
+ " b ^= a; b -= rot(a,14); \\",
+ " c ^= b; c -= rot(b,24); \\",
+ "}",
+ "#endif",
"",
+ "void",
+ "d_hash(uchar *kb, int nbytes)", /* sets two 64-bit or 32-bit nrs, depending on WS */
+ "{ uint8_t *bp;",
+ "#if WS>4",
+ " uint64_t a = 0, b, c, n;",
+ " const uint64_t *k = (uint64_t *) kb;",
+ "#else",
+ " uint32_t a = 0, b, c, n;",
+ " const uint32_t *k = (uint32_t *) kb;",
+ "#endif",
+ " n = nbytes/WS; /* nr of words */",
+ " /* extend to multiple of words, if needed */",
+ " a = WS - (nbytes %% WS);",
+ " if (a > 0 && a < WS)",
+ " { n++;",
+ " bp = kb + nbytes;",
+ " switch (a) {",
+ "#if WS>4",
+ " case 7: *bp++ = 0; /* fall thru */",
+ " case 6: *bp++ = 0; /* fall thru */",
+ " case 5: *bp++ = 0; /* fall thru */",
+ " case 4: *bp++ = 0; /* fall thru */",
+ "#endif",
+ " case 3: *bp++ = 0; /* fall thru */",
+ " case 2: *bp++ = 0; /* fall thru */",
+ " case 1: *bp = 0;",
+ " case 0: break;",
+ " } }",
+ "#if WS>4",
" b = HASH_CONST[HASH_NR];",
- " while (len >= 3)",
+ " c = 0x9e3779b97f4a7c13LL; /* arbitrary value */",
+ " while (n >= 3)",
" { a += k[0];",
" b += k[1];",
" c += k[2];",
" mix(a,b,c);",
- " k += 3; len -= 3;",
+ " n -= 3;",
+ " k += 3;",
" }",
- " c += length;",
- " switch (len) {",
+ " c += (((uint64_t) nbytes)<<3);",
+ " switch (n) {",
" case 2: b += k[1];",
" case 1: a += k[0];",
+ " case 0: break;",
" }",
" mix(a,b,c);",
- " j1 = c&nmask; j3 = a&7;", /* 1st bit */
- " j2 = b&nmask; j4 = (a>>3)&7;", /* 2nd bit */
- " K1 = c; K2 = b;", /* no nmask */
+ "#else", /* 32 bit version: */
+ " a = c = 0xdeadbeef + (n<<2);",
+ " b = HASH_CONST[HASH_NR];",
+ " while (n > 3)",
+ " { a += k[0];",
+ " b += k[1];",
+ " c += k[2];",
+ " mix(a,b,c);",
+ " n -= 3;",
+ " k += 3;",
+ " }",
+ " switch (n) { ",
+ " case 3: c += k[2];",
+ " case 2: b += k[1];",
+ " case 1: a += k[0];",
+ " final(a,b,c);",
+ " case 0: break;",
+ " }",
+ "#endif",
+ " j1_spin = c&nmask; j3_spin = a&7; /* 1st bit */",
+ " j2_spin = b&nmask; j4_spin = (a>>3)&7; /* 2nd bit */",
+ " K1 = c; K2 = b;",
"}",
+ "",
+ "#if defined(MURMUR) && (WS==8)",
+ "/* public-domain, 64-bit MurmurHash3, by Austin Appleby */",
+ "/* https://code.google.com/p/smhasher/wiki/MurmurHash3 */",
"void",
- "s_hash(uchar *cp, int om)",
- "{ d_hash(cp, om); /* sets K1 and K2 */",
+ "m_hash(uchar *v, int len)",
+ "{ uint8_t *bp, *data = (uint8_t*) v;",
+ " int i, nblocks = len / 16;",
+ "",
+ " uint64_t h1 = HASH_CONST[HASH_NR];",
+ " uint64_t h2 = 0x9e3779b97f4a7c13LL;",
+ "",
+ " uint64_t c1 = 0x87c37b91114253d5;",
+ " uint64_t c2 = 0x4cf5ad432745937f;",
+ "",
+ " uint64_t *blocks = (uint64_t *)(data);",
+ "",
+ " /* guarantee a multiple of 16 bytes */",
+ " i = 16 - (len %% 16);",
+ " if (i > 0 && i < 16)",
+ " { nblocks++;",
+ " bp = v + len;",
+ " switch (i) {",
+ " case 15: *bp++ = 0; /* fall thru */",
+ " case 14: *bp++ = 0;",
+ " case 13: *bp++ = 0;",
+ " case 12: *bp++ = 0;",
+ " case 11: *bp++ = 0;",
+ " case 10: *bp++ = 0;",
+ " case 9: *bp++ = 0;",
+ " case 8: *bp++ = 0;",
+ " case 7: *bp++ = 0;",
+ " case 6: *bp++ = 0;",
+ " case 5: *bp++ = 0;",
+ " case 4: *bp++ = 0;",
+ " case 3: *bp++ = 0;",
+ " case 2: *bp++ = 0;",
+ " case 1: *bp = 0;",
+ " case 0: break;",
+ " } }",
+ "",
+ " for (i = 0; i < nblocks; i++)",
+ " { uint64_t k1 = blocks[i*2];",
+ " uint64_t k2 = blocks[i*2+1];",
+ "",
+ " k1 *= c1;",
+ " k1 = (k1 << 31) | (k1 >> 33);",
+ " k1 *= c2;",
+ " h1 ^= k1;",
+ "",
+ " h1 = (h1 << 27) | (h1 >> 37);",
+ " h1 += h2;",
+ " h1 = h1 * 5 + 0x52dce729;",
+ "",
+ " k2 *= c2;",
+ " k2 = (k2 << 33) | (k2 >> 31);",
+ " k2 *= c1;",
+ " h2 ^= k2;",
+ "",
+ " h2 = (h2 << 31) | (h2 >> 33);",
+ " h2 += h1;",
+ " h2 = h2 * 5 + 0x38495ab5;",
+ " }",
+ "",
+ " uint8_t *tail = (uint8_t*)(data + (nblocks * 16));",
+ "",
+ " uint64_t k1 = 0;",
+ " uint64_t k2 = 0;",
+ "",
+ " switch(len & 15) {",
+ " case 15: k2 ^= ((uint64_t) tail[14]) << 48; break;",
+ " case 14: k2 ^= ((uint64_t) tail[13]) << 40; break;",
+ " case 13: k2 ^= ((uint64_t) tail[12]) << 32; break;",
+ " case 12: k2 ^= ((uint64_t) tail[11]) << 24; break;",
+ " case 11: k2 ^= ((uint64_t) tail[10]) << 16; break;",
+ " case 10: k2 ^= ((uint64_t) tail[ 9]) << 8; break;",
+ " case 9: k2 ^= ((uint64_t) tail[ 8]) << 0; break;",
+ " k2 *= c2;",
+ " k2 = (k2 << 33) | (k2 >> 31);",
+ " k2 *= c1;",
+ " h2 ^= k2; break;",
+ " case 8: k1 ^= ((uint64_t) tail[7]) << 56; break;",
+ " case 7: k1 ^= ((uint64_t) tail[6]) << 48; break;",
+ " case 6: k1 ^= ((uint64_t) tail[5]) << 40; break;",
+ " case 5: k1 ^= ((uint64_t) tail[4]) << 32; break;",
+ " case 4: k1 ^= ((uint64_t) tail[3]) << 24; break;",
+ " case 3: k1 ^= ((uint64_t) tail[2]) << 16; break;",
+ " case 2: k1 ^= ((uint64_t) tail[1]) << 8; break;",
+ " case 1: k1 ^= ((uint64_t) tail[0]) << 0; break;",
+ " k1 *= c1;",
+ " k1 = (k1 << 31) | (k1 >> 33);",
+ " k1 *= c2;",
+ " h1 ^= k1;",
+ " };",
+ "",
+ " h1 ^= len; h2 ^= len;",
+ " h1 += h2;",
+ " h2 += h1;",
+ " h1 ^= h1 >> 33;",
+ " h1 *= 0xff51afd7ed558ccd;",
+ " h1 ^= h1 >> 33;",
+ " h1 *= 0xc4ceb9fe1a85ec53;",
+ " h1 ^= h1 >> 33;",
+ " h2 ^= h2 >> 33;",
+ " h2 *= 0xff51afd7ed558ccd;",
+ " h2 ^= h2 >> 33;",
+ " h2 *= 0xc4ceb9fe1a85ec53;",
+ " h2 ^= h2 >> 33;",
+ " h1 += h2;",
+ " h2 += h1;",
+ "",
+ " j1_spin = h1&nmask; j3_spin = (h1>>48)&7;",
+ " j2_spin = h2&nmask; j4_spin = (h2>>48)&7;",
+ " K1 = h1; K2 = h2;",
+ "}",
+ "#endif",
+ "",
+ "void",
+ "s_hash(uchar *cp, int om)", /* uses either d_sfh (1x32bit), or d_hash (2x64bit) */
+ "{", /* depending on ssize ie the -w parameter */
+ " hasher(cp, om); /* sets K1 */",
"#ifdef BITSTATE",
" if (S_Tab == H_tab)", /* state stack in bitstate search */
- " j1 = K1 %% omaxdepth;",
+ " j1_spin = K1 %% omaxdepth;",
" else",
- "#endif", /* if (S_Tab != H_Tab) */
- " if (ssize < 8*WS)",
- " j1 = K1&mask;",
- " else",
- " j1 = K1;",
+ "#endif",
+ " if (ssize < 8*WS)",
+ " j1_spin = K1&mask;",
+ " else",
+ " j1_spin = K1;",
"}",
"#ifndef RANDSTOR",
"int *prerand;",
@@ -3138,10 +4989,11 @@
"void",
"inirand(void)",
"{ int i;",
- " srand(123); /* fixed startpoint */",
+ " srand(s_rand+HASH_NR);", /* inirand */
" prerand = (int *) emalloc((omaxdepth+3)*sizeof(int));",
" for (i = 0; i < omaxdepth+3; i++)",
- " prerand[i] = rand();",
+ " { prerand[i] = rand();",
+ " }",
"}",
"int",
"pan_rand(void)",
@@ -3150,28 +5002,271 @@
"}",
"#endif",
"",
+ "void",
+ "set_masks(void)",
+ "{",
+ " if (WS == 4 && ssize >= 32)",
+ " { mask = 0xffffffff;",
+ "#ifdef BITSTATE",
+ " switch (ssize) {",
+ " case 34: nmask = (mask>>1); break;",
+ " case 33: nmask = (mask>>2); break;",
+ " default: nmask = (mask>>3); break;",
+ " }",
+ "#else",
+ " nmask = mask;",
+ "#endif",
+ " } else if (WS == 8)",
+ " { mask = ((ONE_L<<ssize)-1); /* hash init */",
+ "#ifdef BITSTATE",
+ " nmask = mask>>3;",
+ "#else",
+ " nmask = mask;",
+ "#endif",
+ " } else if (WS != 4)",
+ " { fprintf(stderr, \"pan: wordsize %%ld not supported\\n\", (long int) WS);",
+ " exit(1);",
+ " } else /* WS == 4 and ssize < 32 */",
+ " { mask = ((ONE_L<<ssize)-1); /* hash init */",
+ " nmask = (mask>>3);",
+ " }",
+ "}",
+ "",
+ "#if defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(MA)",
+ "#if NCORE>1",
+ " #error cannot combine AUTO_RESIZE with NCORE>1",
+ "#endif",
+ "static long reclaim_size;",
+ "static char *reclaim_mem;",
+ "static H_el **N_tab;",
+ "void",
+ "reverse_capture(H_el *p)",
+ "{ if (!p) return;",
+ " reverse_capture(p->nxt);",
+ " /* last element of list moves first */",
+ " /* to preserve list-order */",
+ " j2_spin = p->m_K1;",
+ " if (ssize < 8*WS) /* probably always true */",
+ " { j2_spin &= mask;",
+ " }",
+ " p->nxt = N_tab[j2_spin];",
+ " N_tab[j2_spin] = p;",
+ "}",
+ "void",
+ "resize_hashtable(void)",
+ "{",
+ "#ifndef BFS_PAR", /* ssize and mask/nmask are not in shared mem */
+ " if (WS == 4 && ssize >= 27 - 1)",
+ "#endif",
+ " { return; /* cannot increase further */",
+ " }",
+ "",
+ " ssize += 2; /* 4x size @htable ssize */",
+ "",
+ " printf(\"pan: resizing hashtable to -w%%d.. \", ssize);",
+ "",
+ " N_tab = (H_el **) emalloc((ONE_L<<ssize)*sizeof(H_el *));",
+ " set_masks(); /* they changed */",
+ "",
+ " for (j1_spin = 0; j1_spin < (ONE_L << (ssize - 2)); j1_spin++)",
+ " { reverse_capture(H_tab[j1_spin]);",
+ " }",
+ " reclaim_mem = (char *) H_tab;",
+ " reclaim_size = (ONE_L << (ssize - 2));",
+ " H_tab = N_tab;",
+ "",
+ " printf(\" done\\n\");",
+ "}",
+ "#endif",
+ "#if defined(ZAPH) && defined(BITSTATE)",
+ "void",
+ "zap_hashtable(void)",
+ "{ cpu_printf(\"pan: resetting hashtable\\n\");",
+ " if (udmem)",
+ " { memset(SS, 0, udmem);",
+ " } else",
+ " { memset(SS, 0, ONE_L<<(ssize-3));",
+ " }",
+ "}",
+ "#endif",
+ "",
+ "#if NCLAIMS>1",
"int",
+ "find_claim(char *s)",
+ "{ int i, j;",
+ " for (i = 0; strncmp(procname[i], \":np_:\", 5) != 0; i++)",
+ " { if (strcmp(s, procname[i]) == 0)",
+ " { for (j = 0; j < NCLAIMS; j++)",
+ " { if (spin_c_typ[j] == i)",
+ " { return j;",
+ " } }",
+ " break;",
+ " } }",
+ " printf(\"pan: error: cannot find claim '%%s'\\n\", s);",
+ " exit(1);",
+ " return -1; /* unreachable */",
+ "}",
+ "#endif",
+ "",
+ "#if defined(BFS_PAR) && defined(BFS_SEP_HASH)",
+ "int /* to avoid having to include <math.h> and compile with -lm */",
+ "blog2(int n) /* n >= 1 */",
+ "{ int m=1, r=2;",
+ " if (n == 1) { return 0; }",
+ " if (n == 2) { return 1; }",
+ " while (n > r) { m++; r *= 2; }",
+ " return m;",
+ "}",
+ "#endif",
+ "",
+ "uint pp[33];",
+ "",
+ "uint ",
+ "mul(uint a, uint b, uint p)",
+ "{ int c = 0;",
+ " while (a)",
+ " { if (a&1)",
+ " { a ^= 1;",
+ " c ^= b;",
+ " }",
+ " a = (a>>1);",
+ " if (b & 0x80000000)",
+ " { b += b;",
+ " b ^= p;",
+ " } else",
+ " { b += b;",
+ " } }",
+ " return c;",
+ "}",
+ "",
+ "uint",
+ "ppow(int n, uint p)",
+ "{ uint t = 1; int i;",
+ " for (i = 0; i < 32; i++)",
+ " { if (n & (1<<i))",
+ " { t = mul(t, pp[i], p);",
+ " } }",
+ " return t;",
+ "}",
+ "",
+ "void",
+ "hashgen(void) /* courtesy Jim Reeds, 1995 */",
+ "{ uint x, y, p; int i, cnt;",
+ " int ff[5] = { 3, 5, 17, 257, 65537 };",
+ " int nn[5];",
+ "",
+ " srand(s_rand); /* was: srandom(s_rand) */",
+ " nn[0] = ff[1]*ff[2]*ff[3]*ff[4];",
+ " nn[1] = ff[0]*ff[2]*ff[3]*ff[4];",
+ " nn[2] = ff[0]*ff[1]*ff[3]*ff[4];",
+ " nn[3] = ff[0]*ff[1]*ff[2]*ff[4];",
+ " nn[4] = ff[0]*ff[1]*ff[2]*ff[3];",
+ " for (cnt = 0; cnt < 5000; cnt++)",
+ " { x = 2;",
+ " p = ((rand()<<13)^rand()) | 1; /* used random() before */",
+ " pp[0] = x;",
+ " for (i = 0; i < 32; i++)",
+ " { pp[i+1] = mul(pp[i], pp[i], p);",
+ " }",
+ " if (pp[32] == x)",
+ " { for (i = 0; i < 5; i++)",
+ " { y = ppow(nn[i], p);",
+ " if (y == 1)",
+ " { break;",
+ " } }",
+ " if (y != 1)",
+ " { HASH_CONST[0] = p;", /* 32 bit */
+ " if (verbose)",
+ " { printf(\"polynomial: 0x%%.8x (%%d tries)\\n\",",
+ " p, cnt);",
+ " }",
+ " return;", /* success */
+ " } } }",
+ " fprintf(efd, \"pan: could not find a polynomial in %%d tries\\n\", cnt);",
+ " fprintf(efd, \"pan: try a different seed with -RSn\\n\");",
+ " exit(1);",
+ "}",
+ "",
+ "int",
"main(int argc, char *argv[])",
"{ void to_compile(void);\n",
" efd = stderr; /* default */",
+ "#if defined(BFS_PAR) && defined(BFS_SEP_HASH)",
+ " uchar used_w = 0;",
+ "#endif",
+ " if (G_long != sizeof(long)",
+ " || G_int != sizeof(int))",
+ " { printf(\"spin: error, the version of spin \");",
+ " printf(\"that generated this pan.c assumed a different \");",
+ " printf(\"wordsize (%%d iso %%d)\\n\", G_long, (int) sizeof(long));",
+ " exit(1);",
+ " }",
+ "",
+ "#if defined(T_RAND) && (T_RAND>0)",
+ " s_rand = T_RAND;", /* so that -RS can override */
+ "#elif defined(P_RAND) && (P_RAND>0)",
+ " s_rand = P_RAND;",
+ "#endif",
+ "",
+ "#ifdef PUTPID",
+ " { char *ptr = strrchr(argv[0], '/');",
+ " if (ptr == NULL)",
+ " { ptr = argv[0];",
+ " } else",
+ " { ptr++;",
+ " }",
+ " progname = emalloc(strlen(ptr));",
+ " strcpy(progname, ptr);",
+ " /* printf(\"progname: %%s\\n\", progname); */",
+ " }",
+ "#endif",
+ "",
"#ifdef BITSTATE",
- " bstore = bstore_reg; /* default */",
+ " b_store = bstore_reg; /* default */",
"#endif",
+ "#if NCORE>1",
+ " { int i, j;",
+ " strcpy(o_cmdline, \"\");",
+ " for (j = 1; j < argc; j++)",
+ " { strcat(o_cmdline, argv[j]);",
+ " strcat(o_cmdline, \" \");",
+ " }",
+ " /* printf(\"Command Line: %%s\\n\", o_cmdline); */",
+ " if (strlen(o_cmdline) >= sizeof(o_cmdline))",
+ " { Uerror(\"option list too long\");",
+ " } }",
+ "#endif",
" while (argc > 1 && argv[1][0] == '-')",
" { switch (argv[1][1]) {",
"#ifndef SAFETY",
- "#ifdef NP",
- " case 'a': fprintf(efd, \"error: -a disabled\");",
- " usage(efd); break;",
- "#else",
+ " #ifdef NP",
+ " case 'a': fprintf(efd, \"warning: -a is disabled by -DNP, ignored\");",
+ " break;",
+ " #else",
" case 'a': a_cycles = 1; break;",
- "#endif",
+ " #endif",
+ "#else",
+ " #if defined(BFS_PAR) && defined(L_BOUND)",
+ " case 'a': if (isdigit(argv[1][2]))",
+ " { L_bound = atoi(&argv[1][2]);",
+ " if (L_bound < 1 || L_bound > 255)",
+ " { printf(\"usage: -aN with 0<N<256\\n\");",
+ " exit(1);",
+ " } }",
+ " break;",
+ " #endif",
"#endif",
" case 'A': noasserts = 1; break;",
" case 'b': bounded = 1; break;",
- " case 'c': upto = atoi(&argv[1][2]); break;",
+ "#ifdef HAS_CODE",
+ " #if HAS_CODE>0",
+ " case 'C': coltrace = 1; goto samething;",
+ " #endif",
+ "#endif",
+ " case 'c': upto = atoi(&argv[1][2]); break;",
+ " case 'D': dodot++; state_tables++; break;",
" case 'd': state_tables++; break;",
- " case 'e': every_error = 1; Nr_Trails = 1; break;",
+ " case 'e': every_error = 1; upto = 0; Nr_Trails = 1; break;",
" case 'E': noends = 1; break;",
"#ifdef SC",
" case 'F': if (strlen(argv[1]) > 2)",
@@ -3181,23 +5276,57 @@
"#if !defined(SAFETY) && !defined(NOFAIR)",
" case 'f': fairness = 1; break;",
"#endif",
- " case 'h': if (!argv[1][2]) usage(efd); else",
- " HASH_NR = atoi(&argv[1][2])%%33; break;",
+ "#ifdef HAS_CODE",
+ " #if HAS_CODE>0",
+ " case 'g': gui = 1; goto samething;",
+ " #endif",
+ "#endif",
+ " case 'h':",
+ " if (strncmp(&argv[1][1], \"hash\", strlen(\"hash\")) == 0)",
+ " { do_hashgen = 1;",
+ " break;",
+ " }",
+ " if (!argv[1][2] || !isdigit((int) argv[1][2]))",
+ " { usage(efd); /* exits */",
+ " }",
+ " HASH_NR = atoi(&argv[1][2])%%(sizeof(HASH_CONST)/sizeof(uint));",
+ " break;",
" case 'I': iterative = 2; every_error = 1; break;",
- " case 'i': iterative = 1; every_error = 1; break;",
+ " case 'i':",
+ " if (strncmp(&argv[1][1], \"i_reverse\", strlen(\"i_reverse\")) == 0)",
+ " { reversing |= 1;",
+ " } else",
+ " { iterative = 1;",
+ " every_error = 1;",
+ " }",
+ " break;",
" case 'J': like_java = 1; break; /* Klaus Havelund */",
"#ifdef BITSTATE",
" case 'k': hfns = atoi(&argv[1][2]); break;",
"#endif",
+ "#ifdef BCS",
+ " case 'L':",
+ " sched_max = atoi(&argv[1][2]);",
+ " if (sched_max > 255) /* stored as one byte */",
+ " { fprintf(efd, \"warning: using max bound (255)\\n\");",
+ " sched_max = 255;",
+ " }",
+ " #ifndef NOREDUCE",
+ " if (sched_max == 0)",
+ " { fprintf(efd, \"warning: with (default) bound -L0, \");",
+ " fprintf(efd, \"using -DNOREDUCE performs better\\n\");",
+ " }",
+ " #endif",
+ " break;",
+ "#endif",
"#ifndef SAFETY",
"#ifdef NP",
" case 'l': a_cycles = 1; break;",
"#else",
- " case 'l': fprintf(efd, \"error: -l disabled\");",
+ " case 'l': fprintf(efd, \"error: -l not available (compile with -DNP)\");",
" usage(efd); break;",
"#endif",
"#endif",
-#ifndef POWOW
"#ifdef BITSTATE",
" case 'M': udmem = atoi(&argv[1][2]); break;",
" case 'G': udmem = atoi(&argv[1][2]); udmem *= 1024; break;",
@@ -3206,66 +5335,344 @@
" fprintf(stderr, \"-M and -G affect only -DBITSTATE\\n\");",
" break;",
"#endif",
-#endif
" case 'm': maxdepth = atoi(&argv[1][2]); break;",
+ "#ifndef NOCLAIM",
+ " case 'N':",
+ " #if NCLAIMS>1",
+ " if (isdigit((int)argv[1][2]))",
+ " { whichclaim = atoi(&argv[1][2]);",
+ " } else if (isalpha((int)argv[1][2]))",
+ " { claimname = &argv[1][2];",
+ " } else if (argc > 2 && argv[2][0] != '-') /* check next arg */",
+ " { claimname = argv[2];",
+ " argc--; argv++; /* skip next arg */",
+ " }",
+ " #else",
+ " #if NCLAIMS==1",
+ " fprintf(stderr, \"warning: only one claim defined, -N ignored\\n\");",
+ " #else",
+ " fprintf(stderr, \"warning: no claims defined, -N ignored\\n\");",
+ " #endif",
+ " if (!isdigit((int)argv[1][2]) && argc > 2 && argv[2][0] != '-')",
+ " { argc--; argv++;",
+ " }",
+ " #endif",
+ "#endif",
+ " break;\n",
" case 'n': no_rck = 1; break;",
+ "",
+ " case 'P':",
+ " if (!readtrail",
+ " && isdigit((int) argv[1][2]))", /* was argv[1][2] == '_' */
+ " { int x = atoi(&argv[1][2]);",
+ " if (x != 0 && x != 1)",
+ " { fprintf(efd, \"pan: bad option -P[01], ignored\\n\");",
+ " }",
+ " if (x == 0)",
+ " { reversing &= ~1;",
+ " break;",
+ " }",
+ " if (x == 1)",
+ " { reversing |= 1;",
+ " break;",
+ " }",
+ " if (verbose)",
+ " fprintf(efd, \"pan: reversed *active* process creation %%s\\n\",",
+ " reversing&1?\"on\":\"off\");",
+ " break;",
+ " } /* else */",
+ "#ifdef HAS_CODE",
+ " #if HAS_CODE>0",
+ " readtrail = 1; onlyproc = atoi(&argv[1][2]);",
+ " if (argc > 2 && argv[2][0] != '-') /* check next arg */",
+ " { trailfilename = argv[2];",
+ " argc--; argv++; /* skip next arg */",
+ " }",
+ " #else",
+ " fprintf(efd, \"pan: option -P not recognized, ignored\\n\");",
+ " #endif",
+ "#else",
+ " fprintf(efd, \"pan: option -P not recognized, ignored\\n\");",
+ "#endif",
+ " break;",
+ "",
+ " case 'p':",
+ " #if !defined(BFS) && !defined(BFS_PAR)",
+ " #ifdef PERMUTED",
+ " if (strncmp(&argv[1][1], \"p_normal\", strlen(\"p_normal\")) == 0)",
+ " { reversing &= ~2;",
+ " break;",
+ " }",
+ " reversing |=2;",
+ " if (strncmp(&argv[1][1], \"p_permute\", strlen(\"p_permute\")) == 0)",
+ " { p_reorder = set_permuted;",
+ " break;",
+ " }",
+ " if (strncmp(&argv[1][1], \"p_rotate\", strlen(\"p_rotate\")) == 0)",
+ " { p_reorder = set_rotated;",
+ " if (isdigit((int) argv[1][9]))",
+ " { p_rotate = atoi(&argv[1][9]);",
+ " } else",
+ " { p_rotate = 1;",
+ " }",
+ " break;",
+ " }",
+ " if (strncmp(&argv[1][1], \"p_randrot\", strlen(\"p_randrot\")) == 0)",
+ " { p_reorder = set_randrot;",
+ " break;",
+ " }",
+ " if (strncmp(&argv[1][1], \"p_reverse\", strlen(\"p_reverse\")) == 0)",
+ " { p_reorder = set_reversed;",
+ " break;",
+ " }",
+ " #else",
+ " if (strncmp(&argv[1][1], \"p_permute\", strlen(\"p_permute\")) == 0",
+ " || strncmp(&argv[1][1], \"p_rotate\", strlen(\"p_rotate\")) == 0",
+ " || strncmp(&argv[1][1], \"p_randrot\", strlen(\"p_randrot\")) == 0",
+ " || strncmp(&argv[1][1], \"p_reverse\", strlen(\"p_reverse\")) == 0)",
+ " { fprintf(efd, \"option %%s required compilation with -DPERMUTED\\n\",",
+ " argv[1]);",
+ " exit(1);",
+ " }",
+ " #endif",
+ " #endif",
"#ifdef SVDUMP",
- " case 'p': vprefix = atoi(&argv[1][2]); break;",
+ " vprefix = atoi(&argv[1][2]);",
+ "#else",
+ " fprintf(efd, \"invalid option '%%s' -- ignored\\n\", argv[1]);",
"#endif",
+ " break;",
+ "#if NCORE==1",
+ " case 'Q': quota = (double) 60.0 * (double) atoi(&argv[1][2]);",
+ " #ifndef FREQ",
+ " freq /= 10.; /* for better resolution */",
+ " #endif",
+ " break;",
+ "#endif",
" case 'q': strict = 1; break;",
- "#ifdef HAS_CODE",
+ " case 'R':",
+ " if (argv[1][2] == 'S') /* e.g., -RS76842 */",
+ " { s_rand = atoi(&argv[1][3]);", /* RS */
+ " break;",
+ " }",
+ "#ifdef BITSTATE",
+ " Nrun = atoi(&argv[1][2]);",
+ " if (Nrun > 100)",
+ " { Nrun = 100;",
+ " } else if (Nrun < 1)",
+ " { Nrun = 1;",
+ " }",
+ "#else",
+ " usage(efd);",
+ " break;",
+ "#endif",
" case 'r':",
+ " if (strncmp(&argv[1][1], \"rhash\", strlen(\"rhash\")) == 0)",
+ " { if (s_rand == 12345) /* default seed */",
+ " {",
+ "#if defined(WIN32) || defined(WIN64)",
+ " s_rand = (uint) clock();",
+ "#else",
+ " struct tms dummy_tm;",
+ " s_rand = (uint) times(&dummy_tm);",
+ "#endif",
+ " }",
+ " srand(s_rand++);",
+ " #ifdef PERMUTED",
+ " do_hashgen = 1;", /* + randomize p_rotate, p_reverse, p_permute */
+ " switch (rand()%%5) {",
+ " case 0: p_reorder = set_permuted;",
+ " reversing |=2;",
+ " break;",
+ " case 1: p_reorder = set_reversed;",
+ " reversing |=2;",
+ " break;",
+ " /* fully randomize p_rotate: */",
+ " case 2: p_reorder = set_randrot;",
+ " reversing |=2;",
+ " break;",
+ " /* choose once, then keep p_rotate fixed: */",
+ " case 3: p_reorder = set_rotated;",
+ " p_rotate = rand()%%3;",
+ " reversing |=2;",
+ " break;",
+ " default: /* standard search */ break;",
+ " }",
+ " if (rand()%%2 == 0)",
+ " { t_reverse = 1;",
+ " }",
+ " break;",
+ " #else",
+ " fprintf(efd, \"option -rhash requires compilation with -DPERMUTED\\n\");",
+ " exit(1);",
+ " #endif",
+ " }",
+ "#if defined(HAS_CODE) && HAS_CODE>0",
"samething: readtrail = 1;",
- " if (isdigit(argv[1][2]))",
+ " if (isdigit((int)argv[1][2]))",
" whichtrail = atoi(&argv[1][2]);",
+ " else if (argc > 2 && argv[2][0] != '-') /* check next arg */",
+ " { trailfilename = argv[2];",
+ " argc--; argv++; /* skip next arg */",
+ " }",
" break;",
- " case 'P': readtrail = 1; onlyproc = atoi(&argv[1][2]); break;",
- " case 'C': coltrace = 1; goto samething;",
- " case 'g': gui = 1; goto samething;",
- " case 'S': silent = 1; break;",
+ " case 'S': silent = 1; goto samething;",
+ "#else",
+ " fprintf(efd, \"options -r is for models with embedded C code\\n\");",
+ " break;",
"#endif",
- " case 'R': Nrun = atoi(&argv[1][2]); break;",
- "#ifdef BITSTATE",
- " case 's': hfns = 1; break;",
- "#endif",
- " case 'T': TMODE = 0444; break;",
- " case 't': if (argv[1][2]) tprefix = &argv[1][2]; break;",
- " case 'V': printf(\"Generated by %%s\\n\", Version);",
- " to_compile(); pan_exit(0); break;",
- " case 'v': verbose = 1; break;",
- " case 'w': ssize = atoi(&argv[1][2]); break;",
+ " case 'T':",
+ " if (isdigit((int) argv[1][2]))", /* was argv[1][2] == '_' */
+ " { t_reverse = atoi(&argv[1][2]);",
+ " if (verbose)",
+ " printf(\"pan: reverse transition ordering %%s\\n\",",
+ " t_reverse?\"on\":\"off\");",
+ " break;",
+ " }",
+ " TMODE = 0444;",
+ " break;",
+ " case 't':",
+ " if (strncmp(&argv[1][1], \"t_reverse\", strlen(\"t_reverse\")) == 0)",
+ " { t_reverse = 1;",
+ " break;",
+ " }", /* i.e., a trail prefix cannot be '_reverse' */
+ " if (argv[1][2])",
+ " { tprefix = &argv[1][2];",
+ " }",
+ " break;",
+ " case 'u':",
+ " #ifdef BFS_PAR",
+ " ncores = atoi(&argv[1][2]);",
+ " #endif",
+ " break;",
+ " case 'V': start_timer(); printf(\"Generated by %%s\\n\", SpinVersion);",
+ " to_compile(); pan_exit(2); break;",
+ " case 'v': verbose++; break;",
+ " case 'w': ssize = atoi(&argv[1][2]);",
+ " #if defined(BFS_PAR) && defined(BFS_SEP_HASH)",
+ " used_w = 1;",
+ " #endif",
+ " break;",
" case 'Y': signoff = 1; break;",
" case 'X': efd = stdout; break;",
- " default : fprintf(efd, \"saw option -%%c\\n\", argv[1][1]); usage(efd); break;",
+ " case 'x': exclusive = 1; break;",
+ " #if NCORE>1",
+ " /* -B ip is passthru to proxy of remote ip address: */",
+ " case 'B': argc--; argv++; break;",
+ " case 'Q': worker_pids[0] = atoi(&argv[1][2]); break;",
+ " /* -Un means that the nth worker should be instantiated as a proxy */",
+ " case 'U': proxy_pid = atoi(&argv[1][2]); break;",
+ " /* -W means this copy is started by a cluster-server as a remote */",
+ " /* this flag is passed to ./pan_proxy, which interprets it */",
+ " case 'W': remote_party++; break;",
+ " case 'Z': core_id = atoi(&argv[1][2]);",
+ " if (verbose)",
+ " { printf(\"cpu%%d: pid %%d parent %%d\\n\",",
+ " core_id, getpid(), worker_pids[0]);",
+ " }",
+ " break;",
+ " case 'z': z_handoff = atoi(&argv[1][2]); break;",
+ " #else",
+ " case 'z': break; /* ignored for single-core */",
+ " #endif",
+ " default : fprintf(efd, \"saw option -%%c\\n\",",
+ " argv[1][1]); usage(efd); break;",
" }",
" argc--; argv++;",
" }",
+ "#if defined(BFS_PAR) && defined(BFS_SEP_HASH)",
+ " if (used_w == 0)",
+ " { if (ncores == 0) /* all cores used, by default */",
+ " { ssize -= blog2(BFS_MAXPROCS - 1);",
+ " } else",
+ " { ssize -= blog2(ncores);",
+ " } }",
+ "#endif",
+ " if (do_hashgen)",
+ " { hashgen();", /* placed here so that -RSn can appear after -hash */
+ " }",
+ "#ifndef SAFETY",
+ " if (fairness && !a_cycles)",
+ " { fprintf(efd, \"error: -f requires the use of -a or -l\\n\");",
+ " usage(efd);",
+ " }",
+ " #if ACCEPT_LAB==0",
+ " if (a_cycles)",
+ " { fprintf(efd, \"warning: no accept labels are defined, \");",
+ " fprintf(efd, \"so option -a has no effect (ignored)\\n\");",
+ " a_cycles = 0;",
+ " }",
+ " #endif",
+ "#endif",
+ "",
+ "#ifdef BFS_PAR",
+ " uerror = bfs_uerror;",
+ " Uerror = bfs_Uerror;",
+ "#else",
+ " uerror = dfs_uerror;",
+ " Uerror = dfs_Uerror;",
+ "#endif",
+ " if (ssize <= 32) /* 6.2.0 */",
+ " { hasher = d_sfh;",
+ "#if !defined(BITSTATE) && defined(USE_TDH)",
+ " o_hash = o_hash32;",
+ "#endif",
+ " } else",
+ " { hasher = d_hash;",
+ "#if !defined(BITSTATE) && defined(USE_TDH)",
+ " o_hash = o_hash64;",
+ "#endif",
+ " }",
" if (iterative && TMODE != 0666)",
" { TMODE = 0666;",
" fprintf(efd, \"warning: -T ignored when -i or -I is used\\n\");",
" }",
"#if defined(WIN32) || defined(WIN64)",
+ " #ifndef _S_IWRITE",
+ " #define S_IWRITE 0000200 /* write permission, owner */",
+ " #endif",
+ " #ifndef _S_IREAD",
+ " #define S_IREAD 0000400 /* read permission, owner */",
+ " #endif",
" if (TMODE == 0666)",
- " TMODE = _S_IWRITE | _S_IREAD;",
+ " TMODE = S_IWRITE | S_IREAD;",
" else",
- " TMODE = _S_IREAD;",
+ " TMODE = S_IREAD;",
"#endif",
- "#ifdef OHASH",
- " fprintf(efd, \"warning: -DOHASH no longer supported (directive ignored)\\n\");",
+ "#if NCORE>1",
+ " store_proxy_pid = proxy_pid; /* for checks in mem_file() and someone_crashed() */",
+ " if (core_id != 0) { proxy_pid = 0; }",
+ " #ifndef SEP_STATE",
+ " if (core_id == 0 && a_cycles)",
+ " { fprintf(efd, \"hint: this search may be more efficient \");",
+ " fprintf(efd, \"if pan.c is compiled -DSEP_STATE\\n\");",
+ " }",
+ " #endif",
+ " if (z_handoff < 0)",
+ " { z_handoff = 20; /* conservative default - for non-liveness checks */",
+ " }",
+ "#if defined(NGQ) || defined(LWQ_FIXED)",
+ " LWQ_SIZE = (double) (128.*1048576.);",
+ "#else",
+ " LWQ_SIZE = (double) ( z_handoff + 2.) * (double) sizeof(SM_frame);",
+ /* the added margin of +2 is not really necessary */
"#endif",
- "#ifdef JHASH",
- " fprintf(efd, \"warning: -DJHASH no longer supported (directive ignored)\\n\");",
+ " #if NCORE>2",
+ " if (a_cycles)",
+ " { fprintf(efd, \"warning: the intended nr of cores to be used in liveness mode is 2\\n\");",
+ " #ifndef SEP_STATE",
+ " fprintf(efd, \"warning: without -DSEP_STATE there is no guarantee that all liveness violations are found\\n\");",
+ " #endif",
+ " }", /* it still works though, the later cores get states from the global q */
+ " #endif",
+ " #ifdef HAS_HIDDEN",
+ " #error cannot use hidden variables when compiling multi-core",
+ " #endif",
"#endif",
- "#ifdef HYBRID_HASH",
- " fprintf(efd, \"warning: -DHYBRID_HASH no longer supported (directive ignored)\\n\");",
+ "#if defined(T_RAND) && defined(ELSE_IN_GUARD)",
+ " #error cannot hide 'else' as guard in d_step, when using -DT_RAND",
"#endif",
- "#ifdef NOCOVEST",
- " fprintf(efd, \"warning: -DNOCOVEST no longer supported (directive ignored)\\n\");",
- "#endif",
"#ifdef BITSTATE",
- "#ifdef BCOMP",
- " fprintf(efd, \"warning: -DBCOMP no longer supported (directive ignored)\\n\");",
- "#endif",
" if (hfns <= 0)",
" { hfns = 1;",
" fprintf(efd, \"warning: using -k%%d as minimal usable value\\n\", hfns);",
@@ -3278,7 +5685,7 @@
" fprintf(efd, \"warning: using -w%%d as max usable value\\n\", ssize);",
"/*",
" * -w35 would not work: 35-3 = 32 but 1^31 is the largest",
- " * power of 2 that can be represented in an unsigned long",
+ " * power of 2 that can be represented in an ulong",
" */",
" }",
"#else",
@@ -3297,8 +5704,8 @@
" hiwater = HHH = maxdepth-10;",
" DDD = HHH/2;",
" if (!stackfile)",
- " { stackfile = (char *) emalloc(strlen(Source)+4+1);",
- " sprintf(stackfile, \"%%s._s_\", Source);",
+ " { stackfile = (char *) emalloc(strlen(PanSource)+4+1);",
+ " sprintf(stackfile, \"%%s._s_\", PanSource);",
" }",
" if (iterative)",
" { fprintf(efd, \"error: cannot use -i or -I with -DSC\\n\");",
@@ -3307,8 +5714,7 @@
"#endif",
"#if (defined(R_XPT) || defined(W_XPT)) && !defined(MA)",
- " fprintf(efd, \"error: -D?_XPT requires -DMA\\n\");",
- " exit(1);",
+ " #warning -DR_XPT and -DW_XPT assume -DMA (ignored)",
"#endif",
" if (iterative && a_cycles)",
@@ -3315,61 +5721,90 @@
" fprintf(efd, \"warning: -i or -I work for safety properties only\\n\");",
"#ifdef BFS",
- "#if defined(SC)",
- " fprintf(efd, \"error: -DBFS not compatible with -DSC\\n\");",
- " exit(1);",
+ " #ifdef SC",
+ " #error -DBFS not compatible with -DSC",
+ " #endif",
+ " #ifdef HAS_LAST",
+ " #error -DBFS not compatible with _last",
+ " #endif",
+ " #ifdef HAS_STACK",
+ " #error cannot use c_track UnMatched with BFS",
+ " #endif",
+ " #ifdef BCS",
+ " #error -DBFS not compatible with -DBCS",
+ " #endif",
+ " #ifdef REACH",
+ " #warning -DREACH is redundant when -DBFS is used",
+ " #endif",
"#endif",
- "#if defined(HAS_LAST)",
- " fprintf(efd, \"error: -DBFS not compatible with _last\\n\");",
- " exit(1);",
+
+ "#ifdef TRIX",
+ " #ifdef BITSTATE",
+ " #error cannot combine -DTRIX and -DBITSTATE",
+ " #endif",
+ " #ifdef COLLAPSE",
+ " #error cannot combine -DTRIX and -DCOLLAPSE",
+ " #endif",
+ " #ifdef MA",
+ " #error cannot combine -DTRIX and -DMA",
+ " #endif",
+ " #if defined(BFS_PAR) && defined(BFS_SEP_HEAP)",
+ " #error cannot combined -DBFS_SEP_HEAP with -DTRIX",
+ " #endif",
"#endif",
- "#if defined(REACH)",
- " fprintf(efd, \"warning: -DREACH redundant when -DBFS is used\\n\");",
+
+ "#ifdef BFS_PAR",
+ " #ifdef NP",
+ " #error cannot combine -DBFS_PAR and -DNP",
+ " #undef NP",
+ " #endif",
"#endif",
- "#if defined(HAS_STACK)",
- " fprintf(efd, \"error: cannot use UnMatched qualifier on c_track with BFS\\n\");",
- " exit(1);",
+
+ "#ifdef NOCLAIM",
+ " #ifdef NP",
+ " #warning using -DNP overrides -DNOCLAIM",
+ " #undef NOCLAIM",
+ " #endif",
"#endif",
+
+ "#ifdef BCS",
+ " #ifdef P_RAND",
+ " #error cannot combine -DBCS and -DP_RAND",
+ " #endif",
+ " #ifdef BFS",
+ " #error cannot combine -DBCS and -DBFS",
+ " #endif",
"#endif",
"#if defined(MERGED) && defined(PEG)",
- " fprintf(efd, \"error: to allow -DPEG use: spin -o3 -a %%s\\n\", Source);",
- " fprintf(efd, \" to turn off transition merge optimization\\n\");",
- " pan_exit(1);",
+ " #error to use -DPEG use: spin -o3 -a",
"#endif",
- "#ifdef HC",
- "#ifdef NOCOMP",
- " fprintf(efd, \"error: cannot combine -DHC and -DNOCOMP\\n\");",
- " pan_exit(1);",
- "#endif",
- "#ifdef BITSTATE",
- " fprintf(efd, \"error: cannot combine -DHC and -DBITSTATE\\n\");",
- " pan_exit(1);",
- "#endif",
+ "#if defined(HC) && !defined(BFS_PAR)",
+ " #ifdef NOCOMP",
+ " #error cannot combine -DHC and -DNOCOMP",
+ " #endif",
+ " #ifdef BITSTATE",
+ " #error cannot combine -DHC and -DBITSTATE",
+ " #endif",
"#endif",
"#if defined(SAFETY) && defined(NP)",
- " fprintf(efd, \"error: cannot combine -DNP and -DSAFETY\\n\");",
- " pan_exit(1);",
+ " #error cannot combine -DNP and -DBFS or -DSAFETY",
"#endif",
"#ifdef MA",
- "#ifdef BITSTATE",
- " fprintf(efd, \"error: cannot combine -DMA and -DBITSTATE\\n\");",
- " pan_exit(1);",
+ " #ifdef BITSTATE",
+ " #error cannot combine -DMA and -DBITSTATE",
+ " #endif",
+ " #if MA <= 0",
+ " #error usage: -DMA=N with N > 0 and N < VECTORSZ",
+ " #endif",
"#endif",
- " if (MA <= 0)",
- " { fprintf(efd, \"usage: -DMA=N with N > 0 and < VECTORSZ\\n\");",
- " pan_exit(1);",
- " }",
- "#endif",
"#ifdef COLLAPSE",
- "#if defined(BITSTATE)",
- " fprintf(efd, \"error: cannot combine -DBITSTATE and -DCOLLAPSE\\n\");",
- " pan_exit(1);",
- "#endif",
- "#if defined(NOCOMP)",
- " fprintf(efd, \"error: cannot combine -DNOCOMP and -DCOLLAPSE\\n\");",
- " pan_exit(1);",
- "#endif",
+ " #ifdef BITSTATE",
+ " #error cannot combine -DBITSTATE and -DCOLLAPSE",
+ " #endif",
+ " #ifdef NOCOMP",
+ " #error cannot combine -DCOLLAPSE and -DNOCOMP",
+ " #endif",
"#endif",
" if (maxdepth <= 0 || ssize <= 1) usage(efd);",
"#if SYNC>0 && !defined(NOREDUCE)",
@@ -3382,185 +5817,126 @@
" }",
"#endif",
"#if defined(REM_VARS) && !defined(NOREDUCE)",
- " { fprintf(efd, \"warning: p.o. reduction not compatible with \");",
- " fprintf(efd, \"remote varrefs (use -DNOREDUCE)\\n\");",
- " }",
+ " #warning p.o. reduction not compatible with remote varrefs (use -DNOREDUCE)",
"#endif",
"#if defined(NOCOMP) && !defined(BITSTATE)",
" if (a_cycles)",
- " { fprintf(efd, \"error: -DNOCOMP voids -l and -a\\n\");",
+ " { fprintf(efd, \"error: use of -DNOCOMP voids -l and -a\\n\");",
" pan_exit(1);",
" }",
"#endif",
-
- "#ifdef MEMLIM", /* MEMLIM setting takes precedence */
- " memlim = (double) MEMLIM * (double) (1<<20); /* size in Mbyte */",
- "#else",
- "#ifdef MEMCNT",
- "#if MEMCNT<31",
- " memlim = (double) (1<<MEMCNT);",
- "#else",
- " memlim = (double) (1<<30);",
- " memlim *= (double) (1<<(MEMCNT-30));",
- "#endif",
- "#endif",
+ "#ifdef MEMLIM",
+ " memlim = ((double) MEMLIM) * (double) (1<<20); /* size in Mbyte */",
"#endif",
-
- "#ifndef BITSTATE",
- " if (Nrun > 1) HASH_NR = Nrun - 1;",
+ "#if SYNC>0",
+ " #ifdef HAS_PRIORITY",
+ " #error use of priorities cannot be combined with rendezvous",
+ " #elif HAS_ENABLED",
+ " #error use of enabled() cannot be combined with rendezvous",
+ " #endif",
"#endif",
- " if (Nrun < 1 || Nrun > 32)",
- " { fprintf(efd, \"error: invalid arg for -R\\n\");",
- " usage(efd);",
- " }",
- "#ifndef SAFETY",
- " if (fairness && !a_cycles)",
- " { fprintf(efd, \"error: -f requires -a or -l\\n\");",
- " usage(efd);",
- " }",
- "#if ACCEPT_LAB==0",
- " if (a_cycles)",
- "#ifndef VERI",
- " { fprintf(efd, \"error: no accept labels defined \");",
- " fprintf(efd, \"in model (for option -a)\\n\");",
- " usage(efd);",
- " }",
- "#else",
- " { fprintf(efd, \"warning: no explicit accept labels \");",
- " fprintf(efd, \"defined in model (for -a)\\n\");",
- " }",
- "#endif",
- "#endif",
+ "#ifndef NOREDUCE",
+ " #ifdef HAS_PRIORITY",
+ " #warning use of priorities requires -DNOREDUCE",
+ " #elif HAS_ENABLED",
+ " #error use of enabled() requires -DNOREDUCE",
+ " #endif",
+ " #ifdef HAS_PCVALUE",
+ " #error use of pcvalue() requires -DNOREDUCE",
+ " #endif",
+ " #ifdef HAS_BADELSE",
+ " #error use of 'else' combined with i/o stmnts requires -DNOREDUCE",
+ " #endif",
+ " #if defined(HAS_LAST) && !defined(BCS)",
+ " #error use of _last requires -DNOREDUCE",
+ " #endif",
"#endif",
- "#if !defined(NOREDUCE)",
- "#if defined(HAS_ENABLED)",
- " fprintf(efd, \"error: reduced search precludes \");",
- " fprintf(efd, \"use of 'enabled()'\\n\");",
- " pan_exit(1);",
- "#endif",
- "#if defined(HAS_PCVALUE)",
- " fprintf(efd, \"error: reduced search precludes \");",
- " fprintf(efd, \"use of 'pcvalue()'\\n\");",
- " pan_exit(1);",
- "#endif",
- "#if defined(HAS_BADELSE)",
- " fprintf(efd, \"error: reduced search precludes \");",
- " fprintf(efd, \"using 'else' combined with i/o stmnts\\n\");",
- " pan_exit(1);",
- "#endif",
- "#if defined(HAS_LAST)",
- " fprintf(efd, \"error: reduced search precludes \");",
- " fprintf(efd, \"use of _last\\n\");",
- " pan_exit(1);",
- "#endif",
- "#endif",
"#if SYNC>0 && !defined(NOREDUCE)",
- "#ifdef HAS_UNLESS",
+ " #ifdef HAS_UNLESS",
" fprintf(efd, \"warning: use of a rendezvous stmnts in the escape\\n\");",
" fprintf(efd, \"\tof an unless clause, if present, could make p.o. reduction\\n\");",
" fprintf(efd, \"\tinvalid (use -DNOREDUCE to avoid this)\\n\");",
- "#ifdef BFS",
- " fprintf(efd, \"\t(this type of rv is also not compatible with -DBFS)\\n\");",
- "#endif",
- "#endif",
+ " #ifdef BFS",
+ " fprintf(efd, \"\t(this type of rv is also not compatible with -DBFS)\\n\");",
+ " #endif",
+ " #endif",
"#endif",
"#if SYNC>0 && defined(BFS)",
- " fprintf(efd, \"warning: use of rendezvous in BFS mode \");",
- " fprintf(efd, \"does not preserve all invalid endstates\\n\");",
+ " if (!noends)",
+ " fprintf(efd, \"warning: use of rendezvous with BFS does not preserve all invalid endstates\\n\");",
"#endif",
"#if !defined(REACH) && !defined(BITSTATE)",
" if (iterative != 0 && a_cycles == 0)",
- " fprintf(efd, \"warning: -i and -I need -DREACH to work accurately\\n\");",
+ " { fprintf(efd, \"warning: -i and -I need -DREACH to work accurately\\n\");",
+ " }",
"#endif",
"#if defined(BITSTATE) && defined(REACH)",
- " fprintf(efd, \"warning: -DREACH voided by -DBITSTATE\\n\");",
+ " #warning -DREACH is voided by -DBITSTATE",
"#endif",
"#if defined(MA) && defined(REACH)",
- " fprintf(efd, \"warning: -DREACH voided by -DMA\\n\");",
+ " #warning -DREACH is voided by -DMA",
"#endif",
"#if defined(FULLSTACK) && defined(CNTRSTACK)",
- " fprintf(efd, \"error: cannot combine\");",
- " fprintf(efd, \" -DFULLSTACK and -DCNTRSTACK\\n\");",
- " pan_exit(1);",
+ " #error cannot combine -DFULLSTACK and -DCNTRSTACK",
"#endif",
"#if defined(VERI)",
- "#if ACCEPT_LAB>0",
- "#ifndef BFS",
- " if (!a_cycles",
- "#ifdef HAS_CODE",
- " && !readtrail",
- "#endif",
- " && !state_tables)",
- " { fprintf(efd, \"warning: never claim + accept labels \");",
- " fprintf(efd, \"requires -a flag to fully verify\\n\");",
- " }",
- "#else",
- " if (",
- "#ifdef HAS_CODE",
- " !readtrail",
- "#endif",
- " && !state_tables)",
- " { fprintf(efd, \"warning: verification in BFS mode \");",
- " fprintf(efd, \"is restricted to safety properties\\n\");",
- " }",
+ " #if ACCEPT_LAB>0",
+ " #ifndef BFS",
+ " if (!a_cycles",
+ " #ifdef HAS_CODE",
+ " && !readtrail",
+ " #endif",
+ " #if NCORE>1",
+ " && core_id == 0",
+ " #endif",
+ " && !state_tables)",
+ " { fprintf(efd, \"warning: never claim + accept labels \");",
+ " fprintf(efd, \"requires -a flag to fully verify\\n\");",
+ " }",
+ " #else",
+ " if (verbose && !state_tables",
+ " #ifdef HAS_CODE",
+ " && !readtrail",
+ " #endif",
+ " )",
+ " { fprintf(efd, \"warning: verification in BFS mode \");",
+ " fprintf(efd, \"is restricted to safety properties\\n\");",
+ " }",
+ " #endif",
+ " #endif",
"#endif",
- "#endif",
- "#endif",
"#ifndef SAFETY",
+ " #if 0",
" if (!a_cycles",
- "#ifdef HAS_CODE",
+ " #ifdef HAS_CODE",
" && !readtrail",
- "#endif",
- " && !state_tables)",
+ " #endif",
+ " #if NCORE>1",
+ " && core_id == 0",
+ " #endif",
+ " && !state_tables)",
" { fprintf(efd, \"hint: this search is more efficient \");",
" fprintf(efd, \"if pan.c is compiled -DSAFETY\\n\");",
" }",
- "#ifndef NOCOMP",
+ " #endif",
+ " #ifndef NOCOMP",
" if (!a_cycles)",
- " S_A = 0;",
- " else",
+ " { S_A = 0;",
+ " } else",
" { if (!fairness)",
- " S_A = 1; /* _a_t */",
- "#ifndef NOFAIR",
- " else /* _a_t and _cnt[NFAIR] */",
- " S_A = (&(now._cnt[0]) - (uchar *) &now) + NFAIR - 2;",
+ " { S_A = 1; /* _a_t */",
+ " #ifndef NOFAIR",
+ " } else /* _a_t and _cnt[NFAIR] */",
+ " { S_A = (&(now._cnt[0]) - (uchar *) &now) + NFAIR - 2;",
" /* -2 because first two uchars in now are masked */",
- "#endif",
- " }",
- "#endif",
+ " #endif",
+ " } }",
+ " #endif",
"#endif",
" signal(SIGINT, stopped);",
-
- /******************* 4.2.5 ********************/
- " if (WS == 4 && ssize >= 32)",
- " { mask = 0xffffffff;",
- "#ifdef BITSTATE",
- " switch (ssize) {",
- " case 34: nmask = (mask>>1); break;",
- " case 33: nmask = (mask>>2); break;",
- " default: nmask = (mask>>3); break;",
- " }",
- "#else",
- " nmask = mask;",
- "#endif",
- " } else if (WS == 8)",
- " { mask = ((1L<<ssize)-1); /* hash init */",
- "#ifdef BITSTATE",
- " nmask = mask>>3;",
- "#else",
- " nmask = mask;",
- "#endif",
- " } else if (WS != 4)",
- " { fprintf(stderr, \"pan: wordsize %%ld not supported\\n\", WS);",
- " exit(1);",
- " } else /* WS == 4 and ssize < 32 */",
- " { mask = ((1L<<ssize)-1); /* hash init */",
- " nmask = (mask>>3);",
- " }",
- /****************** end **********************/
-
- "#ifdef BFS",
+ " set_masks();",
+ "#if defined(BFS) || defined(BFS_PAR)",
" trail = (Trail *) emalloc(6*sizeof(Trail));",
" trail += 3;",
"#else",
@@ -3567,17 +5943,21 @@
" trail = (Trail *) emalloc((maxdepth+3)*sizeof(Trail));",
" trail++; /* protect trpt-1 refs at depth 0 */",
"#endif",
+ " trpt = &trail[0]; /* precaution -- in case uerror is called early */",
+ "#ifdef BFS",
+ " ntrpt = trpt;",
+ "#endif",
"#ifdef SVDUMP",
" if (vprefix > 0)",
" { char nm[64];",
- " sprintf(nm, \"%%s.svd\", Source);",
- " if ((svfd = creat(nm, 0666)) < 0)",
+ " sprintf(nm, \"%%s.svd\", PanSource);",
+ " if ((svfd = creat(nm, TMODE)) < 0)",
" { fprintf(efd, \"couldn't create %%s\\n\", nm);",
" vprefix = 0;",
" } }",
"#endif",
"#ifdef RANDSTOR",
- " srand(123);",
+ " srand(s_rand+HASH_NR);", /* main - RANDSTOR */
"#endif",
"#if SYNC>0 && ASYNC==0",
" set_recvs();",
@@ -3591,6 +5971,7 @@
"void",
"usage(FILE *fd)",
"{",
+ " fprintf(fd, \"%%s\\n\", SpinVersion);",
" fprintf(fd, \"Valid Options are:\\n\");",
"#ifndef SAFETY",
"#ifdef NP",
@@ -3606,6 +5987,7 @@
" fprintf(fd, \"\t-b consider it an error to exceed the depth-limit\\n\");",
" fprintf(fd, \"\t-cN stop at Nth error \");",
" fprintf(fd, \"(defaults to -c1)\\n\");",
+ " fprintf(fd, \"\t-D print state tables in dot-format and stop\\n\");",
" fprintf(fd, \"\t-d print state tables and stop\\n\");",
" fprintf(fd, \"\t-e create trails for all errors\\n\");",
" fprintf(fd, \"\t-E ignore invalid end states\\n\");",
@@ -3615,7 +5997,9 @@
"#ifndef NOFAIR",
" fprintf(fd, \"\t-f add weak fairness (to -a or -l)\\n\");",
"#endif",
- " fprintf(fd, \"\t-hN use different hash-seed N:1..32\\n\");",
+ " fprintf(fd, \"\t-hN use different hash-seed N:0..499 (defaults to -h0)\\n\");",
+ " fprintf(fd, \"\t-hash generate a random hash-polynomial for -h0 (see also -rhash)\\n\");",
+ " fprintf(fd, \"\t using a seed set with -RSn (default %%u)\\n\", s_rand);",
" fprintf(fd, \"\t-i search for shortest path to error\\n\");",
" fprintf(fd, \"\t-I like -i, but approximate and faster\\n\");",
" fprintf(fd, \"\t-J reverse eval order of nested unlesses\\n\");",
@@ -3622,6 +6006,9 @@
"#ifdef BITSTATE",
" fprintf(fd, \"\t-kN set N bits per state (defaults to 3)\\n\");",
"#endif",
+ "#ifdef BCS",
+ " fprintf(fd, \"\t-LN set scheduling restriction to N (default 0)\\n\");",
+ "#endif",
"#ifndef SAFETY",
"#ifdef NP",
" fprintf(fd, \"\t-l find non-progress cycles\\n\");",
@@ -3631,69 +6018,83 @@
" fprintf(fd, \"compilation with -DNP\\n\");",
"#endif",
"#endif",
-#ifndef POWOW
"#ifdef BITSTATE",
" fprintf(fd, \"\t-MN use N Megabytes for bitstate hash array\\n\");",
" fprintf(fd, \"\t-GN use N Gigabytes for bitstate hash array\\n\");",
"#endif",
-#endif
" fprintf(fd, \"\t-mN max depth N steps (default=10k)\\n\");",
+ "#if NCLAIMS>1",
+ " fprintf(fd, \"\t-N cn -- use the claim named cn\\n\");",
+ " fprintf(fd, \"\t-Nn -- use claim number n\\n\");",
+ "#endif",
" fprintf(fd, \"\t-n no listing of unreached states\\n\");",
+ "#ifdef PERMUTED",
+ " fprintf(fd, \"\t-p_permute randomize order in which processes are scheduled (see also -rhash)\\n\");",
+ " fprintf(fd, \"\t-p_reverse reverse order in which processes are scheduled (see also -rhash)\\n\");",
+ " fprintf(fd, \"\t-p_rotateN rotate by N the process scheduling order (see also -rhash)\\n\");",
+ "#endif",
"#ifdef SVDUMP",
" fprintf(fd, \"\t-pN create svfile (save N bytes per state)\\n\");",
"#endif",
+ " fprintf(fd, \"\t-QN set time-limit on execution of N minutes\\n\");",
" fprintf(fd, \"\t-q require empty chans in valid end states\\n\");",
"#ifdef HAS_CODE",
" fprintf(fd, \"\t-r read and execute trail - can add -v,-n,-PN,-g,-C\\n\");",
+ " fprintf(fd, \"\t-r trailfilename read and execute trail in file\\n\");",
" fprintf(fd, \"\t-rN read and execute N-th error trail\\n\");",
" fprintf(fd, \"\t-C read and execute trail - columnated output (can add -v,-n)\\n\");",
- " fprintf(fd, \"\t-PN read and execute trail - restrict trail output to proc N\\n\");",
+ " fprintf(fd, \"\t-r -PN read and execute trail - restrict trail output to proc N\\n\");",
" fprintf(fd, \"\t-g read and execute trail + msc gui support\\n\");",
" fprintf(fd, \"\t-S silent replay: only user defined printfs show\\n\");",
"#endif",
+ " fprintf(fd, \"\t-RSn use randomization seed n\\n\");",
+ " fprintf(fd, \"\t-rhash use random hash-polynomial and randomly choose -p_rotateN, -p_permute, or p_reverse\\n\");",
"#ifdef BITSTATE",
- " fprintf(fd, \"\t-RN repeat run Nx with N \");",
- " fprintf(fd, \"[1..32] independent hash functions\\n\");",
- " fprintf(fd, \"\t-s same as -k1 (single bit per state)\\n\");",
+ " fprintf(fd, \"\t-Rn run n times n: [1..100] using n \");",
+ " fprintf(fd, \" different hash functions\\n\");",
"#endif",
" fprintf(fd, \"\t-T create trail files in read-only mode\\n\");",
+ " fprintf(fd, \"\t-t_reverse reverse order in which transitions are explored\\n\");",
" fprintf(fd, \"\t-tsuf replace .trail with .suf on trailfiles\\n\");",
" fprintf(fd, \"\t-V print SPIN version number\\n\");",
" fprintf(fd, \"\t-v verbose -- filenames in unreached state listing\\n\");",
" fprintf(fd, \"\t-wN hashtable of 2^N entries \");",
" fprintf(fd, \"(defaults to -w%%d)\\n\", ssize);",
+ " fprintf(fd, \"\t-x do not overwrite an existing trail file\\n\");",
+ "#if NCORE>1",
+ " fprintf(fd, \"\t-zN handoff states below depth N to 2nd cpu (multi_core)\\n\");",
+ "#endif",
+ "#ifdef HAS_CODE",
+ " fprintf(fd, \"\\n\toptions -r, -C, -PN, -g, and -S can optionally be followed by\\n\");",
+ " fprintf(fd, \"\ta filename argument, as in \'-r filename\', naming the trailfile\\n\");",
+ "#endif",
+ "#if NCORE>1",
+ " multi_usage(fd);",
+ "#endif",
" exit(1);",
"}",
"",
"char *",
- "Malloc(unsigned long n)",
+ "Malloc(ulong n)",
"{ char *tmp;",
- "#if defined(MEMCNT) || defined(MEMLIM)",
- " if (memcnt+ (double) n > memlim) goto err;",
+ "#ifdef MEMLIM",
+ " if (memcnt + (double) n > memlim)",
+ " { printf(\"pan: reached -DMEMLIM bound\\n\");",
+ " goto err;",
+ " }",
"#endif",
-"#if 1",
" tmp = (char *) malloc(n);",
" if (!tmp)",
-"#else",
- /* on linux machines, a large amount of memory is set aside
- * for malloc, whether it is used or not
- * using sbrk would make this memory arena inaccessible
- * the reason for using sbrk was originally to provide a
- * small additional speedup (since this memory is never released)
- */
- " tmp = (char *) sbrk(n);",
- " if (tmp == (char *) -1L)",
-"#endif",
" {",
- "#if defined(MEMCNT) || defined(MEMLIM)",
- "err:",
+ "#ifdef BFS_PAR",
+ " Uerror(\"out of non-shared memory\");",
"#endif",
" printf(\"pan: out of memory\\n\");",
- "#if defined(MEMCNT) || defined(MEMLIM)",
+ "#ifdef MEMLIM",
+ "err:",
" printf(\"\t%%g bytes used\\n\", memcnt);",
" printf(\"\t%%g bytes more needed\\n\", (double) n);",
- " printf(\"\t%%g bytes limit\\n\",",
- " memlim);",
+ " printf(\"\t%%g bytes limit\\n\", memlim);",
"#endif",
"#ifdef COLLAPSE",
" printf(\"hint: to reduce memory, recompile with\\n\");",
@@ -3714,6 +6115,15 @@
" printf(\" -DBITSTATE # supertrace, approximation\\n\");",
"#endif",
"#endif",
+ "#if NCORE>1",
+ " #ifdef FULL_TRAIL",
+ " printf(\" omit -DFULL_TRAIL or use pan -c0 to reduce memory\\n\");",
+ " #endif",
+ " #ifdef SEP_STATE",
+ " printf(\"hint: to reduce memory, recompile without\\n\");",
+ " printf(\" -DSEP_STATE # may be faster, but uses more memory\\n\");",
+ " #endif",
+ "#endif",
" wrapup();",
" }",
" memcnt += (double) n;",
@@ -3723,13 +6133,13 @@
"#define CHUNK (100*VECTORSZ)",
"",
"char *",
- "emalloc(unsigned long n) /* never released or reallocated */",
+ "emalloc(ulong n) /* never released or reallocated */",
"{ char *tmp;",
" if (n == 0)",
" return (char *) NULL;",
" if (n&(sizeof(void *)-1)) /* for proper alignment */",
" n += sizeof(void *)-(n&(sizeof(void *)-1));",
- " if ((unsigned long) left < n)", /* was: (left < (long)n) */
+ " if ((ulong) left < n)", /* was: (left < (long)n) */
" { grow = (n < CHUNK) ? CHUNK : n;",
#if 1
" have = Malloc(grow);",
@@ -3754,9 +6164,15 @@
"}",
"void",
- "Uerror(char *str)",
+ "dfs_Uerror(char *str)",
"{ /* always fatal */",
" uerror(str);",
+ "#if NCORE>1",
+ " sudden_stop(\"Uerror\");",
+ "#endif",
+ "#ifdef BFS_PAR",
+ " bfs_shutdown(\"Uerror\");",
+ "#endif",
" wrapup();",
"}\n",
"#if defined(MA) && !defined(SAFETY)",
@@ -3775,9 +6191,14 @@
" trpt = getframe(depth);",
"#endif",
"#ifdef VERBOSE",
- " printf(\"%%d State: \", depth);",
+ " printf(\"%%ld State: \", depth);",
+ "#if !defined(NOCOMP) && !defined(HC)",
" for (i = 0; i < vsize; i++) printf(\"%%d%%s,\",",
" ((char *)&now)[i], Mask[i]?\"*\":\"\");",
+ "#else",
+ " for (i = 0; i < vsize; i++)",
+ " printf(\"%%d,\", ((char *)&now)[i]);",
+ "#endif",
" printf(\"\\n\");",
"#endif",
"#ifndef NOFAIR",
@@ -3794,7 +6215,7 @@
"#endif",
"#ifdef HAS_LAST",
"#ifdef VERI",
- " { int d; Trail *trl;",
+ " { long d; Trail *trl;",
" now._last = 0;",
" for (d = 1; d < depth; d++)",
" { trl = getframe(depth-d); /* was trl = (trpt-d); */",
@@ -3820,10 +6241,10 @@
" tt = trpt->o_tt; this = pptr(II);",
" _m = do_reverse(t, II, trpt->o_m);",
"#ifdef VERBOSE",
- " printf(\"%%3d: proc %%d \", depth, II);",
+ " printf(\"%%3ld: proc %%d \", depth, II);",
" printf(\"reverses %%d, %%d to %%d,\",",
" t->forw, tt, t->st);",
- " printf(\" %%s [abit=%%d,adepth=%%d,\", ",
+ " printf(\" %%s [abit=%%d,adepth=%%ld,\", ",
" t->tp, now._a_t, A_depth);",
" printf(\"tau=%%d,%%d] <unwind>\\n\", ",
" trpt->tau, (trpt-1)->tau);",
@@ -3862,14 +6283,21 @@
"#endif",
"static char unwinding;",
"void",
- "uerror(char *str)",
+ "dfs_uerror(char *str)",
"{ static char laststr[256];",
" int is_cycle;",
"",
" if (unwinding) return; /* 1.4.2 */",
" if (strncmp(str, laststr, 254))",
- " printf(\"pan: %%s (at depth %%ld)\\n\", str,",
- " (depthfound==-1)?depth:depthfound);",
+ "#if NCORE>1",
+ " cpu_printf(\"pan:%%d: %%s (at depth %%ld)\\n\", errors+1, str,",
+ "#else",
+ " printf(\"pan:%%d: %%s (at depth %%ld)\\n\", errors+1, str,",
+ "#endif",
+ "#if NCORE>1",
+ " (nr_handoffs * z_handoff) + ",
+ "#endif",
+ " ((depthfound == -1)?depth:depthfound));",
" strncpy(laststr, str, 254);",
" errors++;",
"#ifdef HAS_CODE",
@@ -3891,13 +6319,16 @@
" depth = od;",
" }",
"#endif",
-"#ifdef BFS",
+ "#if NCORE>1",
+ " writing_trail = 1;",
+ "#endif",
+ "#ifdef BFS",
" if (depth > 1) trpt--;",
- " nuerror(str);",
+ " nuerror();",
" if (depth > 1) trpt++;",
-"#else",
+ "#else",
" putrail();",
-"#endif",
+ "#endif",
"#if defined(MA) && !defined(SAFETY)",
" if (strstr(str, \" cycle\"))",
" { if (every_error)",
@@ -3905,20 +6336,36 @@
" wrapup(); /* no recovery from unwind */",
" }",
"#endif",
+ "#if NCORE>1",
+ " if (search_terminated != NULL)",
+ " { *search_terminated |= 4; /* uerror */",
+ " }",
+ " writing_trail = 0;",
+ "#endif",
" }",
" if (!is_cycle)",
" { depth--; trpt--; /* undo */",
" }",
-"#ifndef BFS",
+ "#ifndef BFS",
" if (iterative != 0 && maxdepth > 0)",
- " { maxdepth = (iterative == 1)?(depth-1):(depth/2);",
+ " { if (maxdepth > depth)",
+ " { maxdepth = (iterative == 1)?(depth+1):(depth/2);",
+ " }",
" warned = 1;",
" printf(\"pan: reducing search depth to %%ld\\n\",",
" maxdepth);",
" } else",
-"#endif",
+ "#endif",
" if (errors >= upto && upto != 0)",
+ " {",
+ "#ifdef BFS_PAR",
+ " bfs_shutdown(\"uerror\"); /* no return */",
+ "#endif",
+ "#if NCORE>1",
+ " sudden_stop(\"uerror\");",
+ "#endif",
" wrapup();",
+ " }",
" depthfound = -1;",
"}\n",
"int",
@@ -3930,13 +6377,14 @@
" || strncmp(T->tp, \"goto :\", 6) == 0)",
" return 1; /* not reported */",
"",
- " printf(\"\\tline %%d\", lno);",
- " if (verbose)",
" for (j = 0; j < sizeof(mp); j++)",
" if (i >= mp[j].from && i <= mp[j].upto)",
- " { printf(\", \\\"%%s\\\"\", mp[j].fnm);",
+ " { printf(\"\\t%%s:%%d\", mp[j].fnm, lno);",
" break;",
" }",
+ " if (j >= sizeof(mp)) /* fnm not found in list */",
+ " { printf(\"\\t%%s:%%d\", PanSource, lno); /* use default */",
+ " }",
" printf(\", state %%d\", i);",
" if (strcmp(T->tp, \"\") != 0)",
" { char *q;",
@@ -3951,45 +6399,120 @@
"}\n",
"void",
"r_ck(uchar *which, int N, int M, short *src, S_F_MAP *mp)",
- "{ int i, m=0;\n",
- "#ifdef VERI",
- " if (M == VERI && !verbose) return;",
- "#endif",
- " printf(\"unreached in proctype %%s\\n\", procname[M]);",
+ "{ int i, m=0;",
+ "",
+ " if ((enum btypes) Btypes[M] == N_CLAIM",
+ " && claimname != NULL && strcmp(claimname, procname[M]) != 0)",
+ " { return;",
+ " }",
+ "",
+ " switch ((enum btypes) Btypes[M]) {",
+ " case P_PROC:",
+ " case A_PROC:",
+ " printf(\"unreached in proctype %%s\\n\", procname[M]);",
+ " break;",
+ " case I_PROC:",
+ " printf(\"unreached in init\\n\");",
+ " break;",
+ " case E_TRACE:",
+ " case N_TRACE:",
+ " case N_CLAIM:",
+ " default:",
+ " printf(\"unreached in claim %%s\\n\", procname[M]);",
+ " break;",
+ " }",
" for (i = 1; i < N; i++)",
-#if 0
- " if (which[i] == 0 /* && trans[M][i] */)",
-#else
- " if (which[i] == 0",
- " && (mapstate[M][i] == 0",
- " || which[mapstate[M][i]] == 0))",
-#endif
- " m += xrefsrc((int) src[i], mp, M, i);",
- " else",
- " m++;",
+ " { if (which[i] == 0",
+ " && (mapstate[M][i] == 0",
+ " || which[mapstate[M][i]] == 0))",
+ " { m += xrefsrc((int) src[i], mp, M, i);",
+ " } else",
+ " { m++;",
+ " } }",
" printf(\"\t(%%d of %%d states)\\n\", N-1-m, N-1);",
- "}\n",
+ "}",
+ "#if NCORE>1 && !defined(SEP_STATE)",
+ "static long rev_trail_cnt;",
+ "",
+ "#ifdef FULL_TRAIL",
"void",
+ "rev_trail(int fd, volatile Stack_Tree *st_tr)",
+ "{ long j; char snap[64];",
+ "",
+ " if (!st_tr)",
+ " { return;",
+ " }",
+ " rev_trail(fd, st_tr->prv);",
+ "#ifdef VERBOSE",
+ " printf(\"%%d (%%d) LRT [%%d,%%d] -- %%9u (root %%9u)\\n\",",
+ " depth, rev_trail_cnt, st_tr->pr, st_tr->t_id, st_tr, stack_last[core_id]);",
+ "#endif",
+ " if (st_tr->pr != 255)", /* still needed? */
+ " { sprintf(snap, \"%%ld:%%d:%%d\\n\", ",
+ " rev_trail_cnt++, st_tr->pr, st_tr->t_id);",
+ " j = strlen(snap);",
+ " if (write(fd, snap, j) != j)",
+ " { printf(\"pan: error writing trailfile\\n\");",
+ " close(fd);",
+ " wrapup();",
+ " return;",
+ " }",
+ " } else /* handoff point */",
+ " { if (a_cycles)",
+ " { (void) write(fd, \"-1:-1:-1\\n\", 9);",
+ " } }",
+ "}",
+ "#endif", /* FULL_TRAIL */
+ "#endif", /* NCORE>1 */
+ "",
+ "void",
"putrail(void)",
- "{ int fd; long i, j;",
- " Trail *trl;",
+ "{ int fd;",
"#if defined VERI || defined(MERGED)",
" char snap[64];",
"#endif",
- "",
+ "#if NCORE==1 || defined(SEP_STATE) || !defined(FULL_TRAIL)",
+ " long i, j;",
+ " Trail *trl;",
+ "#endif",
" fd = make_trail();",
" if (fd < 0) return;",
"#ifdef VERI",
- " sprintf(snap, \"-2:%%d:-2\\n\", VERI);",
- " write(fd, snap, strlen(snap));",
+ " sprintf(snap, \"-2:%%d:-2\\n\", (uchar) ((P0 *)pptr(0))->_t);",
+ " if (write(fd, snap, strlen(snap)) < 0) return;",
"#endif",
"#ifdef MERGED",
" sprintf(snap, \"-4:-4:-4\\n\");",
- " write(fd, snap, strlen(snap));",
+ " if (write(fd, snap, strlen(snap)) < 0) return;",
"#endif",
- " for (i = 1; i <= depth; i++)",
+ "#ifdef PERMUTED",
+ " sprintf(snap, \"-5:%%d:%%d\\n\", t_reverse, reversing&2);",
+ " if (write(fd, snap, strlen(snap)) < 0) return;",
+ "",
+ " sprintf(snap, \"-6:%%d:%%d\\n\", p_reorder==set_permuted, p_reorder==set_reversed);",
+ " if (write(fd, snap, strlen(snap)) < 0) return;",
+ "",
+ " sprintf(snap, \"-7:%%d:%%d\\n\", p_reorder==set_rotated, p_rotate);",
+ " if (write(fd, snap, strlen(snap)) < 0) return;",
+ "",
+ " sprintf(snap, \"-8:%%d:%%d\\n\", p_reorder==set_randrot, --s_rand);",
+ " if (write(fd, snap, strlen(snap)) < 0) return;",
+ "#endif",
+ "#if NCORE>1 && !defined(SEP_STATE) && defined(FULL_TRAIL)",
+ " rev_trail_cnt = 1;",
+ " enter_critical(GLOBAL_LOCK);",
+ " rev_trail(fd, stack_last[core_id]);",
+ " leave_critical(GLOBAL_LOCK);",
+ "#else",
+ " i = 1; /* trail starts at position 1 */",
+ " #if NCORE>1 && defined(SEP_STATE)",
+ " if (cur_Root.m_vsize > 0) { i++; depth++; }",
+ " #endif",
+ " for ( ; i <= depth; i++)",
" { if (i == depthfound+1)",
- " write(fd, \"-1:-1:-1\\n\", 9);",
+ " { if (write(fd, \"-1:-1:-1\\n\", 9) != 9)",
+ " { goto notgood;",
+ " } }",
" trl = getframe(i);",
" if (!trl->o_t) continue;",
" if (trl->o_pm&128) continue;",
@@ -3997,12 +6520,16 @@
" i, trl->pr, trl->o_t->t_id);",
" j = strlen(snap);",
" if (write(fd, snap, j) != j)",
- " { printf(\"pan: error writing trailfile\\n\");",
+ " {",
+ "notgood: printf(\"pan: error writing trailfile\\n\");",
" close(fd);",
" wrapup();",
- " }",
- " }",
+ " } }",
+ "#endif",
" close(fd);",
+ "#if NCORE>1",
+ " cpu_printf(\"pan: wrote trailfile\\n\");",
+ "#endif",
"}\n",
"void",
"sv_save(void) /* push state vector onto save stack */",
@@ -4022,6 +6549,9 @@
"#if SYNC",
" svtack->o_boq = boq;",
"#endif",
+ "#ifdef TRIX",
+ " sv_populate();",
+ "#endif",
" svtack->o_delta = vsize; /* don't compress */",
" memcpy((char *)(svtack->body), (char *) &now, vsize);",
"#if defined(C_States) && defined(HAS_STACK) && (HAS_TRACK==1)",
@@ -4028,7 +6558,7 @@
" c_stack((uchar *) &(svtack->c_stack[0]));",
"#endif",
"#ifdef DEBUG",
- " printf(\"%%d: sv_save\\n\", depth);",
+ " cpu_printf(\"%%d: sv_save\\n\", depth);",
"#endif",
"}\n",
"void",
@@ -4038,7 +6568,9 @@
"#if SYNC",
" boq = svtack->o_boq;",
"#endif",
-
+ "#ifdef TRIX",
+ " re_populate();",
+ "#endif",
"#if defined(C_States) && (HAS_TRACK==1)",
"#ifdef HAS_STACK",
" c_unstack((uchar *) &(svtack->c_stack[0]));",
@@ -4049,78 +6581,144 @@
" if (vsize != svtack->o_delta)",
" Uerror(\"sv_restor\");",
" if (!svtack->lst)",
- " Uerror(\"error: v_restor\");",
+ " Uerror(\"error: sv_restor\");",
" svtack = svtack->lst;",
"#ifdef DEBUG",
- " printf(\" sv_restor\\n\");",
+ " cpu_printf(\" sv_restor\\n\");",
"#endif",
- "}\n",
+ "}",
+ "",
"void",
"p_restor(int h)",
- "{ int i; char *z = (char *) &now;\n",
+ "{ int i;",
+ " char *z = (char *) &now;\n",
+ "",
+ "#ifdef BFS_PAR",
+ " bfs_prepmask(1); /* p_restor */",
+ "#endif",
+ "#ifndef TRIX",
" proc_offset[h] = stack->o_offset;",
" proc_skip[h] = (uchar) stack->o_skip;",
+ "#else",
+ " char *oi;",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: p_restor %%d\\n\", depth, h);",
+ " #endif",
+ "#endif",
"#ifndef XUSAFE",
" p_name[h] = stack->o_name;",
"#endif",
- "#ifndef NOCOMP",
+ "#ifdef TRIX",
+ " vsize += sizeof(char *);",
+ " #ifndef BFS",
+ " if (processes[h] != NULL || freebodies == NULL)",
+ " { Uerror(\"processes error\");",
+ " }",
+ " processes[h] = freebodies;",
+ " freebodies = freebodies->nxt;",
+ " processes[h]->nxt = (TRIX_v6 *) 0;",
+ " processes[h]->modified = 1; /* p_restor */",
+ " #endif",
+ " processes[h]->parent_pid = stack->parent;",
+ " processes[h]->psize = stack->o_delta;",
+ " memcpy((char *)pptr(h), stack->b_ptr, stack->o_delta);",
+ " oi = stack->b_ptr;",
+ "#else",
+ " #if !defined(NOCOMP) && !defined(HC)",
" for (i = vsize + stack->o_skip; i > vsize; i--)",
" Mask[i-1] = 1; /* align */",
- "#endif",
+ " #endif",
" vsize += stack->o_skip;",
" memcpy(z+vsize, stack->body, stack->o_delta);",
" vsize += stack->o_delta;",
- "#ifndef NOVSZ",
- " now._vsz = vsize;",
- "#endif",
- "#ifndef NOCOMP",
- " for (i = 1; i <= Air[((P0 *)pptr(h))->_t]; i++)",
- " Mask[vsize - i] = 1; /* pad */",
- " Mask[proc_offset[h]] = 1; /* _pid */",
- "#endif",
+ " #if !defined(NOCOMP) && !defined(HC)",
+ " for (i = 1; i <= Air[((P0 *)pptr(h))->_t]; i++)",
+ " Mask[vsize - i] = 1; /* pad */",
+ " Mask[proc_offset[h]] = 1; /* _pid */",
+ " #endif",
" if (BASE > 0 && h > 0)",
" ((P0 *)pptr(h))->_pid = h-BASE;",
" else",
" ((P0 *)pptr(h))->_pid = h;",
- " i = stack->o_delqs;",
+ " #ifdef BFS_PAR",
+ " bfs_fixmask(1); /* p_restor */",
+ " #endif",
+ "#endif",
" now._nr_pr += 1;",
- " if (!stack->lst) /* debugging */",
+ "#ifndef NOVSZ",
+ " now._vsz = vsize;",
+ "#endif",
+ " i = stack->o_delqs;",
+ " if (!stack->lst)",
" Uerror(\"error: p_restor\");",
" stack = stack->lst;",
" this = pptr(h);",
" while (i-- > 0)",
" q_restor();",
+ "#ifdef TRIX",
+ " re_mark_all(1); /* p_restor - all chans move up in _ids_ */",
+ " now._ids_[h] = oi; /* restor the original contents */",
+ "#endif",
"}\n",
"void",
"q_restor(void)",
- "{ char *z = (char *) &now;",
- "#ifndef NOCOMP",
- " int k, k_end;",
- "#endif",
- " q_offset[now._nr_qs] = stack->o_offset;",
- " q_skip[now._nr_qs] = (uchar) stack->o_skip;",
- "#ifndef XUSAFE",
- " q_name[now._nr_qs] = stack->o_name;",
- "#endif",
+ "{ int h = now._nr_qs;",
+ "#ifdef TRIX",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: q_restor %%d\\n\", depth, h);",
+ " #endif",
+ " vsize += sizeof(char *);",
+ " #ifndef BFS",
+ " if (channels[h] != NULL || freebodies == NULL)",
+ " { Uerror(\"channels error\");",
+ " }",
+ " channels[h] = freebodies;",
+ " freebodies = freebodies->nxt;",
+ " channels[h]->nxt = (TRIX_v6 *) 0;",
+ " channels[h]->modified = 1; /* q_restor */",
+ " #endif",
+ " channels[h]->parent_pid = stack->parent;",
+ " channels[h]->psize = stack->o_delta;",
+ " memcpy((char *)qptr(h), stack->b_ptr, stack->o_delta);",
+ " now._ids_[now._nr_pr + h] = stack->b_ptr;",
+ "#else",
+ " char *z = (char *) &now;",
+ " #ifndef NOCOMP",
+ " int k, k_end;",
+ " #endif",
+ " #ifdef BFS_PAR",
+ " bfs_prepmask(2); /* q_restor */",
+ " #endif",
+ " q_offset[h] = stack->o_offset;",
+ " q_skip[h] = (uchar) stack->o_skip;",
" vsize += stack->o_skip;",
" memcpy(z+vsize, stack->body, stack->o_delta);",
" vsize += stack->o_delta;",
+ "#endif",
+ "#ifndef XUSAFE",
+ " q_name[h] = stack->o_name;",
+ "#endif",
"#ifndef NOVSZ",
" now._vsz = vsize;",
"#endif",
" now._nr_qs += 1;",
- "#ifndef NOCOMP",
- " k_end = stack->o_offset;",
- " k = k_end - stack->o_skip;",
- "#if SYNC",
- "#ifndef BFS",
- " if (q_zero(now._nr_qs)) k_end += stack->o_delta;",
+ "#ifndef TRIX",
+ " #if !defined(NOCOMP) && !defined(HC)",
+ " k_end = stack->o_offset;",
+ " k = k_end - stack->o_skip;",
+ " #if SYNC",
+ " #ifndef BFS",
+ " if (q_zero(now._nr_qs)) k_end += stack->o_delta;",
+ " #endif",
+ " #endif",
+ " for ( ; k < k_end; k++)",
+ " Mask[k] = 1;",
+ " #endif",
+ " #ifdef BFS_PAR",
+ " bfs_fixmask(2); /* q_restor */",
+ " #endif",
"#endif",
- "#endif",
- " for ( ; k < k_end; k++)",
- " Mask[k] = 1;",
- "#endif",
- " if (!stack->lst) /* debugging */",
+ " if (!stack->lst)",
" Uerror(\"error: q_restor\");",
" stack = stack->lst;",
"}",
@@ -4163,7 +6761,46 @@
"#ifndef NOCOMP",
" int o_vsize = vsize;",
"#endif",
- " if (h+1 != (int) now._nr_pr) return 0;\n",
+ " if (h+1 != (int) now._nr_pr)",
+ " { return 0;",
+ " }",
+ "#ifdef TRIX",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: delproc %%d -- parent %%d\\n\", depth, h, processes[h]->parent_pid);",
+ " if (now._nr_qs > 0)",
+ " printf(\" top channel: %%d -- parent %%d\\n\", now._nr_qs-1, channels[now._nr_qs-1]->parent_pid);",
+ " #endif",
+ " while (now._nr_qs > 0",
+ " && channels[now._nr_qs-1]->parent_pid == processes[h]->parent_pid)",
+ " { delq(sav);",
+ " i++;",
+ " }",
+ " d = processes[h]->psize;",
+ " if (sav)",
+ " { if (!stack->nxt)",
+ " { stack->nxt = (_Stack *) emalloc(sizeof(_Stack));",
+ " stack->nxt->lst = stack;",
+ " smax++;",
+ " }",
+ " stack = stack->nxt;",
+ " #ifndef XUSAFE",
+ " stack->o_name = p_name[h];",
+ " #endif",
+ " stack->parent = processes[h]->parent_pid;",
+ " stack->o_delta = d;",
+ " stack->o_delqs = i;",
+ " stack->b_ptr = now._ids_[h];", /* new 6.1 */
+ " }",
+ " memset((char *)pptr(h), 0, d);",
+ " #ifndef BFS",
+ " processes[h]->nxt = freebodies;",
+ " freebodies = processes[h];",
+ " processes[h] = (TRIX_v6 *) 0;",
+ " #endif",
+ " vsize -= sizeof(char *);",
+ " now._nr_pr -= 1;",
+ " re_mark_all(-1); /* delproc - all chans move down in _ids_ */",
+ "#else",
" while (now._nr_qs",
" && q_offset[now._nr_qs-1] > proc_offset[h])",
" { delq(sav);",
@@ -4172,80 +6809,116 @@
" d = vsize - proc_offset[h];",
" if (sav)",
" { if (!stack->nxt)",
- " { stack->nxt = (Stack *)",
- " emalloc(sizeof(Stack));",
- " stack->nxt->body = ",
- " emalloc(Maxbody*sizeof(char));",
+ " { stack->nxt = (_Stack *) emalloc(sizeof(_Stack));",
+ " stack->nxt->body = emalloc(Maxbody * sizeof(char));",
" stack->nxt->lst = stack;",
" smax++;",
" }",
" stack = stack->nxt;",
" stack->o_offset = proc_offset[h];",
- "#if VECTORSZ>32000",
+ " #if VECTORSZ>32000",
" stack->o_skip = (int) proc_skip[h];",
- "#else",
+ " #else",
" stack->o_skip = (short) proc_skip[h];",
- "#endif",
- "#ifndef XUSAFE",
+ " #endif",
+ " #ifndef XUSAFE",
" stack->o_name = p_name[h];",
- "#endif",
+ " #endif",
" stack->o_delta = d;",
" stack->o_delqs = i;",
" memcpy(stack->body, (char *)pptr(h), d);",
" }",
" vsize = proc_offset[h];",
- " now._nr_pr = now._nr_pr - 1;",
+ " now._nr_pr -= 1;",
" memset((char *)pptr(h), 0, d);",
" vsize -= (int) proc_skip[h];",
+ " #if !defined(NOCOMP) && !defined(HC)",
+ " #ifdef BFS_PAR",
+ " bfs_prepmask(3); /* delproc - no chance in proc_offset or proc_skip */",
+ " #endif",
+ " for (i = vsize; i < o_vsize; i++)",
+ " Mask[i] = 0; /* reset */",
+ " #ifdef BFS_PAR",
+ " bfs_fixmask(3); /* delproc */",
+ " #endif",
+ " #endif",
+ "#endif",
"#ifndef NOVSZ",
" now._vsz = vsize;",
"#endif",
- "#ifndef NOCOMP",
- " for (i = vsize; i < o_vsize; i++)",
- " Mask[i] = 0; /* reset */",
- "#endif",
" return 1;",
"}\n",
"void",
"delq(int sav)",
"{ int h = now._nr_qs - 1;",
+ "#ifdef TRIX",
+ " int d = channels[now._nr_qs - 1]->psize;",
+ "#else",
" int d = vsize - q_offset[now._nr_qs - 1];",
+ "#endif",
"#ifndef NOCOMP",
" int k, o_vsize = vsize;",
"#endif",
" if (sav)",
" { if (!stack->nxt)",
- " { stack->nxt = (Stack *)",
- " emalloc(sizeof(Stack));",
- " stack->nxt->body = ",
- " emalloc(Maxbody*sizeof(char));",
+ " { stack->nxt = (_Stack *) emalloc(sizeof(_Stack));",
+ "#ifndef TRIX",
+ " stack->nxt->body = emalloc(Maxbody * sizeof(char));",
+ "#endif",
" stack->nxt->lst = stack;",
" smax++;",
" }",
" stack = stack->nxt;",
+ "#ifdef TRIX",
+ " stack->parent = channels[h]->parent_pid;",
+ " stack->b_ptr = now._ids_[h];", /* new 6.1 */
+ "#else",
" stack->o_offset = q_offset[h];",
- "#if VECTORSZ>32000",
+ " #if VECTORSZ>32000",
" stack->o_skip = (int) q_skip[h];",
- "#else",
+ " #else",
" stack->o_skip = (short) q_skip[h];",
+ " #endif",
"#endif",
- "#ifndef XUSAFE",
+ " #ifndef XUSAFE",
" stack->o_name = q_name[h];",
- "#endif",
+ " #endif",
" stack->o_delta = d;",
+ "#ifndef TRIX",
" memcpy(stack->body, (char *)qptr(h), d);",
+ "#endif",
" }",
+ "#ifdef TRIX",
+ " vsize -= sizeof(char *);",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: delq %%d parent %%d\\n\", depth, h, channels[h]->parent_pid);",
+ " #endif",
+ "#else",
" vsize = q_offset[h];",
- " now._nr_qs = now._nr_qs - 1;",
- " memset((char *)qptr(h), 0, d);",
" vsize -= (int) q_skip[h];",
+ " #if !defined(NOCOMP) && !defined(HC)",
+ " #ifdef BFS_PAR",
+ " bfs_prepmask(3); /* delq - no change in q_offset or q_skip */",
+ " #endif",
+ " for (k = vsize; k < o_vsize; k++)",
+ " Mask[k] = 0; /* reset */",
+ " #ifdef BFS_PAR",
+ " bfs_fixmask(3); /* delq */",
+ " #endif",
+ " #endif",
+ "#endif",
+ " now._nr_qs -= 1;",
+ " memset((char *)qptr(h), 0, d);",
+ "#ifdef TRIX",
+ " #ifndef BFS",
+ " channels[h]->nxt = freebodies;",
+ " freebodies = channels[h];",
+ " channels[h] = (TRIX_v6 *) 0;",
+ " #endif",
+ "#endif",
"#ifndef NOVSZ",
" now._vsz = vsize;",
"#endif",
- "#ifndef NOCOMP",
- " for (k = vsize; k < o_vsize; k++)",
- " Mask[k] = 0; /* reset */",
- "#endif",
"}\n",
"int",
"qs_empty(void)",
@@ -4265,7 +6938,7 @@
" return 0;",
" }",
" if (strict) return qs_empty();",
- "#if defined(EVENT_TRACE) && !defined(OTIM)",
+ "#if defined(EVENT_TRACE)",
" if (!stopstate[EVENT_TRACE][now._event] && !a_cycles)",
" { printf(\"pan: event_trace not completed\\n\");",
" return 0;",
@@ -4273,55 +6946,54 @@
"#endif",
" return 1;",
"}\n",
- "#ifndef SAFETY",
+ "#if !defined(SAFETY) && !defined(BFS)",
"void",
"checkcycles(void)",
"{ uchar o_a_t = now._a_t;",
- "#ifndef NOFAIR",
- " uchar o_cnt = now._cnt[1];",
- "#endif",
- "#ifdef FULLSTACK",
- "#ifndef MA",
- " struct H_el *sv = trpt->ostate; /* save */",
- "#else",
- " uchar prov = trpt->proviso; /* save */",
- "#endif",
- "#endif",
- "#ifdef DEBUG",
- " { int i; uchar *v = (uchar *) &now;",
- " printf(\" set Seed state \");",
- "#ifndef NOFAIR",
- " if (fairness) printf(\"(cnt = %%d:%%d, nrpr=%%d) \",",
- " now._cnt[0], now._cnt[1], now._nr_pr);",
- "#endif",
- " /* for (i = 0; i < n; i++) printf(\"%%d,\", v[i]); */",
- " printf(\"\\n\");",
- " }",
- " printf(\"%%d: cycle check starts\\n\", depth);",
- "#endif",
+ " #ifndef NOFAIR",
+ " uchar o_cnt = now._cnt[1];",
+ " #endif",
+ " #ifdef FULLSTACK",
+ " #ifndef MA",
+ " H_el *sv = trpt->ostate; /* save */",
+ " #else",
+ " uchar prov = trpt->proviso; /* save */",
+ " #endif",
+ " #endif",
+ " #ifdef DEBUG",
+ " { int i; uchar *v = (uchar *) &now;",
+ " printf(\" set Seed state \");",
+ " #ifndef NOFAIR",
+ " if (fairness)",
+ " printf(\"(cnt = %%d:%%d, nrpr=%%d) \",",
+ " now._cnt[0], now._cnt[1], now._nr_pr);",
+ " #endif",
+ " /* for (i = 0; i < n; i++) printf(\"%%d,\", v[i]); */",
+ " printf(\"\\n\");",
+ " }",
+ " printf(\"%%ld: cycle check starts\\n\", depth);",
+ " #endif",
" now._a_t |= (1|16|32);",
- " /* 1 = 2nd DFS; (16|32) to help hasher */",
- "#ifndef NOFAIR",
-#if 0
- " if (fairness)",
- " { now._a_t &= ~2; /* pre-apply Rule 3 */",
- " now._cnt[1] = 0;", /* reset both a-bit and cnt=0 */
- " /* avoid matching seed on claim stutter on this state */",
- " }",
-#else
- " now._cnt[1] = now._cnt[0];",
-#endif
- "#endif",
+ " /* 1 = 2nd DFS; (16|32) to improve hashing */",
+ " #ifndef NOFAIR",
+ " now._cnt[1] = now._cnt[0];",
+ " #endif",
" memcpy((char *)&A_Root, (char *)&now, vsize);",
" A_depth = depthfound = depth;",
- " new_state(); /* start 2nd DFS */",
+
+ " #if NCORE>1",
+ " mem_put_acc();", /* handoff accept states */
+ " #else",
+ " new_state(); /* start 2nd DFS */",
+ " #endif",
+
" now._a_t = o_a_t;",
- "#ifndef NOFAIR",
- " now._cnt[1] = o_cnt;",
- "#endif",
+ " #ifndef NOFAIR",
+ " now._cnt[1] = o_cnt;",
+ " #endif",
" A_depth = 0; depthfound = -1;",
"#ifdef DEBUG",
- " printf(\"%%d: cycle check returns\\n\", depth);",
+ " printf(\"%%ld: cycle check returns\\n\", depth);",
"#endif",
"#ifdef FULLSTACK",
"#ifndef MA",
@@ -4331,60 +7003,120 @@
"#endif",
"#endif",
"}",
- "#endif\n",
+ "#endif",
+ "",
"#if defined(FULLSTACK) && defined(BITSTATE)",
- "struct H_el *Free_list = (struct H_el *) 0;",
+ "H_el *Free_list = (H_el *) 0;",
"void",
"onstack_init(void) /* to store stack states in a bitstate search */",
- "{ S_Tab = (struct H_el **) emalloc(maxdepth*sizeof(struct H_el *));",
+ "{ S_Tab = (H_el **) emalloc(maxdepth*sizeof(H_el *));",
"}",
- "struct H_el *",
- "grab_state(int n)",
- "{ struct H_el *v, *last = 0;",
- " if (H_tab == S_Tab)",
- " { for (v = Free_list; v && ((int) v->tagged >= n); v=v->nxt)",
- " { if ((int) v->tagged == n)",
- " { if (last)",
- " last->nxt = v->nxt;",
- " else",
- "gotcha: Free_list = v->nxt;",
- " v->tagged = 0;",
- " v->nxt = 0;",
- "#ifdef COLLAPSE",
- " v->ln = 0;",
- "#endif",
- " return v;",
- " }",
- " Fh++; last=v;",
- " }",
- " /* new: second try */",
- " v = Free_list;", /* try to avoid emalloc */
- " if (v && ((int) v->tagged >= n))",
- " goto gotcha;",
- " ngrabs++;",
- " }",
- " return (struct H_el *)",
- " emalloc(sizeof(struct H_el)+n-sizeof(unsigned));",
- "}\n",
- "#else",
- "#define grab_state(n) (struct H_el *) \\",
- " emalloc(sizeof(struct H_el)+n-sizeof(unsigned));",
"#endif",
+
+ "#if !defined(BFS_PAR)",
+ " #if defined(FULLSTACK) && defined(BITSTATE)",
+ "H_el *",
+ "grab_state(int n)",
+ "{ H_el *v, *last = 0;",
+ " if (H_tab == S_Tab)",
+ " { for (v = Free_list; v && ((int) v->tagged >= n); v=v->nxt)",
+ " { if ((int) v->tagged == n)",
+ " { if (last)",
+ " last->nxt = v->nxt;",
+ " else",
+ "gotcha: Free_list = v->nxt;",
+ " v->tagged = 0;",
+ " v->nxt = 0;",
+ " #ifdef COLLAPSE",
+ " v->ln = 0;",
+ " #endif",
+ " return v;",
+ " }",
+ " Fh++; last=v;",
+ " }",
+ " /* new: second try */",
+ " v = Free_list;", /* try to avoid emalloc */
+ " if (v && ((int) v->tagged >= n))",
+ " goto gotcha;",
+ " ngrabs++;",
+ " }",
+ " return (H_el *) emalloc(sizeof(H_el)+n-sizeof(unsigned));",
+ "}",
+ " #else", /* !FULLSTACK || !BITSTATE */
+ "#if NCORE>1",
+ "H_el *",
+ "grab_state(int n)",
+ "{ H_el *grab_shared(int);",
+ " return grab_shared(sizeof(H_el)+n-sizeof(unsigned));",
+ "}",
+ "#else", /* ! NCORE>1 */
+ "#ifndef AUTO_RESIZE",
+ " #define grab_state(n) (H_el *) \\",
+ " emalloc(sizeof(H_el)+n-sizeof(ulong));",
+ "#else", /* AUTO_RESIZE */
+ "H_el *",
+ "grab_state(int n)",
+ "{ H_el *p;",
+ " int cnt = sizeof(H_el)+n-sizeof(ulong);",
+ "#ifndef MA",
+ " if (reclaim_size >= cnt+WS)",
+ " { if ((cnt & (WS-1)) != 0) /* alignment */",
+ " { cnt += WS - (cnt & (WS-1));",
+ " }",
+ " p = (H_el *) reclaim_mem;",
+ " reclaim_mem += cnt;",
+ " reclaim_size -= cnt;",
+ " memset(p, 0, cnt);",
+ " } else",
+ "#endif",
+ " { p = (H_el *) emalloc(cnt);",
+ " }",
+ " return p;",
+ "}",
+ "#endif", /* AUTO_RESIZE */
+ "#endif", /* NCORE>1 */
+ " #endif", /* FULLSTACK && !BITSTATE */
+ "#else", /* BFS_PAR */
+ " extern volatile uchar *sh_pre_malloc(ulong);",
+ " extern volatile uchar *sh_malloc(ulong);",
+ " H_el *",
+ " grab_state(int n) /* bfs_par */",
+ " { volatile uchar *rval = NULL;",
+ " int m = sizeof(H_el) + n - sizeof(unsigned);",
+ "",
+ " if (n == 0) m = m/n;",
+ " #ifdef BFS_SEP_HASH",
+ " rval = emalloc((ulong) m);",
+ " #else",
+ " rval = sh_malloc((ulong) m);",
+ " #endif",
+ " memset((void *) rval, 0, (size_t) m);",
+ "",
+ " return (H_el *) rval;",
+ " }",
+ "#endif", /* BFS_PAR */
+
"#ifdef COLLAPSE",
- "unsigned long",
+ "ulong",
"ordinal(char *v, long n, short tp)",
- "{ struct H_el *tmp, *ntmp; long m;",
- " struct H_el *olst = (struct H_el *) 0;",
+ "{ H_el *tmp, *ntmp; long m;",
+ " H_el *olst = (H_el *) 0;",
" s_hash((uchar *)v, n);",
- " tmp = H_tab[j1];",
+
+ "#if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " e_critical(BFS_ID); /* bfs_par / collapse */",
+ "#endif",
+ "#if NCORE>1 && !defined(SEP_STATE)",
+ " enter_critical(CS_ID); /* uses spinlock - 1..128 */",
+ "#endif",
+ " tmp = H_tab[j1_spin];",
" if (!tmp)",
" { tmp = grab_state(n);",
- " H_tab[j1] = tmp;",
+ " H_tab[j1_spin] = tmp;",
" } else",
" for ( ;; olst = tmp, tmp = tmp->nxt)",
- " { m = memcmp(((char *)&(tmp->state)), v, n);",
- " if (n == tmp->ln)",
- " {",
+ " { if (n == tmp->ln)",
+ " { m = memcmp(((char *)&(tmp->state)), v, n);",
" if (m == 0)",
" goto done;",
" if (m < 0)",
@@ -4392,7 +7124,7 @@
"Insert: ntmp = grab_state(n);",
" ntmp->nxt = tmp;",
" if (!olst)",
- " H_tab[j1] = ntmp;",
+ " H_tab[j1_spin] = ntmp;",
" else",
" olst->nxt = ntmp;",
" tmp = ntmp;",
@@ -4410,15 +7142,38 @@
" else if (!tmp->nxt)",
" goto Append;",
" }",
+ "#if NCORE>1 && !defined(SEP_STATE)",
+ " enter_critical(GLOBAL_LOCK);",
+ "#endif",
+ "#ifdef BFS_PAR",
+ " e_critical(BFS_ORD); /* bfs_par */",
+ "#endif",
" m = ++ncomps[tp];",
+ "#ifdef BFS_PAR",
+ " x_critical(BFS_ORD);",
+ "#endif",
+ "#if NCORE>1 && !defined(SEP_STATE)",
+ " leave_critical(GLOBAL_LOCK);",
+ "#endif",
"#ifdef FULLSTACK",
" tmp->tagged = m;",
"#else",
" tmp->st_id = m;",
"#endif",
+ "#if defined(AUTO_RESIZE) && !defined(BITSTATE)",
+ " tmp->m_K1 = K1;",
+ "#endif",
" memcpy(((char *)&(tmp->state)), v, n);",
" tmp->ln = n;",
"done:",
+
+ "#if NCORE>1 && !defined(SEP_STATE)",
+ " leave_critical(CS_ID);",
+ "#endif",
+ "#if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " x_critical(BFS_ID);",
+ "#endif",
+
"#ifdef FULLSTACK",
" return tmp->tagged;",
"#else",
@@ -4430,7 +7185,7 @@
"compress(char *vin, int nin) /* collapse compression */",
"{ char *w, *v = (char *) &comp_now;",
" int i, j;",
- " unsigned long n;",
+ " ulong n;",
" static char *x;",
" static uchar nbytes[513]; /* 1 + 256 + 256 */",
" static unsigned short nbytelen;",
@@ -4523,7 +7278,7 @@
"#if VECTORSZ<65536",
" w = (char *) &(now._vsz) + sizeof(unsigned short);",
"#else",
- " w = (char *) &(now._vsz) + sizeof(unsigned long);",
+ " w = (char *) &(now._vsz) + sizeof(ulong);",
"#endif",
"#endif",
" x = scratch;",
@@ -4535,8 +7290,14 @@
" else",
" n = pptr(0) - (uchar *) w;",
" j = w - (char *) &now;",
+ "",
+ "#if !defined(NOCOMP) && !defined(HC)",
" for (i = 0; i < (int) n; i++, w++)",
" if (!Mask[j++]) *x++ = *w;",
+ "#else",
+ " memcpy(x, w, n); x += n;",
+ "#endif",
+ "",
"#ifndef SEPQS",
" for (i = 0; i < (int) now._nr_qs; i++)",
" x += col_q(i, x);",
@@ -4572,7 +7333,7 @@
" return v - (char *)&comp_now;",
"}",
-"#else",
+"#else", /* !COLLAPSE */
"#if !defined(NOCOMP)",
"int",
"compress(char *vin, int n) /* default compression */",
@@ -4600,11 +7361,56 @@
" char *vv = vin;",
" char *v = (char *) &comp_now;",
" int i;",
- " for (i = 0; i < n; i++, vv++)",
- " if (!Mask[i]) *v++ = *vv;",
- " for (i = 0; i < WS-1; i++)",
- " *v++ = 0;",
- " v -= i;",
+ " #ifndef NO_FAST_C", /* disable faster compress */
+ " int r = 0, unroll = n/8;", /* most sv are much longer */
+ " if (unroll > 0)",
+ " { i = 0;",
+ " while (r++ < unroll)",
+ " { /* unroll 8 times, avoid ifs */",
+ " /* 1 */ *v = *vv++; v += 1 - Mask[i++];",
+ " /* 2 */ *v = *vv++; v += 1 - Mask[i++];",
+ " /* 3 */ *v = *vv++; v += 1 - Mask[i++];",
+ " /* 4 */ *v = *vv++; v += 1 - Mask[i++];",
+ " /* 5 */ *v = *vv++; v += 1 - Mask[i++];",
+ " /* 6 */ *v = *vv++; v += 1 - Mask[i++];",
+ " /* 7 */ *v = *vv++; v += 1 - Mask[i++];",
+ " /* 8 */ *v = *vv++; v += 1 - Mask[i++];",
+ " }",
+ " r = n - i; /* the rest, at most 7 */",
+ " switch (r) {",
+ " case 7: *v = *vv++; v += 1 - Mask[i++];",
+ " case 6: *v = *vv++; v += 1 - Mask[i++];",
+ " case 5: *v = *vv++; v += 1 - Mask[i++];",
+ " case 4: *v = *vv++; v += 1 - Mask[i++];",
+ " case 3: *v = *vv++; v += 1 - Mask[i++];",
+ " case 2: *v = *vv++; v += 1 - Mask[i++];",
+ " case 1: *v = *vv++; v += 1 - Mask[i++];",
+ " case 0: break;",
+ " }",
+ " n = i = v - (char *)&comp_now; /* bytes written so far */",
+ " r = (n+WS-1)/WS; /* in words, rounded up */",
+ " r *= WS; /* total bytes to fill */",
+ " i = r - i; /* remaining bytes */",
+ " switch (i) {", /* fill word */
+ " case 7: *v++ = 0; /* fall thru */",
+ " case 6: *v++ = 0;",
+ " case 5: *v++ = 0;",
+ " case 4: *v++ = 0;",
+ " case 3: *v++ = 0;",
+ " case 2: *v++ = 0;",
+ " case 1: *v++ = 0;",
+ " case 0: break;",
+ " default: Uerror(\"unexpected wordsize\");",
+ " }",
+ " v -= i;",
+ " } else",
+ " #endif",
+ " { for (i = 0; i < n; i++, vv++)",
+ " if (!Mask[i]) *v++ = *vv;",
+ " for (i = 0; i < WS-1; i++)",
+ " *v++ = 0;",
+ " v -= i;",
+ " }",
"#if 0",
" printf(\"compress %%d -> %%d\\n\",",
" n, v - (char *)&comp_now);",
@@ -4613,7 +7419,7 @@
"#endif",
"}",
"#endif",
-"#endif",
+"#endif", /* COLLAPSE */
"#if defined(FULLSTACK) && defined(BITSTATE)",
"#if defined(MA)",
"#if !defined(onstack_now)",
@@ -4628,9 +7434,15 @@
"#else",
"void",
"onstack_zap(void)",
- "{ struct H_el *v, *w, *last = 0;",
- " struct H_el **tmp = H_tab;",
- " char *nv; int n, m;\n",
+ "{ H_el *v, *w, *last = 0;",
+ " H_el **tmp = H_tab;",
+ " char *nv; int n, m;",
+ " static char warned = 0;",
+ "#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+ " uchar was_last = now._last;",
+ " now._last = 0;",
+ "#endif",
+ "",
" H_tab = S_Tab;",
"#ifndef NOCOMP",
" nv = (char *) &comp_now;",
@@ -4648,7 +7460,7 @@
" s_hash((uchar *)nv, n);",
"#endif",
" H_tab = tmp;",
- " for (v = S_Tab[j1]; v; Zh++, last=v, v=v->nxt)",
+ " for (v = S_Tab[j1_spin]; v; Zh++, last=v, v=v->nxt)",
" { m = memcmp(&(v->state), nv, n);",
" if (m == 0)",
" goto Found;",
@@ -4656,101 +7468,190 @@
" break;",
" }",
"/* NotFound: */",
- " Uerror(\"stack out of wack - zap\");",
- " return;",
+ "#ifndef ZAPH",
+ " /* seen this happen, likely harmless in multicore */",
+ " if (warned == 0)",
+ " { /* Uerror(\"stack out of wack - zap\"); */",
+ " cpu_printf(\"pan: warning, stack incomplete\\n\");",
+ " warned = 1;",
+ " }",
+ "#endif",
+ " goto done;",
"Found:",
" ZAPS++;",
" if (last)",
" last->nxt = v->nxt;",
" else",
- " S_Tab[j1] = v->nxt;",
+ " S_Tab[j1_spin] = v->nxt;",
" v->tagged = (unsigned) n;",
"#if !defined(NOREDUCE) && !defined(SAFETY)",
" v->proviso = 0;",
"#endif",
- " v->nxt = last = (struct H_el *) 0;",
+ " v->nxt = last = (H_el *) 0;",
" for (w = Free_list; w; Fa++, last=w, w = w->nxt)",
" { if ((int) w->tagged <= n)",
" { if (last)",
- " { v->nxt = w; /* was: v->nxt = w->nxt; */",
+ " { v->nxt = w;",
" last->nxt = v;",
" } else",
" { v->nxt = Free_list;",
" Free_list = v;",
" }",
- " return;",
+ " goto done;",
" }",
" if (!w->nxt)",
" { w->nxt = v;",
- " return;",
+ " goto done;",
" } }",
" Free_list = v;",
- "}",
- "void",
- "onstack_put(void)",
- "{ struct H_el **tmp = H_tab;",
- " H_tab = S_Tab;",
- " if (hstore((char *)&now, vsize) != 0)",
- "#if defined(BITSTATE) && defined(LC)",
- " printf(\"pan: warning, double stack entry\\n\");",
- "#else",
- " Uerror(\"cannot happen - unstack_put\");",
+ "done:",
+ "#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+ " now._last = was_last;",
"#endif",
- " H_tab = tmp;",
- " trpt->ostate = Lstate;",
- " PUT++;",
+ " return;",
"}",
- "int",
- "onstack_now(void)",
- "{ struct H_el *tmp;",
- " struct H_el **tmp2 = H_tab;",
- " char *v; int n, m = 1;\n",
- " H_tab = S_Tab;",
- "#ifdef NOCOMP",
- "#if defined(BITSTATE) && defined(LC)",
- " v = (char *) &comp_now;",
- " n = compact_stack((char *)&now, vsize);",
- "#else",
- " v = (char *) &now;",
- " n = vsize;",
- "#endif",
- "#else",
- " v = (char *) &comp_now;",
- " n = compress((char *)&now, vsize);",
- "#endif",
- "#if !defined(HC) && !(defined(BITSTATE) && defined(LC))",
- " s_hash((uchar *)v, n);",
- "#endif",
- " H_tab = tmp2;",
- " for (tmp = S_Tab[j1]; tmp; Zn++, tmp = tmp->nxt)",
- " { m = memcmp(((char *)&(tmp->state)),v,n);",
- " if (m <= 0)",
- " { Lstate = (struct H_el *) tmp;",
- " break;",
- " } }",
- " PROBE++;",
- " return (m == 0);",
- "}",
- "#endif",
-"#endif",
+ "",
+ "#ifndef BFS_PAR",
+ " void",
+ " onstack_put(void)",
+ " { H_el **tmp = H_tab;",
+ " #if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+ " uchar was_last = now._last;",
+ " now._last = 0;",
+ " #endif",
+ " H_tab = S_Tab;",
+ " if (h_store((char *)&now, vsize) != 0)",
+ " #if defined(BITSTATE) && defined(LC)",
+ " printf(\"pan: warning, double stack entry\\n\");",
+ " #else",
+ " #ifndef ZAPH",
+ " Uerror(\"cannot happen - unstack_put\");",
+ " #endif",
+ " #endif",
+ " H_tab = tmp;",
+ " trpt->ostate = Lstate;",
+ " PUT++;",
+ " #if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+ " now._last = was_last;",
+ " #endif",
+ " }",
+ " int",
+ " onstack_now(void)",
+ " { H_el *tmp;",
+ " H_el **tmp2 = H_tab;",
+ " char *v; int n, m = 1;\n",
+ " #if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+ " uchar was_last = now._last;",
+ " now._last = 0;",
+ " #endif",
+ " H_tab = S_Tab;",
+ " #ifdef NOCOMP",
+ " #if defined(BITSTATE) && defined(LC)",
+ " v = (char *) &comp_now;",
+ " n = compact_stack((char *)&now, vsize);",
+ " #else",
+ " v = (char *) &now;",
+ " n = vsize;",
+ " #endif",
+ " #else",
+ " v = (char *) &comp_now;",
+ " n = compress((char *)&now, vsize);",
+ " #endif",
+ " #if !defined(HC) && !(defined(BITSTATE) && defined(LC))",
+ " s_hash((uchar *)v, n);",
+ " #endif",
+ " H_tab = tmp2;",
+ " for (tmp = S_Tab[j1_spin]; tmp; Zn++, tmp = tmp->nxt)",
+ " { m = memcmp(((char *)&(tmp->state)),v,n);",
+ " if (m <= 0)",
+ " { Lstate = (H_el *) tmp; /* onstack_now */",
+ " break;",
+ " } }",
+ " PROBE++;",
+ " #if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+ " now._last = was_last;",
+ " #endif",
+ " return (m == 0);",
+ " }",
+ "#endif", /* !BFS_PAR */
+"#endif", /* !MA */
+ "#endif", /* FULLSTACK && BITSTATE */
- "#ifndef BITSTATE",
+ "#ifdef BITSTATE",
+ "void init_SS(ulong);",
+ "",
"void",
- "hinit(void)",
+ "sinit(void)",
"{",
-"#ifdef MA",
- "#ifdef R_XPT",
- " { void r_xpoint(void);",
- " r_xpoint();",
+ " if (udmem)",
+ " { udmem *= 1024L*1024L;",
+ " #if NCORE>1",
+ " if (!readtrail)",
+ " { init_SS((ulong) udmem);",
+ " } else",
+ " #endif",
+ " #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " SS = (uchar *) sh_pre_malloc((ulong) udmem);",
+ " #else",
+ " SS = (uchar *) emalloc(udmem);",
+ " #endif",
+ " b_store = bstore_mod;",
+ " } else",
+ " {",
+ " #if NCORE>1",
+ " init_SS(ONE_L<<(ssize-3));",
+ " #else",
+ " #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " SS = (uchar *) sh_pre_malloc((ulong)(ONE_L<<(ssize-3)));",
+ " #else",
+ " SS = (uchar *) emalloc(ONE_L<<(ssize-3));",
+ " #endif",
+ " #endif",
" }",
+ "}",
"#else",
- " dfa_init((unsigned short) (MA+a_cycles));",
- "#endif",
-"#endif",
-"#if !defined(MA) || defined(COLLAPSE)",
- " H_tab = (struct H_el **)",
- " emalloc((1L<<ssize)*sizeof(struct H_el *));",
-"#endif",
+ " #if !defined(MA) || defined(COLLAPSE)",
+ " void",
+ " set_H_tab(void)",
+ " {",
+ " #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " H_tab = (H_el **) sh_pre_malloc((ulong)((ONE_L<<ssize)*sizeof(H_el *)));",
+ " #else",
+ " H_tab = (H_el **) emalloc((ONE_L<<ssize)*sizeof(H_el *));",
+ " #endif",
+ " }",
+ " #endif",
+ "void",
+ "hinit(void)",
+ "{",
+ " #ifdef MA",
+ " #ifdef R_XPT",
+ " { void r_xpoint(void);",
+ " r_xpoint();",
+ " }",
+ " #else",
+ " dfa_init((unsigned short) (MA+a_cycles));",
+ " #if NCORE>1 && !defined(COLLAPSE)",
+ " if (!readtrail)",
+ " { void init_HT(ulong);",
+ " init_HT(0L);",
+ " }",
+ " #endif",
+ " #endif",
+ " #endif",
+ " #if !defined(MA) || defined(COLLAPSE)",
+ " #if NCORE>1 || (defined(BFS_PAR) && defined(USE_TDH) && !defined(WIN32) && !defined(WIN64))",
+ " if (!readtrail)",
+ " { void init_HT(ulong);",
+ " init_HT((ulong) (ONE_L<<ssize)*sizeof(H_el *));",
+ " #if defined(TRIX) || (defined(BFS_PAR) && defined(COLLAPSE))",
+ " set_H_tab(); /* need both */",
+ " #endif",
+ " } else",
+ " #endif",
+ " { set_H_tab(); /* @htable ssize */",
+ " }",
+ " #endif", /* !defined(MA) || defined(COLLAPSE) */
"}",
"#endif\n",
@@ -4771,13 +7672,17 @@
" }",
"#endif",
"#ifdef SDUMP",
- "#ifndef NOCOMP",
" printf(\"\t State: \");",
+ "#if !defined(NOCOMP) && !defined(HC)",
" for (i = 0; i < vsize; i++) printf(\"%%d%%s,\",",
" ((char *)&now)[i], Mask[i]?\"*\":\"\");",
+ "#else",
+ " for (i = 0; i < vsize; i++)",
+ " printf(\"%%d,\", ((char *)&now)[i]);",
"#endif",
" printf(\"\\n\tVector: \");",
- " for (i = 0; i < n; i++) printf(\"%%d,\", v[i]);",
+ " for (i = 0; i < n; i++)",
+ " printf(\"%%d,\", v[i]);",
" printf(\"\\n\");",
"#endif",
"}",
@@ -4785,8 +7690,9 @@
"#ifdef MA",
"int",
- "gstore(char *vin, int nin, uchar pbit)",
+ "g_store(char *vin, int nin, uchar pbit)",
"{ int n, i;",
+ " int ret_val = 1;",
" uchar *v;",
" static uchar Info[MA+1];",
"#ifndef NOCOMP",
@@ -4794,7 +7700,7 @@
" v = (uchar *) &comp_now;",
"#else",
" n = nin;",
- " v = vin;",
+ " v = (uchar *) vin;",
"#endif",
" if (n >= MA)",
" { printf(\"pan: error, MA too small, recompile pan.c\");",
@@ -4801,15 +7707,29 @@
" printf(\" with -DMA=N with N>%%d\\n\", n);",
" Uerror(\"aborting\");",
" }",
- " if (n > (int) maxgs) maxgs = (unsigned int) n;",
-
+ " if (n > (int) maxgs)",
+ " { maxgs = (uint) n;",
+ " }",
" for (i = 0; i < n; i++)",
- " Info[i] = v[i];",
+ " { Info[i] = v[i];",
+ " }",
" for ( ; i < MA-1; i++)",
- " Info[i] = 0;",
+ " { Info[i] = 0;",
+ " }",
" Info[MA-1] = pbit;",
" if (a_cycles) /* place _a_t at the end */",
- " { Info[MA] = Info[0]; Info[0] = 0; }",
+ " { Info[MA] = Info[0];",
+ " Info[0] = 0;",
+ " }",
+ "",
+ "#ifdef BFS_PAR",
+ " e_critical(BFS_STATE); /* bfs_par / g_store */",
+ "#endif",
+ "#if NCORE>1 && !defined(SEP_STATE)",
+ " enter_critical(GLOBAL_LOCK); /* crude, but necessary */",
+ " /* to make this mode work, also replace emalloc with grab_shared inside store MA routines */",
+ "#endif",
+ "",
" if (!dfa_store(Info))",
" { if (pbit == 0",
" && (now._a_t&1)",
@@ -4819,16 +7739,17 @@
" { Info[MA-1] = 4; /* off-stack bit */",
" nShadow++;",
" if (!dfa_member(MA-1))",
- " {",
- "#ifdef VERBOSE",
- " printf(\"intersected 1st dfs stack\\n\");",
- "#endif",
- " return 3;",
+ " { ret_val = 3;",
+ " #ifdef VERBOSE",
+ " printf(\"intersected 1st dfs stack\\n\");",
+ " #endif",
+ " goto done;",
" } } }",
- "#ifdef VERBOSE",
+ " ret_val = 0;",
+ " #ifdef VERBOSE",
" printf(\"new state\\n\");",
- "#endif",
- " return 0; /* new state */",
+ " #endif",
+ " goto done;",
" }",
"#ifdef FULLSTACK",
" if (pbit == 0)",
@@ -4837,23 +7758,32 @@
" trpt->proviso = dfa_member(MA-1);",
"#endif",
" Info[MA-1] = 4; /* off-stack bit */",
- " if (dfa_member(MA-1)) {",
- "#ifdef VERBOSE",
+ " if (dfa_member(MA-1))",
+ " { ret_val = 1; /* off-stack */",
+ " #ifdef VERBOSE",
" printf(\"old state\\n\");",
- "#endif",
- " return 1; /* off-stack */",
- " } else {",
- "#ifdef VERBOSE",
+ " #endif",
+ " } else",
+ " { ret_val = 2; /* on-stack */",
+ " #ifdef VERBOSE",
" printf(\"on-stack\\n\");",
- "#endif",
- " return 2; /* on-stack */",
+ " #endif",
" }",
+ " goto done;",
" }",
"#endif",
+ " ret_val = 1;",
"#ifdef VERBOSE",
- " printf(\"old state\\n\");",
+ " printf(\"old state\\n\");",
"#endif",
- " return 1; /* old state */",
+ "done:",
+ "#ifdef BFS_PAR",
+ " x_critical(BFS_STATE);",
+ "#endif",
+ "#if NCORE>1 && !defined(SEP_STATE)",
+ " leave_critical(GLOBAL_LOCK);",
+ "#endif",
+ " return ret_val; /* old state */",
"}",
"#endif",
@@ -4873,15 +7803,120 @@
"}",
"#endif",
+ "#ifdef TRIX",
+ "void",
+ "sv_populate(void)",
+ "{ int i, cnt = 0;",
+ " TRIX_v6 **base = processes;",
+ " int bound = now._nr_pr; /* MAXPROC+1; */",
+ "#ifdef V_TRIX",
+ " printf(\"%%4d: sv_populate\\n\", depth);",
+ "#endif",
+ "again:",
+ " for (i = 0; i < bound; i++)",
+ " { if (base[i] != NULL)",
+ " { H_el *tmp;",
+ " int m, n; uchar *v;",
+ "#ifndef BFS",
+ " if (base[i]->modified == 0)",
+ " { cnt++;",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: %%s %%d not modified\\n\",",
+ " depth, (base == processes)?\"proc\":\"chan\", i);",
+ " #endif",
+ " continue;",
+ " }",
+ " #ifndef V_MOD",
+ " base[i]->modified = 0;",
+ " #endif",
+ "#endif",
+ "#ifdef TRIX_RIX",
+ " if (base == processes)",
+ " { ((P0 *)pptr(i))->_pid = 0;",
+ " }",
+ "#endif",
+ " n = base[i]->psize;",
+ " v = base[i]->body;",
+ " s_hash(v, n); /* sets j1_spin */",
+ " tmp = H_tab[j1_spin];",
+ " if (!tmp) /* new */",
+ " { tmp = grab_state(n);",
+ " H_tab[j1_spin] = tmp;",
+ " m = 1; /* non-zero */",
+ " } else",
+ " { H_el *ntmp, *olst = (H_el *) 0;",
+ " for (;; hcmp++, olst = tmp, tmp = tmp->nxt)",
+ " { m = memcmp(((char *)&(tmp->state)), v, n);",
+ " if (m == 0) /* match */",
+ " { break;",
+ " } else if (m < 0) /* insert */",
+ " { ntmp = grab_state(n);",
+ " ntmp->nxt = tmp;",
+ " if (!olst)",
+ " H_tab[j1_spin] = ntmp;",
+ " else",
+ " olst->nxt = ntmp;",
+ " tmp = ntmp;",
+ " break;",
+ " } else if (!tmp->nxt) /* append */",
+ " { tmp->nxt = grab_state(n);",
+ " tmp = tmp->nxt;",
+ " break;",
+ " } } }",
+ " if (m != 0)",
+ " { memcpy((char *)&(tmp->state), v, n);",
+ "#if defined(AUTO_RESIZE) && !defined(BITSTATE)",
+ " tmp->m_K1 = K1; /* set via s_hash */",
+ "#endif",
+ " if (verbose)",
+ " { if (base == processes)",
+ " { _p_count[i]++;",
+ " } else",
+ " { _c_count[i]++;",
+ " } } }",
+ " now._ids_[cnt++] = (char *)&(tmp->state);",
+ "#ifdef TRIX_RIX",
+ " if (base == processes)",
+ " { ((P0 *)pptr(i))->_pid = i;",
+ " if (BASE > 0 && i > 0)",
+ " { ((P0 *)pptr(i))->_pid -= BASE;",
+ " } }",
+ "#endif",
+ " } }",
+#if 0
+ if a process appears or disappears: always secure a full sv_populate
+ (channels come and go only with a process)
+
+ only one process can disappear per step
+ but any nr of channels can be removed at the same time
+ if a process disappears, all subsequent entries
+ are then in the wrong place in the _ids_ list
+ and need to be recomputed
+ but we do not need to fill out with zeros
+ because vsize prevents them being used
+#endif
+ " /* do the same for all channels */",
+ " if (base == processes)",
+ " { base = channels;",
+ " bound = now._nr_qs; /* MAXQ+1; */",
+ " goto again;",
+ " }",
+ "}",
+ "#endif\n",
+ "#if !defined(BFS_PAR) || (!defined(BITSTATE) && !defined(USE_TDH))",
"int",
- "hstore(char *vin, int nin) /* hash table storage */",
- "{ struct H_el *tmp, *ntmp, *olst = (struct H_el *) 0;",
+ "h_store(char *vin, int nin) /* hash table storage */",
+ "{ H_el *ntmp;",
+ " H_el *tmp, *olst = (H_el *) 0;",
" char *v; int n, m=0;",
- "#ifdef HC",
+ " #ifdef HC",
" uchar rem_a;",
- "#endif",
- "#ifdef NOCOMP", /* defined by BITSTATE */
- "#if defined(BITSTATE) && defined(LC)",
+ " #endif",
+ " #ifdef TRIX",
+ " sv_populate(); /* update proc and chan ids */",
+ " #endif",
+ " #ifdef NOCOMP", /* defined by BITSTATE */
+ " #if defined(BITSTATE) && defined(LC)",
" if (S_Tab == H_tab)",
" { v = (char *) &comp_now;",
" n = compact_stack(vin, nin);",
@@ -4888,19 +7923,20 @@
" } else",
" { v = vin; n = nin;",
" }",
- "#else",
+ " #else",
" v = vin; n = nin;",
- "#endif",
- "#else",
+ " #endif",
+ " #else",
" v = (char *) &comp_now;",
" #ifdef HC",
- " rem_a = now._a_t;", /* 4.3.0 */
+ " rem_a = now._a_t;", /* new 5.0 */
" now._a_t = 0;", /* for hashing/state matching to work right */
" #endif",
- " n = compress(vin, nin);", /* with HC, this calls s_hash */
+ " n = compress(vin, nin);", /* with HC, this calls s_hash -- but on vin, not on v... */
" #ifdef HC",
- " now._a_t = rem_a;", /* 4.3.0 */
+ " now._a_t = rem_a;", /* new 5.0 */
" #endif",
+ /* with HC4 -a, compress copies K1 and K2 into v[], leaving v[0] free for the a-bit */
"#ifndef SAFETY",
" if (S_A)",
" { v[0] = 0; /* _a_t */",
@@ -4911,35 +7947,53 @@
"#endif",
" m = 0;",
" }",
- "#endif",
- "#endif",
- "#if !defined(HC) && !(defined(BITSTATE) && defined(LC))",
+ " #endif",
+ " #endif",
+ " #if !defined(HC) && !(defined(BITSTATE) && defined(LC))",
" s_hash((uchar *)v, n);",
- "#endif",
- " tmp = H_tab[j1];",
+ " #endif",
+ " /* for BFS_PAR we can only get here in BITSTATE mode */",
+ " /* and in that case we don't use locks */",
+ " #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " e_critical(BFS_ID); /* bfs_par / h_store */",
+ " #endif",
+ " #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+ " enter_critical(CS_ID);",
+ " #endif",
+ " tmp = H_tab[j1_spin];",
" if (!tmp)",
- " { tmp = grab_state(n);",
- " H_tab[j1] = tmp;",
+ " { tmp = grab_state(n);", /* no zero-returns with bfs_par */
+ " #if NCORE>1",
+ " if (!tmp)",
+ " { /* if we get here -- we've already issued a warning */",
+ " /* but we want to allow the normal distributed termination */",
+ " /* to collect the stats on all cpus in the wrapup */",
+ " #if !defined(SEP_STATE) && !defined(BITSTATE)",
+ " leave_critical(CS_ID);",
+ " #endif",
+ " return 1; /* allow normal termination */",
+ " }",
+ " #endif",
+ " H_tab[j1_spin] = tmp;",
" } else",
" { for (;; hcmp++, olst = tmp, tmp = tmp->nxt)",
" { /* skip the _a_t and the _cnt bytes */",
- "#ifdef COLLAPSE",
+ " #ifdef COLLAPSE",
" if (tmp->ln != 0)",
" { if (!tmp->nxt) goto Append;",
" continue;",
" }",
- "#endif",
+ " #endif",
" m = memcmp(((char *)&(tmp->state)) + S_A, ",
" v + S_A, n - S_A);",
" if (m == 0) {",
- "#ifdef SAFETY",
+ " #ifdef SAFETY",
"#define wasnew 0",
- "#else",
+ " #else",
" int wasnew = 0;",
- "#endif",
+ " #endif",
- "#ifndef SAFETY",
- "#ifndef NOCOMP",
+ " #if !defined(SAFETY) && !defined(NOCOMP)",
" if (S_A)",
" { if ((((char *)&(tmp->state))[0] & V_A) != V_A)",
" { wasnew = 1; nShadow++;",
@@ -4948,7 +8002,7 @@
"#ifndef NOFAIR",
" if (S_A > NFAIR)",
" { /* 0 <= now._cnt[now._a_t&1] < MAXPROC */",
- " unsigned ci, bp; /* index, bit pos */",
+ " uint ci, bp; /* index, bit pos */",
" ci = (now._cnt[now._a_t&1] / 8);",
" bp = (now._cnt[now._a_t&1] - 8*ci);",
" if (now._a_t&1) /* use tail-bits in _cnt */",
@@ -4968,13 +8022,16 @@
" /* else: wasnew == 0, i.e., old state */",
"#endif",
" }",
- "#endif",
- "#endif",
+ " #endif",
+ " #if NCORE>1",
+ " Lstate = (H_el *) tmp; /* h_store */",
+ " #endif",
+
"#ifdef FULLSTACK",
"#ifndef SAFETY", /* or else wasnew == 0 */
" if (wasnew)",
- " { Lstate = (struct H_el *) tmp;",
+ " { Lstate = (H_el *) tmp; /* h_store */",
" tmp->tagged |= V_A;",
" if ((now._a_t&1)",
" && (tmp->tagged&A_V)",
@@ -4982,22 +8039,42 @@
" {",
"intersect:",
"#ifdef CHECK",
+ " #if NCORE>1",
+ " printf(\"cpu%%d: \", core_id);",
+ " #endif",
" printf(\"1st dfs-stack intersected on state %%d+\\n\",",
" (int) tmp->st_id);",
"#endif",
+
+ " #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " x_critical(BFS_ID);",
+ " #endif",
+ " #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+ " leave_critical(CS_ID);",
+ " #endif",
+
" return 3;",
" }",
"#ifdef CHECK",
+ " #if NCORE>1",
+ " printf(\"cpu%%d: \", core_id);",
+ " #endif",
" printf(\"\tNew state %%d+\\n\", (int) tmp->st_id);",
"#endif",
"#ifdef DEBUG",
" dumpstate(1, (char *)&(tmp->state),n,tmp->tagged);",
"#endif",
+ " #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " x_critical(BFS_ID);",
+ " #endif",
+ " #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+ " leave_critical(CS_ID);",
+ " #endif",
" return 0;",
" } else",
"#endif",
" if ((S_A)?(tmp->tagged&V_A):tmp->tagged)",
- " { Lstate = (struct H_el *) tmp;",
+ " { Lstate = (H_el *) tmp; /* h_store */",
"#ifndef SAFETY",
" /* already on current dfs stack */",
" /* but may also be on 1st dfs stack */",
@@ -5014,11 +8091,20 @@
" goto intersect;",
"#endif",
"#ifdef CHECK",
+ " #if NCORE>1",
+ " printf(\"cpu%%d: \", core_id);",
+ " #endif",
" printf(\"\tStack state %%d\\n\", (int) tmp->st_id);",
"#endif",
"#ifdef DEBUG",
" dumpstate(0, (char *)&(tmp->state),n,tmp->tagged);",
"#endif",
+ " #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " x_critical(BFS_ID);",
+ " #endif",
+ " #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+ " leave_critical(CS_ID);",
+ " #endif",
" return 2; /* match on stack */",
" }",
"#else",
@@ -5025,30 +8111,90 @@
" if (wasnew)",
" {",
"#ifdef CHECK",
+ " #if NCORE>1",
+ " printf(\"cpu%%d: \", core_id);",
+ " #endif",
" printf(\"\tNew state %%d+\\n\", (int) tmp->st_id);",
"#endif",
"#ifdef DEBUG",
" dumpstate(1, (char *)&(tmp->state), n, 0);",
"#endif",
+ " #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " x_critical(BFS_ID);",
+ " #endif",
+ " #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+ " leave_critical(CS_ID);",
+ " #endif",
" return 0;",
" }",
"#endif",
"#ifdef CHECK",
+ "#if NCORE>1",
+ " printf(\"cpu%%d: \", core_id);",
+ "#endif",
" printf(\"\tOld state %%d\\n\", (int) tmp->st_id);",
"#endif",
"#ifdef DEBUG",
" dumpstate(0, (char *)&(tmp->state), n, 0);",
"#endif",
- "#ifdef REACH",
- " if (tmp->D > depth)",
- " { tmp->D = depth;",
- "#ifdef CHECK",
- " printf(\"\t\tReVisiting (from smaller depth)\\n\");",
- "#endif",
- " nstates--;",
+ "#if defined(BCS)",
+ " #ifdef CONSERVATIVE",
+ " if (tmp->ctx_low > trpt->sched_limit)",
+ " { tmp->ctx_low = trpt->sched_limit;",
+ " tmp->ctx_pid[(now._last)/8] = 1 << ((now._last)%%8); /* new */",
+ " #ifdef CHECK",
+ " #if NCORE>1",
+ " printf(\"cpu%%d: \", core_id);",
+ " #endif",
+ " printf(\"\t\tRevisit with fewer context switches\\n\");",
+ " #endif",
+ " nstates--;",
+ " #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " x_critical(BFS_ID);",
+ " #endif",
+ " #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+ " leave_critical(CS_ID);",
+ " #endif",
+ " return 0;",
+ " } else if ((tmp->ctx_low == trpt->sched_limit",
+ " && (tmp->ctx_pid[(now._last)/8] & ( 1 << ((now._last)%%8) )) == 0 ))",
+ " { tmp->ctx_pid[(now._last)/8] |= 1 << ((now._last)%%8); /* add */",
+ " #ifdef CHECK",
+ " #if NCORE>1",
+ " printf(\"cpu%%d: \", core_id);",
+ " #endif",
+ " printf(\"\t\tRevisit with same nr of context switches\\n\");",
+ " #endif",
+ " nstates--;",
+ " #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " x_critical(BFS_ID);",
+ " #endif",
+ " #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+ " leave_critical(CS_ID);",
+ " #endif",
+ " return 0;",
+ " }",
+ " #endif",
+ "#endif",
+ " #ifdef REACH",
+ " if (tmp->D > depth)",
+ " { tmp->D = depth;",
+ " #ifdef CHECK",
+ " #if NCORE>1",
+ " printf(\"cpu%%d: \", core_id);",
+ " #endif",
+ " printf(\"\t\tReVisiting (from smaller depth)\\n\");",
+ " #endif",
+ " nstates--;",
+ " #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " x_critical(BFS_ID);",
+ " #endif",
+ " #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+ " leave_critical(CS_ID);",
+ " #endif",
#if 0
- possible variation of iterative search for shortest counter-example (pan -i
- and pan -I) suggested by Pierre Moro (for safety properties):
+ a possible variation of iterative search for shortest counter-example
+ (pan -i and pan -I) suggested by Pierre Moro (for safety properties):
state revisits on shorter depths do not start until after
the first counter-example is found. this assumes that the max search
depth is set large enough that a first (possibly long) counter-example
@@ -5056,22 +8202,37 @@
if set too short, this variant can miss the counter-example, even if
it would otherwise be shorter than the depth-limit.
(p.m. unsure if this preserves the guarantee of finding the
- shortest counter-example - so not enabled yet)
- " if (errors > 0 && iterative)", /* Moro */
+ shortest counter-example - so not enabled by default)
+ " if (errors > 0 && iterative)", /* Moro */
#endif
- " return 0;",
- " }",
- "#endif",
- "#if defined(BFS) && defined(Q_PROVISO)",
- " Lstate = (struct H_el *) tmp;",
- "#endif",
+ " return 0;",
+ " }",
+ " #endif",
+ " #if (defined(BFS) && defined(Q_PROVISO)) || NCORE>1",
+ " Lstate = (H_el *) tmp; /* h_store */",
+ " #endif",
+ " #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " x_critical(BFS_ID);",
+ " #endif",
+ " #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+ " leave_critical(CS_ID);",
+ " #endif",
" return 1; /* match outside stack */",
" } else if (m < 0)",
" { /* insert state before tmp */",
" ntmp = grab_state(n);",
+ " #if NCORE>1",
+ " if (!ntmp)",
+ " {",
+ " #if !defined(SEP_STATE) && !defined(BITSTATE)",
+ " leave_critical(CS_ID);",
+ " #endif",
+ " return 1; /* allow normal termination */",
+ " }",
+ " #endif",
" ntmp->nxt = tmp;",
" if (!olst)",
- " H_tab[j1] = ntmp;",
+ " H_tab[j1_spin] = ntmp;",
" else",
" olst->nxt = ntmp;",
" tmp = ntmp;",
@@ -5078,16 +8239,28 @@
" break;",
" } else if (!tmp->nxt)",
" { /* append after tmp */",
- "#ifdef COLLAPSE",
+ " #ifdef COLLAPSE",
"Append:",
- "#endif",
+ " #endif",
" tmp->nxt = grab_state(n);",
+ " #if NCORE>1",
+ " if (!tmp->nxt)",
+ " {",
+ " #if !defined(SEP_STATE) && !defined(BITSTATE)",
+ " leave_critical(CS_ID);",
+ " #endif",
+ " return 1; /* allow normal termination */",
+ " }",
+ " #endif",
" tmp = tmp->nxt;",
" break;",
" } }",
" }",
- "#ifdef CHECK",
+ " #ifdef CHECK",
" tmp->st_id = (unsigned) nstates;",
+ " #if NCORE>1",
+ " printf(\"cpu%%d: \", core_id);",
+ " #endif",
"#ifdef BITSTATE",
" printf(\" Push state %%d\\n\", ((int) nstates) - 1);",
"#else",
@@ -5094,16 +8267,21 @@
" printf(\" New state %%d\\n\", (int) nstates);",
"#endif",
"#endif",
- "#if !defined(SAFETY) || defined(REACH)",
+ " #if defined(BCS)",
+ " tmp->ctx_low = trpt->sched_limit;",
+ " #ifdef CONSERVATIVE",
+ " tmp->ctx_pid[(now._last)/8] = 1 << ((now._last)%%8); /* new limit */",
+ " #endif",
+ " #endif",
+ " #if !defined(SAFETY) || defined(REACH)",
" tmp->D = depth;",
- "#endif",
- "#ifndef SAFETY",
- "#ifndef NOCOMP",
+ " #endif",
+ " #if !defined(SAFETY) && !defined(NOCOMP)",
" if (S_A)",
" { v[0] = V_A;",
"#ifndef NOFAIR",
" if (S_A > NFAIR)",
- " { unsigned ci, bp; /* as above */",
+ " { uint ci, bp; /* as above */",
" ci = (now._cnt[now._a_t&1] / 8);",
" bp = (now._cnt[now._a_t&1] - 8*ci);",
" if (now._a_t&1)",
@@ -5114,26 +8292,409 @@
" }",
"#endif",
" }",
- "#endif",
- "#endif",
+ " #endif",
+ " #if defined(AUTO_RESIZE) && !defined(BITSTATE)",
+ " tmp->m_K1 = K1;",
+ " #endif",
" memcpy(((char *)&(tmp->state)), v, n);",
- "#ifdef FULLSTACK",
+ " #ifdef FULLSTACK",
" tmp->tagged = (S_A)?V_A:(depth+1);",
"#ifdef DEBUG",
- " dumpstate(-1, v, n, tmp->tagged);",
+ " dumpstate(-1, v, n, tmp->tagged);",
"#endif",
- " Lstate = (struct H_el *) tmp;",
+ " Lstate = (H_el *) tmp; /* end of h_store */",
+ " #else",
+ " #ifdef DEBUG",
+ " dumpstate(-1, v, n, 0);",
+ " #endif",
+ " #if NCORE>1",
+ " Lstate = (H_el *) tmp; /* end of h_store */",
+ " #endif",
+ " #endif",
+
+ " #if defined(BFS_PAR) && !defined(BFS_SEP_HASH)",
+ " x_critical(BFS_ID);",
+ " #endif",
+ " #if NCORE>1",
+ " #ifdef V_PROVISO",
+ " tmp->cpu_id = core_id;",
+ " #endif",
+ " #if !defined(SEP_STATE) && !defined(BITSTATE)",
+ " leave_critical(CS_ID);",
+ " #endif",
+ " #endif",
+
+ " return 0;",
+ "}", /* end of h_store */
+ "#endif", /* !BFS_PAR || !USE_TDH */
+ "",
+ "void",
+ "o_hash32(uchar *s, int len, int h) /* 32-bit, like d_sfh, but with seed */",
+ "{ uint32_t tmp;",
+ " int rem;",
+ "",
+ " rem = len & 3;",
+ " len >>= 2;",
+ "",
+ " for ( ; len > 0; len--)",
+ " { h += get16bits(s);",
+ " tmp = (get16bits(s+2) << 11) ^ h;",
+ " h = (h << 16) ^ tmp;",
+ " s += 2*sizeof(uint16_t);",
+ " h += h >> 11;",
+ " }",
+ " switch (rem) {",
+ " case 3: h += get16bits(s);",
+ " h ^= h << 16;",
+ " h ^= s[sizeof(uint16_t)] << 18;",
+ " h += h >> 11;",
+ " break;",
+ " case 2: h += get16bits(s);",
+ " h ^= h << 11;",
+ " h += h >> 17;",
+ " break;",
+ " case 1: h += *s;",
+ " h ^= h << 10;",
+ " h += h >> 1;",
+ " break;",
+ " }",
+ " h ^= h << 3;",
+ " h += h >> 5;",
+ " h ^= h << 4;",
+ " h += h >> 17;",
+ " h ^= h << 25;",
+ " h += h >> 6;",
+ "",
+ " K1 = h;",
+ "}",
+ "void",
+ "o_hash64(uchar *kb, int nbytes, int seed)", /* 64-bit hash */
+ "{ uint8_t *bp;",
+ " uint64_t a, b, c, n;",
+ " const uint64_t *k = (uint64_t *) kb;",
+ " n = nbytes/WS; /* nr of 8-byte chunks */",
+ " /* extend to multiple of words, if needed */",
+ " a = WS - (nbytes %% WS);",
+ " if (a > 0 && a < WS)",
+ " { n++;",
+ " bp = kb + nbytes;",
+ " switch (a) {",
+ " case 7: *bp++ = 0; /* fall thru */",
+ " case 6: *bp++ = 0; /* fall thru */",
+ " case 5: *bp++ = 0; /* fall thru */",
+ " case 4: *bp++ = 0; /* fall thru */",
+ " case 3: *bp++ = 0; /* fall thru */",
+ " case 2: *bp++ = 0; /* fall thru */",
+ " case 1: *bp = 0;",
+ " case 0: break;",
+ " } }",
+ " a = (uint64_t) seed;",
+ " b = HASH_CONST[HASH_NR];",
+ " c = 0x9e3779b97f4a7c13LL; /* arbitrary */",
+ " while (n >= 3)",
+ " { a += k[0];",
+ " b += k[1];",
+ " c += k[2];",
+ " mix(a,b,c);",
+ " n -= 3;",
+ " k += 3;",
+ " }",
+ " c += (((uint64_t) nbytes)<<3);",
+ " switch (n) {",
+ " case 2: b += k[1];",
+ " case 1: a += k[0];",
+ " case 0: break;",
+ " }",
+ " mix(a,b,c);",
+ "",
+ " K1 = a;",
+ "}",
+ "",
+ "#if defined(USE_TDH) && !defined(WIN32) && !defined(WIN64)",
+#if 0
+ some problems with this storage mode:
+
+ 0. pre-allocates full hash-table with slots equal to max statevector size
+ e.g. with -w26 we allocate 2^26 (64 M) slots of VECTORSZ large
+ which can accomodate up to 64 M states
+ once you get close to or exceed the max, the search aborts
+ with a 'hashtable full' message
+ in HC mode the max storage needed per state is more modest and independent
+ of the maximum vectorsize; which makes this mode attractive as a default
+
+ 1. does not support PO reduction through the Lstate->ostate->tagged
+ to distinguish open from closed states - this can reduce states by 50%
+ could add this as another bit from the hash value
+ e.g., could add it in HC mode to the first hash?
+
+ 2. the same state may be stored multiple times
+#endif
+ "#ifdef HC",
+ " #ifndef T_HC",
+ " #ifdef BFS_HC",
+ " #define T_HC BFS_HC",
+ " #else",
+ " #define T_HC 2",
+ " #endif",
+ " #endif",
+ " #if T_HC<1 || T_HC>4",
+ " #error \"BFS_HC must be 1, 2, 3, or 4 (default is 2)\"",
+ " #endif",
+ "#endif",
+ "",
+ "#define T_ROW 6", /* related to cache line size */
+ "#define T_ROW_SIZE (1<<T_ROW)",
+ "#define T_ROW_MASK -(1<<T_ROW)",
+ "#define T_FREE 0",
+ "#define T_STAT 1 /* status bit */",
+ "#ifndef T_VSZ",
+ " #define T_VSZ VECTORSZ/4 /* compressed vectorsize */",
+ "#endif",
+ "",
+ "static volatile char *ohash_sd; /* state data */",
+ "static volatile uint32_t *ohash_hv; /* hash values */",
+ "static ulong ohash_max;",
+ "static ulong ohash_mask;",
+ "",
+ "#if defined(USE_TDH) && defined(Q_PROVISO)",
+ " static volatile uchar *ohash_inq; /* open/closed flag BFS_INQ */",
+ "#endif",
+ "#ifdef HC",
+ " static uint32_t ohash_hc[T_HC];",
+ " static ulong ohash_hc_sz;",
+ "#endif",
+ "",
+ "void",
+ "init_HT(ulong x) /* USE_TDH cygwin/linux */",
+ "{ x = x / (ulong) sizeof(H_el *); /* room for x pointers */",
+ " #ifdef DEBUG",
+ " printf(\"prealloc x %%lu v %%d x*v %%lu\\n\",",
+ " x, T_VSZ, (ulong) (x * (ulong)T_VSZ));",
+ " #endif",
+ "#ifndef HC",
+ " if (!(x * (ulong) T_VSZ > x))",
+ " { Uerror(\"assertion x * (ulong) T_VSZ > x fails\");",
+ " }",
+ " #ifdef BFS_SEP_HASH",
+ " ohash_sd = (char *) emalloc(x * (ulong) T_VSZ);",
+ " #else",
+ " ohash_sd = (volatile char *) sh_pre_malloc(x * (ulong) T_VSZ);",
+ " #endif",
+ "#else", /* assume T_HC >= 1, and normally 2 */
+ " ohash_hc_sz = (ulong) (T_HC * (ulong) sizeof(uint32_t));",
+ " if (!(x * ohash_hc_sz > x))", /* watch for overflow */
+ " { Uerror(\"assertion x * ohash_hc_sz > x fails\");",
+ " }",
+ " #ifdef BFS_SEP_HASH",
+ " ohash_sd = (char *) emalloc(x * ohash_hc_sz);",
+ " #else",
+ " ohash_sd = (volatile char *) sh_pre_malloc(x * ohash_hc_sz);",
+ " #endif",
+ "#endif",
+ "#ifdef BFS_SEP_HASH",
+ " ohash_hv = (uint32_t *) emalloc(x * (ulong) sizeof(uint32_t));",
"#else",
- "#ifdef DEBUG",
- " dumpstate(-1, v, n, 0);",
- "#endif",
+ " ohash_hv = (volatile uint32_t *) sh_pre_malloc(x * (ulong) sizeof(uint32_t));",
"#endif",
- " return 0;",
+ " ohash_mask = (((ulong)1)<<ssize)-1;",
+ " ohash_max = (((ulong)1)<<ssize)/100;",
+ "#if defined(USE_TDH) && defined(Q_PROVISO)",
+ " #ifdef BFS_SEP_HASH",
+ " ohash_inq = (uchar *) emalloc(x * (ulong) sizeof(uchar));",
+ " #else",
+ " ohash_inq = (volatile uchar *) sh_pre_malloc(x * (ulong) sizeof(uchar));",
+ " #endif",
+ "#endif",
"}",
+ "",
+ "static int h_table_full;",
+ "#ifdef L_BOUND",
+ "void",
+ "bfs_mark_live(void)",
+ "{ int i;",
+ "",
+ " trpt->o_pm &= ~2;",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"check to mark\\n\");",
"#endif",
- "#include TRANSITIONS",
+ " for (i = 0; i < (int) now._nr_pr; i++)",
+ " { P0 *ptr = (P0 *) pptr(i);",
+ " if (accpstate[ptr->_t][ptr->_p])",
+ " { trpt->o_pm |= 2;",
+ " now._l_bnd = L_bound;",
+ " now._l_sds = (uchar *) 0;",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"mark state live\\n\");",
+ "#endif",
+ " break;",
+ " } }",
+ "}",
"void",
- "do_reach(void)",
- "{",
+ "bfs_check_live(uchar b, uchar *s)",
+ "{ /* assert(b>0); */",
+ " now._l_bnd = b-1; /* decrease bound */",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"check live %%d\\n\", b);",
+ "#endif",
+ " if (b == L_bound && boq == -1)", /* never mid rv */
+ " { now._l_sds = (uchar *) Lstate; /* new target */",
+ " } else",
+ " { now._l_sds = s; /* restore target */",
+ " if (s == (uchar *) Lstate)",
+ " { depthfound = depth - (BASE+1)*(L_bound - now._l_bnd - 1);",
+ " uerror(\"accept cycle found\");",
+ " depthfound = -1;",
+ " now._l_bnd = 0;",
+ " now._l_sds = (uchar *) 0;",
+ " } }",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"set l_bound to %%d -- sds %%p\\n\", b-1, (void *) now._l_sds);",
+ "#endif",
+ "}",
+ "#endif",
+ "/* closed hashing with locality - similar to ltsmin */",
+ "int",
+ "o_store(const char *vin, int nin)",
+ "{ int i, seed = 0;",
+ " ulong hash_v, ix, ex;",
+ " uint32_t T_BUSY, T_DONE;",
+ " volatile uint32_t *t_entry;",
+ "#ifdef HC",
+ " ulong vs = ohash_hc_sz;",
+ "#else",
+ " ulong vs = (ulong) T_VSZ;",
+ "#endif",
+ "#ifdef L_BOUND",
+ " uchar o_bnd, *o_sds;",
+ "#endif",
+ "#ifndef STOP_ON_FULL",
+ " if (h_table_full)",
+ " { goto done;",
+ " }",
+ "#endif",
+ "#ifdef L_BOUND",
+ " if (now._l_bnd == 0)",
+ " { bfs_mark_live();",
+ " }",
+ " #ifdef VERBOSE",
+ " else",
+ " { bfs_printf(\"non-markable state %%d\\n\", now._l_bnd);",
+ " }",
+ " #endif",
+ " o_bnd = now._l_bnd;",
+ " o_sds = now._l_sds;",
+ " now._l_bnd = (o_bnd)?1:0; /* mark nested phase of bounded search */",
+ " now._l_sds = (uchar *) 0;",
+ "#endif",
+ "#if !defined(HC) && !defined(T_NOCOMP)",
+ " nin = compress((char *)vin, nin);",
+ " vin = (char *) &comp_now;",
+ "#endif",
+ " do { o_hash((uchar *)vin, nin, seed++);",
+ " hash_v = K1;",
+ " } while (hash_v == T_FREE || hash_v == T_STAT); /* unlikely, hash_v 0 or 1 */",
+ "",
+ " T_BUSY = ((uint32_t) hash_v & ~((uint32_t) T_STAT)); /* hash with status bit 0 */",
+ " T_DONE = ((uint32_t) hash_v | ((uint32_t) T_STAT)); /* hash with status bit 1 */",
+ "#ifdef HC",
+ " d_hash((uchar *)vin, nin);", /* HC */
+ " ohash_hc[0] = (uint32_t) K1;",
+ " #if T_HC>1",
+ " ohash_hc[1] = (uint32_t) (K1>>32);", /* assumes ulong = 64 bits */
+ " #endif",
+ " #if T_HC>2",
+ " ohash_hc[2] = (uint32_t) K2;",
+ " #endif",
+ " #if T_HC>3",
+ " ohash_hc[3] = (uint32_t) (K2>>32);",
+ " #endif",
+ "#endif",
+ " while (seed < ohash_max)",
+ " { ix = hash_v & ohash_mask;",
+ " ex = (ix & T_ROW_MASK) + T_ROW_SIZE;",
+ " for (i = 0; i < T_ROW_SIZE; i++)",
+ " { t_entry = (uint32_t *) &ohash_hv[ix];",
+ " if (*t_entry == T_FREE && cas(t_entry, T_FREE, T_BUSY))",
+ " {",
+ "#ifndef HC",
+ " memcpy((char *) &ohash_sd[ix * vs], vin, nin);",
+ "#else",
+ " memcpy((char *) &ohash_sd[ix * vs], (char *) ohash_hc, vs);",
+ "#endif",
+ "#if defined(USE_TDH) && defined(Q_PROVISO)",
+ " ohash_inq[ix] = (uchar) BFS_INQ;",
+ " Lstate = (H_el *) &ohash_inq[ix];",
+ "#endif",
+ " *t_entry = T_DONE;",
+ "#ifdef VERBOSE",
+ " #ifdef L_BOUND",
+ " bfs_printf(\"New state %%p [%%p]\\n\",",
+ " (void *) Lstate, (void *) o_sds);",
+ " #else",
+ " bfs_printf(\"New state %%p\\n\", (void *) Lstate);",
+ " #endif",
+ "#endif",
+ "#ifdef L_BOUND",
+ " if (o_bnd) { bfs_check_live(o_bnd, o_sds); }",
+ "#endif",
+ " return 0; /* New State */",
+ " }",
+ " while (*t_entry == T_BUSY)",
+ " { usleep(2); /* wait */",
+ " }",
+ " if (*t_entry == T_DONE /* (first) hash matches, check data */",
+ "#ifndef HC",
+ " && memcmp((char *) &ohash_sd[ix * vs], vin, nin) == 0)",
+ "#else",
+ " && memcmp((char *) &ohash_sd[ix * vs], (char *) ohash_hc, vs) == 0)",
+ "#endif",
+ " {",
+ "#if defined(USE_TDH) && defined(Q_PROVISO)",
+ " Lstate = (H_el *) &ohash_inq[ix];",
+ "#endif",
+ "#ifdef VERBOSE",
+ " #ifdef L_BOUND",
+ " bfs_printf(\"Old state %%p [%%p]\\n\",",
+ " (void *) Lstate, (void *) o_sds);",
+ " #else",
+ " bfs_printf(\"Old state %%p\\n\", (void *) Lstate);",
+ " #endif",
+ "#endif",
+ "#ifdef L_BOUND",
+ " if (o_bnd) { bfs_check_live(o_bnd, o_sds); }",
+ "#endif",
+ " return 1; /* Old State */",
+ " }",
+ " hcmp++; ix++;",
+ " ix = (ix==ex) ? ex - T_ROW_SIZE : ix;",
+ " }",
+ " /* find a new slot: */",
+ " do { o_hash((uchar *)vin, nin, (int) (hash_v + seed++));",
+ " hash_v = K1;",
+ " } while (hash_v == T_FREE || hash_v == T_STAT);",
+ " T_BUSY = ((uint32_t) hash_v & ~((uint32_t) T_STAT));",
+ " T_DONE = ((uint32_t) hash_v | ((uint32_t) T_STAT));",
+ " }",
+ "#ifdef STOP_ON_FULL",
+ " Uerror(\"hash table full\");",
+ " /* no return from Uerror */",
+ "#else",
+ " if (!h_table_full)",
+ " { h_table_full++;",
+ " if (who_am_i == 0)",
+ " { bfs_printf(\"hash table is full\\n\");",
+ " } }",
+ "done:",
+ " bfs_punt++; /* counts this as a lost state */",
+ "#endif",
+ "#ifdef L_BOUND",
+ " now._l_bnd = 0; /* no more checking */",
+ " now._l_sds = (uchar *) 0;",
+ "#endif",
+ " return 1; /* technically should be 0, but we want to throttle down */",
+ "}",
+ "#endif", /* USE_TDH && !WIN32 && !WIN64 */
+ "#endif", /* !BITSTATE || FULLSTACK */
+ "#include TRANSITIONS",
0,
};
--- a/sys/src/cmd/spin/pangen2.c
+++ b/sys/src/cmd/spin/pangen2.c
@@ -1,13 +1,10 @@
/***** spin: pangen2.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include "spin.h"
#include "version.h"
@@ -15,33 +12,40 @@
#include "pangen2.h"
#include "pangen4.h"
#include "pangen5.h"
+#include "pangen7.h"
#define DELTA 500 /* sets an upperbound on nr of chan names */
#define blurb(fd, e) { fprintf(fd, "\n"); if (!merger) fprintf(fd, "\t\t/* %s:%d */\n", \
e->n->fn->name, e->n->ln); }
-#define tr_map(m, e) { if (!merger) fprintf(tt, "\t\ttr_2_src(%d, %s, %d);\n", \
+#define tr_map(m, e) { if (!merger) fprintf(tt, "\t\ttr_2_src(%d, \"%s\", %d);\n", \
m, e->n->fn->name, e->n->ln); }
extern ProcList *rdy;
extern RunList *run;
+extern Lextok *runstmnts;
extern Symbol *Fname, *oFname, *context;
extern char *claimproc, *eventmap;
-extern int lineno, verbose, Npars, Mpars;
+extern int lineno, verbose, Npars, Mpars, nclaims;
extern int m_loss, has_remote, has_remvar, merger, rvopt, separate;
-extern int Ntimeouts, Etimeouts, deadvar;
-extern int u_sync, u_async, nrRdy;
+extern int Ntimeouts, Etimeouts, deadvar, old_scope_rules, old_priority_rules;
+extern int u_sync, u_async, nrRdy, Unique;
extern int GenCode, IsGuard, Level, TestOnly;
+extern int globmin, globmax, ltl_mode, dont_simplify;
+
extern short has_stack;
-extern char *NextLab[];
+extern char *NextLab[64]; /* must match value in dstep.c:18 */
-FILE *tc, *th, *tt, *tm, *tb;
+int buzzed;
+FILE *tc, *th, *tt, *tb;
+static FILE *tm;
-int OkBreak = -1;
+int OkBreak = -1, has_hidden = 0; /* has_hidden set in sym.c and structs.c */
short nocast=0; /* to turn off casts in lvalues */
short terse=0; /* terse printing of varnames */
short no_arrays=0;
short has_last=0; /* spec refers to _last */
+short has_priority=0; /* spec refers to _priority */
short has_badelse=0; /* spec contains else combined with chan refs */
short has_enabled=0; /* spec contains enabled() */
short has_pcvalue=0; /* spec contains pc_value() */
@@ -52,9 +56,7 @@
short has_unless=0; /* spec contains unless statements */
short has_provided=0; /* spec contains PROVIDED clauses on procs */
short has_code=0; /* spec contains c_code, c_expr, c_state */
-short _isok=0; /* checks usage of predefined variable _ */
-short evalindex=0; /* evaluate index of var names */
-short withprocname=0; /* prefix local varnames with procname */
+short has_ltl=0; /* has inline ltl formulae */
int mst=0; /* max nr of state/process */
int claimnr = -1; /* claim process, if any */
int eventmapnr = -1; /* event trace, if any */
@@ -74,6 +76,9 @@
static int uniq=1;
static int multi_needed, multi_undo;
static short AllGlobal=0; /* set if process has provided clause */
+static short withprocname=0; /* prefix local varnames with procname */
+static short _isok=0; /* checks usage of predefined variable _ */
+static short evalindex=0; /* evaluate index of var names */
int has_global(Lextok *);
static int getweight(Lextok *);
@@ -86,6 +91,29 @@
static void Tpe(Lextok *);
extern void spit_recvs(FILE *, FILE*);
+static L_List *keep_track;
+
+void
+keep_track_off(Lextok *n)
+{ L_List *p;
+
+ p = (L_List *) emalloc(sizeof(L_List));
+ p->n = n;
+ p->nxt = keep_track;
+ keep_track = p;
+}
+
+int
+check_track(Lextok *n)
+{ L_List *p;
+
+ for (p = keep_track; p; p = p->nxt)
+ { if (p->n == n)
+ { return n->sym?n->sym->type:0;
+ } }
+ return 0;
+}
+
static int
fproc(char *s)
{ ProcList *p;
@@ -98,26 +126,48 @@
return -1;
}
+int
+pid_is_claim(int p) /* Pid (p->tn) to type (p->b) */
+{ ProcList *r;
+
+ for (r = rdy; r; r = r->nxt)
+ { if (r->tn == p) return (r->b == N_CLAIM);
+ }
+ printf("spin: error, cannot find pid %d\n", p);
+ return 0;
+}
+
static void
reverse_procs(RunList *q)
{
if (!q) return;
reverse_procs(q->nxt);
- fprintf(tc, " Addproc(%d);\n", q->tn);
+ fprintf(tc, " Addproc(%d, %d);\n",
+ q->tn, q->priority < 1 ? 1 : q->priority);
}
static void
+forward_procs(RunList *q)
+{
+ if (!q) return;
+ fprintf(tc, " Addproc(%d, %d);\n",
+ q->tn, q->priority < 1 ? 1 : q->priority);
+ forward_procs(q->nxt);
+}
+
+static void
tm_predef_np(void)
{
fprintf(th, "#define _T5 %d\n", uniq++);
fprintf(th, "#define _T2 %d\n", uniq++);
+
fprintf(tm, "\tcase _T5:\t/* np_ */\n");
if (separate == 2)
- fprintf(tm, "\t\tif (!((!(o_pm&4) && !(tau&128))))\n");
- else
- fprintf(tm, "\t\tif (!((!(trpt->o_pm&4) && !(trpt->tau&128))))\n");
-
+ { fprintf(tm, "\t\tif (!((!(o_pm&4) && !(tau&128))))\n");
+ } else
+ { fprintf(tm, "\t\tif (!((!(trpt->o_pm&4) && !(trpt->tau&128))))\n");
+ }
fprintf(tm, "\t\t\tcontinue;\n");
fprintf(tm, "\t\t/* else fall through */\n");
fprintf(tm, "\tcase _T2:\t/* true */\n");
@@ -151,51 +201,120 @@
void
gensrc(void)
{ ProcList *p;
+ int i;
- if (!(tc = fopen(Cfile[0].nm[separate], "w")) /* main routines */
- || !(th = fopen(Cfile[1].nm[separate], "w")) /* header file */
- || !(tt = fopen(Cfile[2].nm[separate], "w")) /* transition matrix */
- || !(tm = fopen(Cfile[3].nm[separate], "w")) /* forward moves */
- || !(tb = fopen(Cfile[4].nm[separate], "w"))) /* backward moves */
+ disambiguate(); /* avoid name-clashes between scopes */
+
+ if (!(tc = fopen(Cfile[0].nm[separate], MFLAGS)) /* main routines */
+ || !(th = fopen(Cfile[1].nm[separate], MFLAGS)) /* header file */
+ || !(tt = fopen(Cfile[2].nm[separate], MFLAGS)) /* transition matrix */
+ || !(tm = fopen(Cfile[3].nm[separate], MFLAGS)) /* forward moves */
+ || !(tb = fopen(Cfile[4].nm[separate], MFLAGS))) /* backward moves */
{ printf("spin: cannot create pan.[chtmfb]\n");
alldone(1);
}
- fprintf(th, "#define Version \"%s\"\n", Version);
- fprintf(th, "#define Source \"%s\"\n\n", oFname->name);
- if (separate != 2)
- fprintf(th, "char *TrailFile = Source; /* default */\n");
+ fprintf(th, "#ifndef PAN_H\n");
+ fprintf(th, "#define PAN_H\n\n");
+ fprintf(th, "#define SpinVersion \"%s\"\n", SpinVersion);
+ fprintf(th, "#define PanSource \"");
+ for (i = 0; oFname->name[i] != '\0'; i++)
+ { char c = oFname->name[i];
+ if (c == '\\' || c == ' ') /* Windows path */
+ { fprintf(th, "\\");
+ }
+ fprintf(th, "%c", c);
+ }
+ fprintf(th, "\"\n\n");
+
+ fprintf(th, "#define G_long %d\n", (int) sizeof(long));
+ fprintf(th, "#define G_int %d\n\n", (int) sizeof(int));
+ fprintf(th, "#define ulong unsigned long\n");
+ fprintf(th, "#define ushort unsigned short\n");
+
+ fprintf(th, "#ifdef WIN64\n");
+ fprintf(th, " #define ONE_L (1L)\n");
+ fprintf(th, "/* #define long long long */\n");
+ fprintf(th, "#else\n");
+ fprintf(th, " #define ONE_L (1L)\n");
+ fprintf(th, "#endif\n\n");
+
+ fprintf(th, "#ifdef BFS_PAR\n");
+ fprintf(th, " #define NRUNS %d\n", (runstmnts)?1:0);
+ fprintf(th, " #ifndef BFS\n");
+ fprintf(th, " #define BFS\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, " #ifndef PUTPID\n");
+ fprintf(th, " #define PUTPID\n");
+ fprintf(th, " #endif\n\n");
+ fprintf(th, " #if !defined(USE_TDH) && !defined(NO_TDH)\n");
+ fprintf(th, " #define USE_TDH\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, " #if defined(USE_TDH) && !defined(NO_HC)\n");
+ fprintf(th, " #define HC /* default for USE_TDH */\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, " #ifndef BFS_MAXPROCS\n");
+ fprintf(th, " #define BFS_MAXPROCS 64 /* max nr of cores to use */\n");
+ fprintf(th, " #endif\n");
+
+ fprintf(th, " #define BFS_GLOB 0 /* global lock */\n");
+ fprintf(th, " #define BFS_ORD 1 /* used with -DCOLLAPSE */\n");
+ fprintf(th, " #define BFS_MEM 2 /* malloc from shared heap */\n");
+ fprintf(th, " #define BFS_PRINT 3 /* protect printfs */\n");
+ fprintf(th, " #define BFS_STATE 4 /* hashtable */\n\n");
+ fprintf(th, " #define BFS_INQ 2 /* state is in q */\n\n");
+
+ fprintf(th, " #ifdef BFS_FIFO\n"); /* queue access */
+ fprintf(th, " #define BFS_ID(a,b) (BFS_STATE + (int) ((a)*BFS_MAXPROCS+(b)))\n");
+ fprintf(th, " #define BFS_MAXLOCKS (BFS_STATE + (BFS_MAXPROCS*BFS_MAXPROCS))\n");
+ fprintf(th, " #else\n"); /* h_store access (not needed for o_store) */
+ fprintf(th, " #ifndef BFS_W\n");
+ fprintf(th, " #define BFS_W 10\n"); /* 1<<BFS_W locks */
+ fprintf(th, " #endif\n");
+ fprintf(th, " #define BFS_MASK ((1<<BFS_W) - 1)\n");
+ fprintf(th, " #define BFS_ID (BFS_STATE + (int) (j1_spin & (BFS_MASK)))\n");
+ fprintf(th, " #define BFS_MAXLOCKS (BFS_STATE + (1<<BFS_W))\n"); /* 4+1024 */
+ fprintf(th, " #endif\n");
+
+ fprintf(th, " #undef NCORE\n");
+ fprintf(th, " extern int Cores, who_am_i;\n");
+ fprintf(th, " #ifndef SAFETY\n");
+ fprintf(th, " #if !defined(BFS_STAGGER) && !defined(BFS_DISK)\n");
+ fprintf(th, " #define BFS_STAGGER 64 /* randomizer, was 16 */\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, " #ifndef L_BOUND\n");
+ fprintf(th, " #define L_BOUND 10 /* default */\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, " extern int L_bound;\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, " #if defined(BFS_DISK) && defined(BFS_STAGGER)\n");
+ fprintf(th, " #error BFS_DISK and BFS_STAGGER are not compatible\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, "#endif\n\n");
+
fprintf(th, "#if defined(BFS)\n");
- fprintf(th, "#ifndef SAFETY\n");
- fprintf(th, "#define SAFETY\n");
+ fprintf(th, " #ifndef SAFETY\n");
+ fprintf(th, " #define SAFETY\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, " #ifndef XUSAFE\n");
+ fprintf(th, " #define XUSAFE\n");
+ fprintf(th, " #endif\n");
fprintf(th, "#endif\n");
- fprintf(th, "#ifndef XUSAFE\n");
- fprintf(th, "#define XUSAFE\n");
- fprintf(th, "#endif\n");
- fprintf(th, "#endif\n");
fprintf(th, "#ifndef uchar\n");
- fprintf(th, "#define uchar unsigned char\n");
+ fprintf(th, " #define uchar unsigned char\n");
fprintf(th, "#endif\n");
fprintf(th, "#ifndef uint\n");
- fprintf(th, "#define uint unsigned int\n");
+ fprintf(th, " #define uint unsigned int\n");
fprintf(th, "#endif\n");
- if (sizeof(void *) > 4) /* 64 bit machine */
- { fprintf(th, "#ifndef HASH32\n");
- fprintf(th, "#define HASH64\n");
- fprintf(th, "#endif\n");
- }
-#if 0
- if (sizeof(long)==sizeof(int))
- fprintf(th, "#define long int\n");
-#endif
if (separate == 1 && !claimproc)
{ Symbol *n = (Symbol *) emalloc(sizeof(Symbol));
Sequence *s = (Sequence *) emalloc(sizeof(Sequence));
+ s->minel = -1;
claimproc = n->name = "_:never_template:_";
- ready(n, ZN, s, 0, ZN);
+ ready(n, ZN, s, 0, ZN, N_CLAIM);
}
if (separate == 2)
{ if (has_remote)
@@ -207,20 +326,29 @@
fprintf(th, "#endif\n");
if (has_last)
fprintf(th, "#define HAS_LAST %d\n", has_last);
+ if (has_priority && !old_priority_rules)
+ fprintf(th, "#define HAS_PRIORITY %d\n", has_priority);
goto doless;
}
fprintf(th, "#define DELTA %d\n", DELTA);
fprintf(th, "#ifdef MA\n");
- fprintf(th, "#if MA==1\n"); /* user typed -DMA without size */
- fprintf(th, "#undef MA\n#define MA 100\n");
- fprintf(th, "#endif\n#endif\n");
+ fprintf(th, " #if NCORE>1 && !defined(SEP_STATE)\n");
+ fprintf(th, " #define SEP_STATE\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, " #if MA==1\n"); /* user typed -DMA without size */
+ fprintf(th, " #undef MA\n");
+ fprintf(th, " #define MA 100\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, "#endif\n");
fprintf(th, "#ifdef W_XPT\n");
- fprintf(th, "#if W_XPT==1\n"); /* user typed -DW_XPT without size */
- fprintf(th, "#undef W_XPT\n#define W_XPT 1000000\n");
- fprintf(th, "#endif\n#endif\n");
+ fprintf(th, " #if W_XPT==1\n"); /* user typed -DW_XPT without size */
+ fprintf(th, " #undef W_XPT\n");
+ fprintf(th, " #define W_XPT 1000000\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, "#endif\n");
fprintf(th, "#ifndef NFAIR\n");
- fprintf(th, "#define NFAIR 2 /* must be >= 2 */\n");
+ fprintf(th, " #define NFAIR 2 /* must be >= 2 */\n");
fprintf(th, "#endif\n");
if (Ntimeouts)
fprintf(th, "#define NTIM %d\n", Ntimeouts);
@@ -230,8 +358,16 @@
fprintf(th, "#define REM_VARS 1\n");
if (has_remote)
fprintf(th, "#define REM_REFS %d\n", has_remote); /* not yet used */
+ if (has_hidden)
+ { fprintf(th, "#define HAS_HIDDEN %d\n", has_hidden);
+ fprintf(th, "#if defined(BFS_PAR) || defined(BFS)\n");
+ fprintf(th, " #error cannot use BFS on models with variables declared hidden\n");
+ fprintf(th, "#endif\n");
+ }
if (has_last)
fprintf(th, "#define HAS_LAST %d\n", has_last);
+ if (has_priority && !old_priority_rules)
+ fprintf(th, "#define HAS_PRIORITY %d\n", has_priority);
if (has_sorted)
fprintf(th, "#define HAS_SORTED %d\n", has_sorted);
if (m_loss)
@@ -238,10 +374,17 @@
fprintf(th, "#define M_LOSS\n");
if (has_random)
fprintf(th, "#define HAS_RANDOM %d\n", has_random);
- fprintf(th, "#define HAS_CODE\n"); /* doesn't seem to cause measurable overhead */
+ if (has_ltl)
+ fprintf(th, "#define HAS_LTL 1\n");
+ fprintf(th, "#define HAS_CODE 1\n"); /* could also be set to has_code */
+ /* always defining it doesn't seem to cause measurable overhead though */
+ /* and allows for pan -r etc to work for non-embedded code as well */
+ fprintf(th, "#if defined(RANDSTORE) && !defined(RANDSTOR)\n");
+ fprintf(th, " #define RANDSTOR RANDSTORE\n"); /* xspin uses RANDSTORE... */
+ fprintf(th, "#endif\n");
if (has_stack)
- fprintf(th, "#define HAS_STACK\n");
- if (has_enabled)
+ fprintf(th, "#define HAS_STACK %d\n", has_stack);
+ if (has_enabled || (has_priority && !old_priority_rules))
fprintf(th, "#define HAS_ENABLED 1\n");
if (has_unless)
fprintf(th, "#define HAS_UNLESS %d\n", has_unless);
@@ -252,11 +395,12 @@
if (has_badelse)
fprintf(th, "#define HAS_BADELSE %d\n", has_badelse);
if (has_enabled
+ || (has_priority && !old_priority_rules)
|| has_pcvalue
|| has_badelse
|| has_last)
{ fprintf(th, "#ifndef NOREDUCE\n");
- fprintf(th, "#define NOREDUCE 1\n");
+ fprintf(th, " #define NOREDUCE 1\n");
fprintf(th, "#endif\n");
}
if (has_np)
@@ -265,33 +409,46 @@
fprintf(th, "#define MERGED 1\n");
doless:
- fprintf(th, "#ifdef NP /* includes np_ demon */\n");
+ fprintf(th, "#if !defined(HAS_LAST) && defined(BCS)\n");
+ fprintf(th, " #define HAS_LAST 1 /* use it, but */\n");
+ fprintf(th, " #ifndef STORE_LAST\n"); /* unless the user insists */
+ fprintf(th, " #define NO_LAST 1 /* dont store it */\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, "#endif\n");
+
+ fprintf(th, "#if defined(BCS) && defined(BITSTATE)\n");
+ fprintf(th, " #ifndef NO_CTX\n");
+ fprintf(th, " #define STORE_CTX 1\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, "#endif\n");
+
+ fprintf(th, "#ifdef NP\n");
if (!has_np)
- fprintf(th, "#define HAS_NP 2\n");
- fprintf(th, "#define VERI %d\n", nrRdy);
- fprintf(th, "#define endclaim 3 /* none */\n");
+ fprintf(th, " #define HAS_NP 2\n");
+ fprintf(th, " #define VERI %d /* np_ */\n", nrRdy);
fprintf(th, "#endif\n");
if (claimproc)
- { claimnr = fproc(claimproc);
- /* NP overrides claimproc */
- fprintf(th, "#if !defined(NOCLAIM) && !defined NP\n");
- fprintf(th, "#define VERI %d\n", claimnr);
- fprintf(th, "#define endclaim endstate%d\n", claimnr);
+ { claimnr = fproc(claimproc); /* the default claim */
+ fprintf(th, "#ifndef NOCLAIM\n");
+ fprintf(th, " #define NCLAIMS %d\n", nclaims);
+ fprintf(th, " #ifndef NP\n");
+ fprintf(th, " #define VERI %d\n", claimnr);
+ fprintf(th, " #endif\n");
fprintf(th, "#endif\n");
}
if (eventmap)
{ eventmapnr = fproc(eventmap);
fprintf(th, "#define EVENT_TRACE %d\n", eventmapnr);
- fprintf(th, "#define endevent endstate%d\n", eventmapnr);
+ fprintf(th, "#define endevent _endstate%d\n", eventmapnr);
if (eventmap[2] == 'o') /* ":notrace:" */
fprintf(th, "#define NEGATED_TRACE 1\n");
}
- fprintf(th, "typedef struct S_F_MAP {\n");
- fprintf(th, " char *fnm; int from; int upto;\n");
+ fprintf(th, "\ntypedef struct S_F_MAP {\n");
+ fprintf(th, " char *fnm;\n\tint from;\n\tint upto;\n");
fprintf(th, "} S_F_MAP;\n");
- fprintf(tc, "/*** Generated by %s ***/\n", Version);
+ fprintf(tc, "/*** Generated by %s ***/\n", SpinVersion);
fprintf(tc, "/*** From source: %s ***/\n\n", oFname->name);
ntimes(tc, 0, 1, Pre0);
@@ -304,19 +461,36 @@
case 2: fprintf(tc, "#include \"pan_t.h\"\n"); break;
}
+ if (separate != 2)
+ { fprintf(tc, "char *TrailFile = PanSource; /* default */\n");
+ fprintf(tc, "char *trailfilename;\n");
+ }
+
+ fprintf(tc, "#ifdef LOOPSTATE\n");
+ fprintf(tc, "double cnt_loops;\n");
+ fprintf(tc, "#endif\n");
+
fprintf(tc, "State A_Root; /* seed-state for cycles */\n");
fprintf(tc, "State now; /* the full state-vector */\n");
+ fprintf(tc, "#if NQS > 0\n");
+ fprintf(tc, "short q_flds[NQS+1];\n");
+ fprintf(tc, "short q_max[NQS+1];\n");
+ fprintf(tc, "#endif\n");
+
plunk_c_fcts(tc); /* State can be used in fcts */
if (separate != 2)
- ntimes(tc, 0, 1, Preamble);
- else
- fprintf(tc, "extern int verbose; extern long depth;\n");
+ { ntimes(tc, 0, 1, Preamble);
+ ntimes(tc, 0, 1, Separate); /* things that moved out of pan.h */
+ } else
+ { fprintf(tc, "extern int verbose;\n");
+ fprintf(tc, "extern long depth, depthfound;\n");
+ }
fprintf(tc, "#ifndef NOBOUNDCHECK\n");
- fprintf(tc, "#define Index(x, y)\tBoundcheck(x, y, II, tt, t)\n");
+ fprintf(tc, " #define Index(x, y)\tBoundcheck(x, y, II, tt, t)\n");
fprintf(tc, "#else\n");
- fprintf(tc, "#define Index(x, y)\tx\n");
+ fprintf(tc, " #define Index(x, y)\tx\n");
fprintf(tc, "#endif\n");
c_preview(); /* sets hastrack */
@@ -335,7 +509,7 @@
fprintf(tt, "}\n\n");
fprintf(tt, "void\nputpeg(int n, int m)\n");
fprintf(tt, "{ printf(\"%%5d\ttrans %%4d \", m, n);\n");
- fprintf(tt, " printf(\"file %%s line %%3d\\n\",\n");
+ fprintf(tt, " printf(\"%%s:%%d\\n\",\n");
fprintf(tt, " T_SRC[n].fl, T_SRC[n].ln);\n");
fprintf(tt, "}\n");
if (!merger)
@@ -359,13 +533,18 @@
}
fprintf(tm, "#define rand pan_rand\n");
+ fprintf(tm, "#define pthread_equal(a,b) ((a)==(b))\n");
fprintf(tm, "#if defined(HAS_CODE) && defined(VERBOSE)\n");
- fprintf(tm, " printf(\"Pr: %%d Tr: %%d\\n\", II, t->forw);\n");
+ fprintf(tm, " #ifdef BFS_PAR\n");
+ fprintf(tm, " bfs_printf(\"Pr: %%d Tr: %%d\\n\", II, t->forw);\n");
+ fprintf(tm, " #else\n");
+ fprintf(tm, " cpu_printf(\"Pr: %%d Tr: %%d\\n\", II, t->forw);\n");
+ fprintf(tm, " #endif\n");
fprintf(tm, "#endif\n");
fprintf(tm, " switch (t->forw) {\n");
} else
{ fprintf(tt, "#ifndef PEG\n");
- fprintf(tt, "#define tr_2_src(m,f,l)\n");
+ fprintf(tt, " #define tr_2_src(m,f,l)\n");
fprintf(tt, "#endif\n");
fprintf(tt, "void\nset_claim(void)\n{\tTrans *T;\n");
fprintf(tt, "\textern Trans ***trans;\n");
@@ -373,8 +552,9 @@
fprintf(tt, " char *, int, int, int);\n\n");
fprintf(tm, "#define rand pan_rand\n");
+ fprintf(tm, "#define pthread_equal(a,b) ((a)==(b))\n");
fprintf(tm, "#if defined(HAS_CODE) && defined(VERBOSE)\n");
- fprintf(tm, " printf(\"Pr: %%d Tr: %%d\\n\", II, forw);\n");
+ fprintf(tm, " cpu_printf(\"Pr: %%d Tr: %%d\\n\", II, forw);\n");
fprintf(tm, "#endif\n");
fprintf(tm, " switch (forw) {\n");
}
@@ -404,25 +584,48 @@
fprintf(tb, " case 0: goto R999; /* nothing to undo */\n");
for (p = rdy; p; p = p->nxt)
- putproc(p);
+ { putproc(p);
+ }
-
if (separate != 2)
- { fprintf(th, "struct {\n");
- fprintf(th, " int tp; short *src;\n");
- fprintf(th, "} src_all[] = {\n");
+ { fprintf(th, "\n");
for (p = rdy; p; p = p->nxt)
- fprintf(th, " { %d, &src_ln%d[0] },\n",
+ fprintf(th, "extern short src_ln%d[];\n", p->tn);
+ for (p = rdy; p; p = p->nxt)
+ fprintf(th, "extern S_F_MAP src_file%d[];\n", p->tn);
+ fprintf(th, "\n");
+
+ fprintf(tc, "uchar reached%d[3]; /* np_ */\n", nrRdy);
+ fprintf(tc, "uchar *loopstate%d; /* np_ */\n", nrRdy);
+
+ fprintf(tc, "struct {\n");
+ fprintf(tc, " int tp; short *src;\n");
+ fprintf(tc, "} src_all[] = {\n");
+ for (p = rdy; p; p = p->nxt)
+ fprintf(tc, " { %d, &src_ln%d[0] },\n",
p->tn, p->tn);
- fprintf(th, " { 0, (short *) 0 }\n");
- fprintf(th, "};\n");
- fprintf(th, "short *frm_st0;\n"); /* records src states for transitions in never claim */
+ fprintf(tc, " { 0, (short *) 0 }\n");
+ fprintf(tc, "};\n");
+
+ fprintf(tc, "S_F_MAP *flref[] = {\n"); /* 5.3.0 */
+ for (p = rdy; p; p = p->nxt)
+ { fprintf(tc, " src_file%d%c\n", p->tn, p->nxt?',':' ');
+ }
+ fprintf(tc, "};\n\n");
} else
- { fprintf(th, "extern short *frm_st0;\n");
+ { fprintf(tc, "extern uchar reached%d[3]; /* np_ */\n", nrRdy);
}
- gencodetable(th);
+ gencodetable(tc); /* was th */
+ if (Unique < (1 << (8*sizeof(unsigned char)) )) /* was uniq before */
+ { fprintf(th, "#define T_ID unsigned char\n");
+ } else if (Unique < (1 << (8*sizeof(unsigned short)) ))
+ { fprintf(th, "#define T_ID unsigned short\n");
+ } else
+ { fprintf(th, "#define T_ID unsigned int\n");
+ }
+
if (separate != 1)
{ tm_predef_np();
tt_predef_np();
@@ -438,13 +641,13 @@
genheader();
if (separate == 1)
{ fprintf(th, "#define FORWARD_MOVES\t\"pan_s.m\"\n");
- fprintf(th, "#define REVERSE_MOVES\t\"pan_s.b\"\n");
+ fprintf(th, "#define BACKWARD_MOVES\t\"pan_s.b\"\n");
fprintf(th, "#define SEPARATE\n");
fprintf(th, "#define TRANSITIONS\t\"pan_s.t\"\n");
fprintf(th, "extern void ini_claim(int, int);\n");
} else
{ fprintf(th, "#define FORWARD_MOVES\t\"pan.m\"\n");
- fprintf(th, "#define REVERSE_MOVES\t\"pan.b\"\n");
+ fprintf(th, "#define BACKWARD_MOVES\t\"pan.b\"\n");
fprintf(th, "#define TRANSITIONS\t\"pan.t\"\n");
}
genaddproc();
@@ -456,33 +659,37 @@
if (!run) fatal("no runable process", (char *)0);
fprintf(tc, "void\n");
fprintf(tc, "active_procs(void)\n{\n");
+
+ fprintf(tc, " if (reversing == 0) {\n");
reverse_procs(run);
+ fprintf(tc, " } else {\n");
+ forward_procs(run);
+ fprintf(tc, " }\n");
+
fprintf(tc, "}\n");
ntimes(tc, 0, 1, Dfa);
ntimes(tc, 0, 1, Xpt);
fprintf(th, "#define NTRANS %d\n", uniq);
- fprintf(th, "#ifdef PEG\n");
- fprintf(th, "long peg[NTRANS];\n");
- fprintf(th, "#endif\n");
-
if (u_sync && !u_async)
- spit_recvs(th, tc);
+ { spit_recvs(th, tc);
+ }
} else
{ genheader();
fprintf(th, "#define FORWARD_MOVES\t\"pan_t.m\"\n");
- fprintf(th, "#define REVERSE_MOVES\t\"pan_t.b\"\n");
+ fprintf(th, "#define BACKWARD_MOVES\t\"pan_t.b\"\n");
fprintf(th, "#define TRANSITIONS\t\"pan_t.t\"\n");
fprintf(tc, "extern int Maxbody;\n");
fprintf(tc, "#if VECTORSZ>32000\n");
- fprintf(tc, "extern int proc_offset[];\n");
+ fprintf(tc, " extern int *proc_offset;\n");
fprintf(tc, "#else\n");
- fprintf(tc, "extern short proc_offset[];\n");
+ fprintf(tc, " extern short *proc_offset;\n");
fprintf(tc, "#endif\n");
- fprintf(tc, "extern uchar proc_skip[];\n");
+ fprintf(tc, "extern uchar *proc_skip;\n");
fprintf(tc, "extern uchar *reached[];\n");
fprintf(tc, "extern uchar *accpstate[];\n");
fprintf(tc, "extern uchar *progstate[];\n");
+ fprintf(tc, "extern uchar *loopstate[];\n");
fprintf(tc, "extern uchar *stopstate[];\n");
fprintf(tc, "extern uchar *visstate[];\n\n");
fprintf(tc, "extern short *mapstate[];\n");
@@ -491,7 +698,7 @@
fprintf(tc, "\textern State now;\n");
fprintf(tc, "\textern void set_claim(void);\n\n");
fprintf(tc, "#ifdef PROV\n");
- fprintf(tc, "#include PROV\n");
+ fprintf(tc, " #include PROV\n");
fprintf(tc, "#endif\n");
fprintf(tc, "\tset_claim();\n");
genother();
@@ -509,13 +716,42 @@
fprintf(tc, "int\nrev_claim(int backw)\n{ return 0; }\n");
fprintf(tc, "#include TRANSITIONS\n");
}
- if (separate != 1)
- ntimes(tc, 0, 1, Nvr1);
if (separate != 2)
{ c_wrapper(tc);
c_chandump(tc);
}
+
+ fprintf(th, "#if defined(BFS_PAR) || NCORE>1\n");
+ fprintf(th, " void e_critical(int);\n");
+ fprintf(th, " void x_critical(int);\n");
+ fprintf(th, " #ifdef BFS_PAR\n");
+ fprintf(th, " void bfs_main(int, int);\n");
+ fprintf(th, " void bfs_report_mem(void);\n");
+ fprintf(th, " #endif\n");
+ fprintf(th, "#endif\n");
+
+ fprintf(th, "\n\n/* end of PAN_H */\n#endif\n");
+ fclose(th);
+ fclose(tt);
+ fclose(tm);
+ fclose(tb);
+
+ if (!(th = fopen("pan.p", MFLAGS)))
+ { printf("spin: cannot create pan.p for -DBFS_PAR\n");
+ return; /* we're done anyway */
+ }
+
+ ntimes(th, 0, 1, pan_par); /* BFS_PAR */
+ fclose(th);
+
+ fprintf(tc, "\nTrans *t_id_lkup[%d];\n\n", globmax+1);
+
+ if (separate != 2)
+ { fprintf(tc, "\n#ifdef BFS_PAR\n\t#include \"pan.p\"\n#endif\n");
+ }
+ fprintf(tc, "\n/* end of pan.c */\n");
+ fclose(tc);
}
static int
@@ -537,13 +773,13 @@
fprintf(tc, "%s(", pre);
if (!(s->hidden&1))
{ if (s->context)
- fprintf(tc, "((P%d *)this)->", pid);
+ fprintf(tc, "(int) ( ((P%d *)this)->", pid);
else
- fprintf(tc, "now.");
+ fprintf(tc, "(int) ( now.");
}
fprintf(tc, "%s", s->name);
- if (qln > 1) fprintf(tc, "[%d]", ai);
- fprintf(tc, ")");
+ if (qln > 1 || s->isarray) fprintf(tc, "[%d]", ai);
+ fprintf(tc, ") )");
}
struct AA { char TT[9]; char CC[8]; };
@@ -712,47 +948,60 @@
fprintf(tc, "}\n");
}
+extern int find_min(Sequence *);
+extern int find_max(Sequence *);
+
static void
putproc(ProcList *p)
{ Pid = p->tn;
Det = p->det;
- if (Pid == claimnr
+ if (pid_is_claim(Pid)
&& separate == 1)
{ fprintf(th, "extern uchar reached%d[];\n", Pid);
#if 0
- fprintf(th, "extern short nstates%d;\n", Pid);
+ fprintf(th, "extern short _nstates%d;\n", Pid);
#else
- fprintf(th, "\n#define nstates%d %d\t/* %s */\n",
+ fprintf(th, "\n#define _nstates%d %d\t/* %s */\n",
Pid, p->s->maxel, p->n->name);
#endif
fprintf(th, "extern short src_ln%d[];\n", Pid);
+ fprintf(th, "extern uchar *loopstate%d;\n", Pid);
fprintf(th, "extern S_F_MAP src_file%d[];\n", Pid);
- fprintf(th, "#define endstate%d %d\n",
+ fprintf(th, "#define _endstate%d %d\n",
Pid, p->s->last?p->s->last->seqno:0);
- fprintf(th, "#define src_claim src_ln%d\n", claimnr);
-
return;
}
- if (Pid != claimnr
+ if (!pid_is_claim(Pid)
&& separate == 2)
{ fprintf(th, "extern short src_ln%d[];\n", Pid);
+ fprintf(th, "extern uchar *loopstate%d;\n", Pid);
return;
}
AllGlobal = (p->prov)?1:0; /* process has provided clause */
- fprintf(th, "\n#define nstates%d %d\t/* %s */\n",
+ fprintf(th, "\n#define _nstates%d %d\t/* %s */\n",
Pid, p->s->maxel, p->n->name);
- if (Pid == claimnr)
- fprintf(th, "#define nstates_claim nstates%d\n", Pid);
+/* new */
+ fprintf(th, "#define minseq%d %d\n", Pid, find_min(p->s));
+ fprintf(th, "#define maxseq%d %d\n", Pid, find_max(p->s));
+
+/* end */
+
if (Pid == eventmapnr)
- fprintf(th, "#define nstates_event nstates%d\n", Pid);
+ fprintf(th, "#define nstates_event _nstates%d\n", Pid);
- fprintf(th, "#define endstate%d %d\n",
- Pid, p->s->last->seqno);
- fprintf(tm, "\n /* PROC %s */\n", p->n->name);
- fprintf(tb, "\n /* PROC %s */\n", p->n->name);
+ fprintf(th, "#define _endstate%d %d\n", Pid, p->s->last?p->s->last->seqno:0);
+
+ if (p->b == N_CLAIM || p->b == E_TRACE || p->b == N_TRACE)
+ { fprintf(tm, "\n /* CLAIM %s */\n", p->n->name);
+ fprintf(tb, "\n /* CLAIM %s */\n", p->n->name);
+ }
+ else
+ { fprintf(tm, "\n /* PROC %s */\n", p->n->name);
+ fprintf(tb, "\n /* PROC %s */\n", p->n->name);
+ }
fprintf(tt, "\n /* proctype %d: %s */\n", Pid, p->n->name);
fprintf(tt, "\n trans[%d] = (Trans **)", Pid);
fprintf(tt, " emalloc(%d*sizeof(Trans *));\n\n", p->s->maxel);
@@ -761,7 +1010,6 @@
{ fprintf(th, "\n#define in_s_scope(x_y3_) 0");
fprintf(tc, "\n#define in_r_scope(x_y3_) 0");
}
-
put_seq(p->s, 2, 0);
if (Pid == eventmapnr)
{ fprintf(th, "\n\n");
@@ -947,10 +1195,10 @@
if (e->n->ntyp == D_STEP)
{ int inherit = (e->status&(ATOM|L_ATOM));
fprintf(tm, "\tcase %d: ", uniq++);
- fprintf(tm, "/* STATE %d - line %d %s - [",
- e->seqno, e->n->ln, e->n->fn->name);
+ fprintf(tm, "// STATE %d - %s:%d - [",
+ e->seqno, e->n->fn->name, e->n->ln);
comment(tm, e->n, 0);
- fprintf(tm, "] */\n\t\t");
+ fprintf(tm, "]\n\t\t");
if (s->last->n->ntyp == BREAK)
OkBreak = target(huntele(s->last->nxt,
@@ -971,7 +1219,7 @@
}
fprintf(tb, "\tcase %d: ", uniq-1);
- fprintf(tb, "/* STATE %d */\n", e->seqno);
+ fprintf(tb, "// STATE %d\n", e->seqno);
fprintf(tb, "\t\tsv_restor();\n");
fprintf(tb, "\t\tgoto R999;\n");
if (e->nxt)
@@ -1024,7 +1272,7 @@
struct CaseCache *nxt;
} CaseCache;
-CaseCache *casing[6];
+static CaseCache *casing[6];
static int
identical(Lextok *p, Lextok *q)
@@ -1076,6 +1324,9 @@
if (stopat)
while (f && f->seqno != stopat)
{ f = findnext(f);
+ if (!f)
+ { break;
+ }
switch (f->n->ntyp) {
case GOTO:
case '.':
@@ -1084,8 +1335,7 @@
break;
default:
return f;
- }
- }
+ } }
return (Element *) 0;
}
@@ -1107,18 +1357,16 @@
if (!stopat_a && !stopat_b)
return 1;
- for (;;)
- {
- f = advance(a, stopat_a);
- g = advance(b, stopat_b);
- if (!f && !g)
- return 1;
- if (f && g)
- return identical(f->n, g->n);
- else
- return 0;
- }
- return 1;
+ f = advance(a, stopat_a);
+ g = advance(b, stopat_b);
+
+ if (!f && !g)
+ return 1;
+
+ if (f && g)
+ return identical(f->n, g->n);
+
+ return 0;
}
static CaseCache *
@@ -1174,6 +1422,7 @@
switch (e->n->ntyp) {
case ASGN:
+ if (check_track(e->n) == STRUCT) { break; }
nr++;
break;
case 'r':
@@ -1234,10 +1483,10 @@
}
if (f && !f->merge && !f->merge_single && f->seqno != stopat)
- { fprintf(tm, "\n\t\tbad hop %s:%d -- at %d, <",
+ { fprintf(tm, "\n\t\t// bad hop %s:%d -- at %d, <",
f->n->fn->name,f->n->ln, f->seqno);
comment(tm, f->n, 0);
- fprintf(tm, "> looking for %d -- merge %d:%d:%d\n\t\t",
+ fprintf(tm, "> looking for %d -- merge %d:%d:%d ",
stopat, f->merge, f->merge_start, f->merge_single);
break;
}
@@ -1258,18 +1507,20 @@
}
static void
-doforward(FILE *tm, Element *e)
+doforward(FILE *tm_fd, Element *e)
{ FSM_use *u;
- putstmnt(tm, e->n, e->seqno);
+ putstmnt(tm_fd, e->n, e->seqno);
if (e->n->ntyp != ELSE && Det)
- { fprintf(tm, ";\n\t\tif (trpt->o_pm&1)\n\t\t");
- fprintf(tm, "\tuerror(\"non-determinism in D_proctype\")");
+ { fprintf(tm_fd, ";\n\t\tif (trpt->o_pm&1)\n\t\t");
+ fprintf(tm_fd, "\tuerror(\"non-determinism in D_proctype\")");
}
if (deadvar && !has_code)
for (u = e->dead; u; u = u->nxt)
- { fprintf(tm, ";\n\t\t/* dead %d: %s */ ",
+ { fprintf(tm_fd, ";\n\t\t");
+ fprintf(tm_fd, "if (TstOnly) return 1; /* TT */\n");
+ fprintf(tm_fd, "\t\t/* dead %d: %s */ ",
u->special, u->var->name);
switch (u->special) {
@@ -1281,10 +1532,10 @@
}
if (e->n->ntyp != 'r')
{ XZ.sym = u->var;
- fprintf(tm, "\n#ifdef HAS_CODE\n");
- fprintf(tm, "\t\tif (!readtrail)\n");
- fprintf(tm, "#endif\n\t\t\t");
- putname(tm, "", &XZ, 0, " = 0");
+ fprintf(tm_fd, "\n#ifdef HAS_CODE\n");
+ fprintf(tm_fd, "\t\tif (!readtrail)\n");
+ fprintf(tm_fd, "#endif\n\t\t\t");
+ putname(tm_fd, "", &XZ, 0, " = 0");
break;
} /* else fall through */
case 1: /* dead after read -- add asgn of rval -- needs bup */
@@ -1292,20 +1543,20 @@
CnT[YZcnt]++; /* this step added bups */
if (multi_oval)
{ check_needed();
- fprintf(tm, "(trpt+1)->bup.ovals[%d] = ",
+ fprintf(tm_fd, "(trpt+1)->bup.ovals[%d] = ",
multi_oval-1);
multi_oval++;
} else
- fprintf(tm, "(trpt+1)->bup.oval = ");
- putname(tm, "", &YZ[YZmax], 0, ";\n");
- fprintf(tm, "#ifdef HAS_CODE\n");
- fprintf(tm, "\t\tif (!readtrail)\n");
- fprintf(tm, "#endif\n\t\t\t");
- putname(tm, "", &YZ[YZmax], 0, " = 0");
+ fprintf(tm_fd, "(trpt+1)->bup.oval = ");
+ putname(tm_fd, "", &YZ[YZmax], 0, ";\n");
+ fprintf(tm_fd, "#ifdef HAS_CODE\n");
+ fprintf(tm_fd, "\t\tif (!readtrail)\n");
+ fprintf(tm_fd, "#endif\n\t\t\t");
+ putname(tm_fd, "", &YZ[YZmax], 0, " = 0");
YZmax++;
break;
} }
- fprintf(tm, ";\n\t\t");
+ fprintf(tm_fd, ";\n\t\t");
}
static int
@@ -1318,7 +1569,7 @@
if (!didcase)
{ fprintf(tb, "\n\tcase %d: ", casenr);
- fprintf(tb, "/* STATE %d */\n\t\t", e->seqno);
+ fprintf(tb, "// STATE %d\n\t\t", e->seqno);
didcase++;
}
@@ -1412,7 +1663,7 @@
{ int bupcase = 0, casenr = uniq, fromcache = 0;
CaseCache *Cached = (CaseCache *) 0;
Element *f, *g;
- int j, nrbups, mark, target;
+ int j, nrbups, mark, ntarget;
extern int ccache;
mark = (e->status&ATOM); /* could lose atomicity in a merge chain */
@@ -1439,7 +1690,7 @@
fprintf(tt, "\ttrans[%d][%d]\t= ", Pid, e->seqno);
if (ccache
- && Pid != claimnr
+ && !pid_is_claim(Pid)
&& Pid != eventmapnr
&& (Cached = prev_case(e, Pid)))
{ bupcase = Cached->b;
@@ -1446,10 +1697,10 @@
casenr = Cached->m;
fromcache = 1;
- fprintf(tm, "/* STATE %d - line %d %s - [",
- e->seqno, e->n->ln, e->n->fn->name);
+ fprintf(tm, "// STATE %d - %s:%d - [",
+ e->seqno, e->n->fn->name, e->n->ln);
comment(tm, e->n, 0);
- fprintf(tm, "] (%d:%d - %d) same as %d (%d:%d - %d) */\n",
+ fprintf(tm, "] (%d:%d - %d) same as %d (%d:%d - %d)\n",
e->merge_start, e->merge, e->merge_in,
casenr,
Cached->e->merge_start, Cached->e->merge, Cached->e->merge_in);
@@ -1457,17 +1708,17 @@
goto gotit;
}
- fprintf(tm, "\tcase %d: /* STATE %d - line %d %s - [",
- uniq++, e->seqno, e->n->ln, e->n->fn->name);
+ fprintf(tm, "\tcase %d: // STATE %d - %s:%d - [",
+ uniq++, e->seqno, e->n->fn->name, e->n->ln);
comment(tm, e->n, 0);
nrbups = (e->merge || e->merge_start) ? nrhops(e) : nr_bup(e);
- fprintf(tm, "] (%d:%d:%d - %d) */\n\t\t",
+ fprintf(tm, "] (%d:%d:%d - %d)\n\t\t",
e->merge_start, e->merge, nrbups, e->merge_in);
if (nrbups > MAXMERGE-1)
fatal("merge requires more than 256 bups", (char *)0);
- if (e->n->ntyp != 'r' && Pid != claimnr && Pid != eventmapnr)
+ if (e->n->ntyp != 'r' && !pid_is_claim(Pid) && Pid != eventmapnr)
fprintf(tm, "IfNotBlocked\n\t\t");
if (multi_needed != 0 || multi_undo != 0)
@@ -1482,18 +1733,29 @@
memset(CnT, 0, sizeof(CnT));
YZmax = YZcnt = 0;
-/* NEW 4.2.6 */
- if (Pid == claimnr)
- {
- fprintf(tm, "\n#if defined(VERI) && !defined(NP)\n\t\t");
- fprintf(tm, "{ static int reported%d = 0;\n\t\t", e->seqno);
- /* source state changes in retrans and must be looked up in frm_st0[t->forw] */
- fprintf(tm, " if (verbose && !reported%d)\n\t\t", e->seqno);
- fprintf(tm, " { printf(\"depth %%d: Claim reached state %%d (line %%d)\\n\",\n\t\t");
- fprintf(tm, " depth, frm_st0[t->forw], src_claim[%d]);\n\t\t", e->seqno);
- fprintf(tm, " reported%d = 1;\n\t\t", e->seqno);
- fprintf(tm, " fflush(stdout);\n\t\t");
- fprintf(tm, "} }\n");
+/* new 4.2.6, revised 6.0.0 */
+ if (pid_is_claim(Pid))
+ { fprintf(tm, "\n#if defined(VERI) && !defined(NP)\n");
+ fprintf(tm, "#if NCLAIMS>1\n\t\t");
+ fprintf(tm, "{ static int reported%d = 0;\n\t\t", e->seqno);
+ fprintf(tm, " if (verbose && !reported%d)\n\t\t", e->seqno);
+ fprintf(tm, " { int nn = (int) ((Pclaim *)pptr(0))->_n;\n\t\t");
+ fprintf(tm, " printf(\"depth %%ld: Claim %%s (%%d), state %%d (line %%d)\\n\",\n\t\t");
+ fprintf(tm, " depth, procname[spin_c_typ[nn]], nn, ");
+ fprintf(tm, "(int) ((Pclaim *)pptr(0))->_p, src_claim[ (int) ((Pclaim *)pptr(0))->_p ]);\n\t\t");
+ fprintf(tm, " reported%d = 1;\n\t\t", e->seqno);
+ fprintf(tm, " fflush(stdout);\n\t\t");
+ fprintf(tm, "} }\n");
+ fprintf(tm, "#else\n\t\t");
+ fprintf(tm, "{ static int reported%d = 0;\n\t\t", e->seqno);
+ fprintf(tm, " if (verbose && !reported%d)\n\t\t", e->seqno);
+ fprintf(tm, " { printf(\"depth %%d: Claim, state %%d (line %%d)\\n\",\n\t\t");
+ fprintf(tm, " (int) depth, (int) ((Pclaim *)pptr(0))->_p, ");
+ fprintf(tm, "src_claim[ (int) ((Pclaim *)pptr(0))->_p ]);\n\t\t");
+ fprintf(tm, " reported%d = 1;\n\t\t", e->seqno);
+ fprintf(tm, " fflush(stdout);\n\t\t");
+ fprintf(tm, "} }\n");
+ fprintf(tm, "#endif\n");
fprintf(tm, "#endif\n\t\t");
}
/* end */
@@ -1504,32 +1766,32 @@
doforward(tm, e);
if (e->merge_start)
- target = e->merge_start;
+ ntarget = e->merge_start;
else
- target = e->merge;
+ ntarget = e->merge;
- if (target)
+ if (ntarget)
{ f = e;
more: if (f->n->ntyp == GOTO)
{ g = get_lab(f->n, 1);
- if (g->seqno == target)
+ if (g->seqno == ntarget)
f = g;
else
- f = huntele(g, f->status, target);
+ f = huntele(g, f->status, ntarget);
} else
f = f->nxt;
- if (f && f->seqno != target)
+ if (f && f->seqno != ntarget)
{ if (!f->merge && !f->merge_single)
{ fprintf(tm, "/* stop at bad hop %d, %d */\n\t\t",
- f->seqno, target);
+ f->seqno, ntarget);
goto out;
}
fprintf(tm, "/* merge: ");
comment(tm, f->n, 0);
- fprintf(tm, "(%d, %d, %d) */\n\t\t", f->merge, f->seqno, target);
+ fprintf(tm, "(%d, %d, %d) */\n\t\t", f->merge, f->seqno, ntarget);
fprintf(tm, "reached[%d][%d] = 1;\n\t\t", Pid, f->seqno);
YZcnt++;
lab_transfer(e, f);
@@ -1547,8 +1809,8 @@
multi_needed = 0;
didcase = 0;
- if (target)
- lastfirst(target, e, casenr); /* mergesteps only */
+ if (ntarget)
+ lastfirst(ntarget, e, casenr); /* mergesteps only */
dobackward(e, casenr); /* the original step */
@@ -1557,7 +1819,7 @@
if (e->merge || e->merge_start)
{ if (!didcase)
{ fprintf(tb, "\n\tcase %d: ", casenr);
- fprintf(tb, "/* STATE %d */", e->seqno);
+ fprintf(tb, "// STATE %d", e->seqno);
didcase++;
} else
fprintf(tb, ";");
@@ -1607,8 +1869,8 @@
} else
a = 0;
if (g
- && (g->status&CHECK2 /* entering remotely ref'd state */
- || e->status&CHECK2)) /* leaving remotely ref'd state */
+ && ((g->status&CHECK2) /* entering remotely ref'd state */
+ || (e->status&CHECK2))) /* leaving remotely ref'd state */
e->status |= I_GLOB;
/* don't remove dead edges in here, to preserve structure of fsm */
@@ -1758,8 +2020,8 @@
{ fprintf(tt, "#if 0\n\t/* dead link: */\n");
deadlink = 1;
if (verbose&32)
- printf("spin: line %3d %s, Warning: condition is always false\n",
- g->n->ln, g->n->fn?g->n->fn->name:"");
+ printf("spin: %s:%d, warning, condition is always false\n",
+ g->n->fn?g->n->fn->name:"", g->n->ln);
} else
deadlink = 0;
if (0) printf(" settr %d %d\n", a, 0);
@@ -1867,7 +2129,7 @@
case BREAK:
if (e->nxt)
{ f = find_target(huntele(e->nxt, e->status, -1));
- break; /* 4.3.0 -- was missing */
+ break; /* new 5.0 -- was missing */
}
/* else fall through */
default:
@@ -1888,6 +2150,26 @@
}
static int
+seq_has_el(Sequence *s, Element *g) /* new to version 5.0 */
+{ Element *f;
+ SeqList *h;
+
+ for (f = s->frst; f; f = f->nxt) /* g in same atomic? */
+ { if (f == g)
+ { return 1;
+ }
+ if (f->status & CHECK3)
+ { continue;
+ }
+ f->status |= CHECK3; /* protect against cycles */
+ for (h = f->sub; h; h = h->nxt)
+ { if (h->this && seq_has_el(h->this, g))
+ { return 1;
+ } } }
+ return 0;
+}
+
+static int
scan_seq(Sequence *s)
{ Element *f, *g;
SeqList *h;
@@ -1896,20 +2178,22 @@
{ if ((f->status&CHECK2)
|| has_global(f->n))
return 1;
- if (f->n->ntyp == GOTO) /* may reach other atomic */
- {
-#if 0
- /* if jumping from an atomic without globals into
- * one with globals, this does the wrong thing
+ if (f->n->ntyp == GOTO /* may exit or reach other atomic */
+ && !(f->status & D_ATOM)) /* cannot jump from d_step */
+ { /* consider jump from an atomic without globals into
+ * an atomic with globals
* example by Claus Traulsen, 22 June 2007
*/
g = target(f);
+#if 1
+ if (g && !seq_has_el(s, g)) /* not internal to this atomic/dstep */
+
+#else
if (g
&& !(f->status & L_ATOM)
&& !(g->status & (ATOM|L_ATOM)))
#endif
- { fprintf(tt, " /* mark-down line %d */\n",
- f->n->ln);
+ { fprintf(tt, "\t/* mark-down line %d status %d = %d */\n", f->n->ln, f->status, (f->status & D_ATOM));
return 1; /* assume worst case */
} }
for (h = f->sub; h; h = h->nxt)
@@ -1937,9 +2221,26 @@
return result;
}
+static int
+proc_is_safe(const Lextok *n)
+{ ProcList *p;
+ /* not safe unless no local var inits are used */
+ /* note that a local variable init could refer to a global */
+
+ for (p = rdy; p; p = p->nxt)
+ { if (strcmp(n->sym->name, p->n->name) == 0)
+ { /* printf("proc %s safety: %d\n", p->n->name, p->unsafe); */
+ return (p->unsafe != 0);
+ } }
+/* non_fatal("bad call to proc_is_safe", (char *) 0); */
+ /* cannot happen */
+ return 0;
+}
+
int
has_global(Lextok *n)
-{ Lextok *v; extern int runsafe;
+{ Lextok *v;
+ static Symbol *n_seen = (Symbol *) 0;
if (!n) return 0;
if (AllGlobal) return 1; /* global provided clause */
@@ -1968,6 +2269,14 @@
case LEN: return (((n->sym->xu)&(XR|XS|XX)) != (XR|XS));
case NAME:
+ if (strcmp(n->sym->name, "_priority") == 0)
+ { if (old_priority_rules)
+ { if (n_seen != n->sym)
+ fatal("cannot refer to _priority with -o6", (char *) 0);
+ n_seen = n->sym;
+ }
+ return 0;
+ }
if (n->sym->context
|| (n->sym->hidden&64)
|| strcmp(n->sym->name, "_pid") == 0
@@ -1975,14 +2284,15 @@
return 0;
return 1;
- case RUN: return 1-runsafe;
+ case RUN:
+ return proc_is_safe(n);
case C_CODE: case C_EXPR:
return glob_inline(n->sym->name);
case ENABLED: case PC_VAL: case NONPROGRESS:
- case 'p': case 'q':
- case TIMEOUT:
+ case 'p': case 'q':
+ case TIMEOUT: case SET_P: case GET_P:
return 1;
/* @ was 1 (global) since 2.8.5
@@ -2017,11 +2327,12 @@
Bailout(FILE *fd, char *str)
{
if (!GenCode)
- fprintf(fd, "continue%s", str);
- else if (IsGuard)
- fprintf(fd, "%s%s", NextLab[Level], str);
- else
- fprintf(fd, "Uerror(\"block in step seq\")%s", str);
+ { fprintf(fd, "continue%s", str);
+ } else if (IsGuard)
+ { fprintf(fd, "%s%s", NextLab[Level], str);
+ } else
+ { fprintf(fd, "Uerror(\"block in d_step seq\")%s", str);
+ }
}
#define cat0(x) putstmnt(fd,now->lft,m); fprintf(fd, x); \
@@ -2029,6 +2340,7 @@
#define cat1(x) fprintf(fd,"("); cat0(x); fprintf(fd,")")
#define cat2(x,y) fprintf(fd,x); putstmnt(fd,y,m)
#define cat3(x,y,z) fprintf(fd,x); putstmnt(fd,y,m); fprintf(fd,z)
+#define cat30(x,y,z) fprintf(fd,x,0); putstmnt(fd,y,m); fprintf(fd,z)
void
putstmnt(FILE *fd, Lextok *now, int m)
@@ -2070,12 +2382,14 @@
else
fprintf(fd, "((trpt->tau)&1)");
if (GenCode)
- printf("spin: line %3d, warning: 'timeout' in d_step sequence\n",
- lineno);
+ printf("spin: %s:%d, warning, 'timeout' in d_step sequence\n",
+ Fname->name, lineno);
/* is okay as a guard */
break;
case RUN:
+ if (now->sym == NULL)
+ fatal("internal error pangen2.c", (char *) 0);
if (claimproc
&& strcmp(now->sym->name, claimproc) == 0)
fatal("claim %s, (not runnable)", claimproc);
@@ -2084,10 +2398,11 @@
fatal("eventmap %s, (not runnable)", eventmap);
if (GenCode)
- fatal("'run' in d_step sequence (use atomic)",
- (char *)0);
+ fatal("'run' in d_step sequence (use atomic)", (char *)0);
- fprintf(fd,"addproc(%d", fproc(now->sym->name));
+ fprintf(fd,"addproc(II, %d, %d",
+ (now->val > 0 && !old_priority_rules) ? now->val : 1,
+ fproc(now->sym->name));
for (v = now->lft, i = 0; v; v = v->rgt, i++)
{ cat2(", ", v->lft);
}
@@ -2094,13 +2409,21 @@
check_param_count(i, now);
if (i > Npars)
- { printf("\t%d parameters used, max %d expected\n", i, Npars);
- fatal("too many parameters in run %s(...)",
- now->sym->name);
+ { /* printf("\t%d parameters used, max %d expected\n", i, Npars); */
+ fatal("too many parameters in run %s(...)", now->sym->name);
}
for ( ; i < Npars; i++)
fprintf(fd, ", 0");
fprintf(fd, ")");
+#if 0
+ /* process now->sym->name has run priority now->val */
+ if (now->val > 0 && now->val < 256 && !old_priority_rules)
+ { fprintf(fd, " && (((P0 *)pptr(now._nr_pr - 1))->_priority = %d)", now->val);
+ }
+#endif
+ if (now->val < 0 || now->val > 255) /* 0 itself is allowed */
+ { fatal("bad process in run %s, valid range: 1..255", now->sym->name);
+ }
break;
case ENABLED:
@@ -2107,6 +2430,25 @@
cat3("enabled(II, ", now->lft, ")");
break;
+ case GET_P:
+ if (old_priority_rules)
+ { fprintf(fd, "1");
+ } else
+ { cat3("get_priority(", now->lft, ")");
+ }
+ break;
+
+ case SET_P:
+ if (!old_priority_rules)
+ { fprintf(fd, "if (TstOnly) return 1; /* T30 */\n\t\t");
+ fprintf(fd, "set_priority(");
+ putstmnt(fd, now->lft->lft, m);
+ fprintf(fd, ", ");
+ putstmnt(fd, now->lft->rgt, m);
+ fprintf(fd, ")");
+ }
+ break;
+
case NONPROGRESS:
/* o_pm&4=progress, tau&128=claim stutter */
if (separate == 2)
@@ -2180,7 +2522,7 @@
case 's':
if (Pid == eventmapnr)
- { fprintf(fd, "if ((ot == EVENT_TRACE && _tp != 's') ");
+ { fprintf(fd, "if ((II == -EVENT_TRACE && _tp != 's') ");
putname(fd, "|| _qid+1 != ", now->lft, m, "");
for (v = now->rgt, i=0; v; v = v->rgt, i++)
{ if (v->lft->ntyp != CONST
@@ -2208,10 +2550,16 @@
break;
}
if (has_xu)
- { fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
- putname(fd, "if (q_claim[", now->lft, m, "]&2) ");
- putname(fd, "q_S_check(", now->lft, m, ", II);");
- fprintf(fd, "\n#endif\n\t\t");
+ { fprintf(fd, "\n#if !defined(XUSAFE) && !defined(NOREDUCE)\n\t\t");
+ putname(fd, "if (q_claim[", now->lft, m, "]&2)\n\t\t");
+ putname(fd, "{ q_S_check(", now->lft, m, ", II);\n\t\t");
+ fprintf(fd, "}\n");
+ if (has_sorted && now->val == 1)
+ { putname(fd, "\t\tif (q_claim[", now->lft, m, "]&1)\n\t\t"); /* &1 iso &2 */
+ fprintf(fd, "{ uerror(\"sorted send on xr channel violates po reduction\");\n\t\t");
+ fprintf(fd, "}\n");
+ }
+ fprintf(fd, "#endif\n\t\t");
}
fprintf(fd, "if (q_%s",
(u_sync > 0 && u_async == 0)?"len":"full");
@@ -2218,14 +2566,14 @@
putname(fd, "(", now->lft, m, "))\n");
if (m_loss)
- fprintf(fd, "\t\t{ nlost++; delta_m = 1; } else {");
- else
+ { fprintf(fd, "\t\t{ nlost++; delta_m = 1; } else {");
+ } else
{ fprintf(fd, "\t\t\t");
Bailout(fd, ";");
}
- if (has_enabled)
- fprintf(fd, "\n\t\tif (TstOnly) return 1;");
+ if (has_enabled || has_priority)
+ fprintf(fd, "\n\t\tif (TstOnly) return 1; /* T1 */");
if (u_sync && !u_async && rvopt)
fprintf(fd, "\n\n\t\tif (no_recvs(II)) continue;\n");
@@ -2232,7 +2580,7 @@
fprintf(fd, "\n#ifdef HAS_CODE\n");
fprintf(fd, "\t\tif (readtrail && gui) {\n");
- fprintf(fd, "\t\t\tchar simtmp[32];\n");
+ fprintf(fd, "\t\t\tchar simtmp[64];\n");
putname(fd, "\t\t\tsprintf(simvals, \"%%d!\", ", now->lft, m, ");\n");
_isok++;
for (v = now->rgt, i = 0; v; v = v->rgt, i++)
@@ -2256,9 +2604,9 @@
printf(" %d msg parameters sent, %d expected\n", i, Mpars);
fatal("too many pars in send", "");
}
- for ( ; i < Mpars; i++)
+ for (j = i; i < Mpars; i++)
fprintf(fd, ", 0");
- fprintf(fd, ")");
+ fprintf(fd, ", %d)", j);
if (u_sync)
{ fprintf(fd, ";\n\t\t");
if (u_async)
@@ -2274,7 +2622,7 @@
case 'r':
if (Pid == eventmapnr)
- { fprintf(fd, "if ((ot == EVENT_TRACE && _tp != 'r') ");
+ { fprintf(fd, "if ((II == -EVENT_TRACE && _tp != 'r') ");
putname(fd, "|| _qid+1 != ", now->lft, m, "");
for (v = now->rgt, i=0; v; v = v->rgt, i++)
{ if (v->lft->ntyp != CONST
@@ -2342,10 +2690,13 @@
break;
}
if (has_xu)
- { fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
- putname(fd, "if (q_claim[", now->lft, m, "]&1) ");
- putname(fd, "q_R_check(", now->lft, m, ", II);");
- fprintf(fd, "\n#endif\n\t\t");
+ { fprintf(fd, "\n#if !defined(XUSAFE) && !defined(NOREDUCE)\n\t\t");
+ putname(fd, "if (q_claim[", now->lft, m, "]&1)\n\t\t");
+ putname(fd, "{ q_R_check(", now->lft, m, ", II);\n\t\t");
+ if (has_random && now->val != 0)
+ fprintf(fd, " uerror(\"rand receive on xr channel violates po reduction\");\n\t\t");
+ fprintf(fd, "}\n");
+ fprintf(fd, "#endif\n\t\t");
}
if (u_sync)
{ if (now->val >= 2)
@@ -2398,6 +2749,8 @@
fprintf(fd, "0, %d, 0)) ", i);
Bailout(fd, "");
} }
+ if (has_enabled || has_priority)
+ fprintf(fd, ";\n\t\tif (TstOnly) return 1 /* T2 */");
} else /* random receive: val 1 or 3 */
{ fprintf(fd, ";\n\t\tif (!(XX = Q_has(");
putname(fd, "", now->lft, m, "");
@@ -2415,19 +2768,21 @@
fprintf(fd, ", 0, 0");
fprintf(fd, "))) ");
Bailout(fd, "");
- fprintf(fd, ";\n\t\t");
- if (multi_oval)
- { check_needed();
- fprintf(fd, "(trpt+1)->bup.ovals[%d] = ",
- multi_oval-1);
- multi_oval++;
- } else
- fprintf(fd, "(trpt+1)->bup.oval = ");
- fprintf(fd, "XX");
- }
- if (has_enabled)
- fprintf(fd, ";\n\t\tif (TstOnly) return 1");
+ if (has_enabled || has_priority)
+ fprintf(fd, ";\n\t\tif (TstOnly) return 1 /* T2 */");
+ if (!GenCode) {
+ fprintf(fd, ";\n\t\t");
+ if (multi_oval)
+ { check_needed();
+ fprintf(fd, "(trpt+1)->bup.ovals[%d] = ",
+ multi_oval-1);
+ multi_oval++;
+ } else
+ { fprintf(fd, "(trpt+1)->bup.oval = ");
+ }
+ fprintf(fd, "XX");
+ } }
if (j == 0 && now->val >= 2)
{ fprintf(fd, ";\n\t\t");
@@ -2439,16 +2794,20 @@
fprintf(fd, ";\n\t\t");
/* no variables modified */
if (j == 0 && now->val == 0)
- { fprintf(fd, "if (q_flds[((Q0 *)qptr(");
+ { fprintf(fd, "\n#ifndef BFS_PAR\n\t\t");
+ /* q_flds values are not shared among cores */
+ fprintf(fd, "if (q_flds[((Q0 *)qptr(");
putname(fd, "", now->lft, m, "-1))->_t]");
- fprintf(fd, " != %d)\n\t", i);
- fprintf(fd, "\t\tUerror(\"wrong nr of msg fields in rcv\");\n\t\t");
+ fprintf(fd, " != %d)\n\t\t\t", i);
+ fprintf(fd, "Uerror(\"wrong nr of msg fields in rcv\");\n");
+ fprintf(fd, "#endif\n\t\t");
}
for (v = now->rgt; v; v = v->rgt)
- if ((v->lft->ntyp != CONST
+ { if ((v->lft->ntyp != CONST
&& v->lft->ntyp != EVAL))
- jj++; /* nr of vars needing bup */
+ { jj++; /* nr of vars needing bup */
+ } }
if (jj)
for (v = now->rgt, i = 0; v; v = v->rgt, i++)
@@ -2467,12 +2826,12 @@
sprintf(tempbuf, "(trpt+1)->bup.oval = ");
if (v->lft->sym && !strcmp(v->lft->sym->name, "_"))
- { fprintf(fd, tempbuf);
+ { fprintf(fd, tempbuf, (char *) 0);
putname(fd, "qrecv(", now->lft, m, "");
fprintf(fd, ", XX-1, %d, 0);\n\t\t", i);
} else
{ _isok++;
- cat3(tempbuf, v->lft, ";\n\t\t");
+ cat30(tempbuf, v->lft, ";\n\t\t");
_isok--;
}
}
@@ -2485,7 +2844,7 @@
&& v->lft->ntyp != EVAL
&& v->lft->sym
&& v->lft->sym->type != STRUCT /* not a struct */
- && v->lft->sym->nel == 1 /* not an array */
+ && (v->lft->sym->nel == 1 && v->lft->sym->isarray == 0) /* not array */
&& strcmp(v->lft->sym->name, "_") != 0)
for (w = v->rgt; w; w = w->rgt)
if (v->lft->sym == w->lft->sym)
@@ -2501,6 +2860,7 @@
if (v->lft->ntyp != CONST
&& v->lft->ntyp != EVAL
+ && v->lft->sym != NULL
&& strcmp(v->lft->sym->name, "_") != 0)
{ nocast=1;
_isok++;
@@ -2515,6 +2875,7 @@
if (v->lft->ntyp != CONST
&& v->lft->ntyp != EVAL
+ && v->lft->sym != NULL
&& strcmp(v->lft->sym->name, "_") != 0
&& (v->lft->ntyp != NAME
|| v->lft->sym->type != CHAN))
@@ -2658,8 +3019,10 @@
break;
case ASGN:
- if (has_enabled)
- fprintf(fd, "if (TstOnly) return 1;\n\t\t");
+ if (check_track(now) == STRUCT) { break; }
+
+ if (has_enabled || has_priority)
+ fprintf(fd, "if (TstOnly) return 1; /* T3 */\n\t\t");
_isok++;
if (!GenCode)
@@ -2669,14 +3032,27 @@
sprintf(tempbuf, "(trpt+1)->bup.ovals[%d] = ",
multi_oval-1);
multi_oval++;
- cat3(tempbuf, now->lft, ";\n\t\t");
+ cat30(tempbuf, now->lft, ";\n\t\t");
} else
{ cat3("(trpt+1)->bup.oval = ", now->lft, ";\n\t\t");
} }
+ if (now->lft->sym
+ && now->lft->sym->type == PREDEF
+ && strcmp(now->lft->sym->name, "_") != 0
+ && strcmp(now->lft->sym->name, "_priority") != 0)
+ { fatal("invalid assignment to %s", now->lft->sym->name);
+ }
+
nocast = 1; putstmnt(fd,now->lft,m); nocast = 0;
fprintf(fd," = ");
_isok--;
- putstmnt(fd,now->rgt,m);
+ if (now->lft->sym->isarray
+ && now->rgt->ntyp == ',') /* array initializer */
+ { putstmnt(fd, now->rgt->lft, m);
+ non_fatal("cannot use an array list initializer here", (char *) 0);
+ } else
+ { putstmnt(fd, now->rgt, m);
+ }
if (now->sym->type != CHAN
|| verbose > 0)
@@ -2695,8 +3071,8 @@
break;
case PRINT:
- if (has_enabled)
- fprintf(fd, "if (TstOnly) return 1;\n\t\t");
+ if (has_enabled || has_priority)
+ fprintf(fd, "if (TstOnly) return 1; /* T4 */\n\t\t");
#ifdef PRINTF
fprintf(fd, "printf(%s", now->sym->name);
#else
@@ -2709,8 +3085,8 @@
break;
case PRINTM:
- if (has_enabled)
- fprintf(fd, "if (TstOnly) return 1;\n\t\t");
+ if (has_enabled || has_priority)
+ fprintf(fd, "if (TstOnly) return 1; /* T5 */\n\t\t");
fprintf(fd, "printm(");
if (now->lft && now->lft->ismtyp)
fprintf(fd, "%d", now->lft->val);
@@ -2732,7 +3108,7 @@
case 'q':
if (terse)
- fprintf(fd, "%s", now->sym->name);
+ fprintf(fd, "%s", now->sym?now->sym->name:"?");
else
fprintf(fd, "%d", remotelab(now));
break;
@@ -2748,14 +3124,16 @@
break;
case C_CODE:
- fprintf(fd, "/* %s */\n\t\t", now->sym->name);
- if (has_enabled)
- fprintf(fd, "if (TstOnly) return 1;\n\t\t");
- if (!GenCode) /* not in d_step */
- { fprintf(fd, "sv_save();\n\t\t");
- /* store the old values for reverse moves */
- }
- plunk_inline(fd, now->sym->name, 1);
+ if (now->sym)
+ fprintf(fd, "/* %s */\n\t\t", now->sym->name);
+ if (has_enabled || has_priority)
+ fprintf(fd, "if (TstOnly) return 1; /* T6 */\n\t\t");
+
+ if (now->sym)
+ plunk_inline(fd, now->sym->name, 1, GenCode);
+ else
+ fatal("internal error pangen2.c", (char *) 0);
+
if (!GenCode)
{ fprintf(fd, "\n"); /* state changed, capture it */
fprintf(fd, "#if defined(C_States) && (HAS_TRACK==1)\n");
@@ -2765,10 +3143,10 @@
break;
case ASSERT:
- if (has_enabled)
- fprintf(fd, "if (TstOnly) return 1;\n\t\t");
+ if (has_enabled || has_priority)
+ fprintf(fd, "if (TstOnly) return 1; /* T7 */\n\t\t");
- cat3("assert(", now->lft, ", ");
+ cat3("spin_assert(", now->lft, ", ");
terse = nocast = 1;
cat3("\"", now->lft, "\", II, tt, t)");
terse = nocast = 0;
@@ -2788,7 +3166,7 @@
break;
}
- if (has_enabled)
+ if (has_enabled || has_priority)
{ fprintf(fd, "if (TstOnly)\n\t\t\t");
fprintf(fd, "return (II+1 == now._nr_pr);\n\t\t");
}
@@ -2797,16 +3175,30 @@
break;
default:
- printf("spin: bad node type %d (.m) - line %d\n",
- now->ntyp, now->ln);
- fflush(tm);
+ printf("spin: error, %s:%d, bad node type %d (.m)\n",
+ now->fn->name, now->ln, now->ntyp);
+ fflush(fd);
alldone(1);
}
}
+char *
+simplify_name(char *s)
+{ char *t = s;
+
+ if (!old_scope_rules)
+ { while (*t == '_' || isdigit((int)*t))
+ { t++;
+ } }
+
+ return t;
+}
+
void
putname(FILE *fd, char *pre, Lextok *n, int m, char *suff) /* varref */
{ Symbol *s = n->sym;
+ char *ptr;
+
lineno = n->ln; Fname = n->fn;
if (!s)
@@ -2819,12 +3211,13 @@
{ fprintf(fd, "%s%s%s", pre, n->sym->name, suff);
return;
}
+
if (!s->type) /* not a local name */
s = lookup(s->name); /* must be a global */
if (!s->type)
{ if (strcmp(pre, ".") != 0)
- non_fatal("undeclared variable '%s'", s->name);
+ fatal("undeclared variable '%s'", s->name);
s->type = INT;
}
@@ -2831,36 +3224,54 @@
if (s->type == PROCTYPE)
fatal("proctype-name '%s' used as array-name", s->name);
- fprintf(fd, pre);
+ fprintf(fd, pre, 0);
if (!terse && !s->owner && evalindex != 1)
- { if (s->context
- || strcmp(s->name, "_p") == 0
- || strcmp(s->name, "_pid") == 0)
- { fprintf(fd, "((P%d *)this)->", Pid);
+ { if (old_priority_rules
+ && strcmp(s->name, "_priority") == 0)
+ { fprintf(fd, "1");
+ goto shortcut;
} else
- { int x = strcmp(s->name, "_");
- if (!(s->hidden&1) && x != 0)
- fprintf(fd, "now.");
- if (x == 0 && _isok == 0)
- fatal("attempt to read value of '_'", 0);
- } }
+ { if (s->context
+ || strcmp(s->name, "_p") == 0
+ || strcmp(s->name, "_pid") == 0
+ || strcmp(s->name, "_priority") == 0)
+ { fprintf(fd, "((P%d *)this)->", Pid);
+ } else
+ { int x = strcmp(s->name, "_");
+ if (!(s->hidden&1) && x != 0)
+ fprintf(fd, "now.");
+ if (x == 0 && _isok == 0)
+ fatal("attempt to read value of '_'", 0);
+ } } }
- if (withprocname
- && s->context
- && strcmp(pre, "."))
- fprintf(fd, "%s:", s->context->name);
+ if (terse && buzzed == 1)
+ { fprintf(fd, "B_state.%s", (s->context)?"local[B_pid].":"");
+ }
+ ptr = s->name;
+
+ if (!dont_simplify /* new 6.4.3 */
+ && s->type != PREDEF) /* new 6.0.2 */
+ { if (withprocname
+ && s->context
+ && strcmp(pre, "."))
+ { fprintf(fd, "%s:", s->context->name);
+ ptr = simplify_name(ptr);
+ } else
+ { if (terse)
+ { ptr = simplify_name(ptr);
+ } } }
+
if (evalindex != 1)
- fprintf(fd, "%s", s->name);
+ fprintf(fd, "%s", ptr);
- if (s->nel != 1)
+ if (s->nel > 1 || s->isarray == 1)
{ if (no_arrays)
- {
- non_fatal("ref to array element invalid in this context",
- (char *)0);
- printf("\thint: instead of, e.g., x[rs] qu[3], use\n");
- printf("\tchan nm_3 = qu[3]; x[rs] nm_3;\n");
- printf("\tand use nm_3 in sends/recvs instead of qu[3]\n");
+ { non_fatal("ref to array element invalid in this context",
+ (char *)0);
+ printf("\thint: instead of, e.g., x[rs] qu[3], use\n");
+ printf("\tchan nm_3 = qu[3]; x[rs] nm_3;\n");
+ printf("\tand use nm_3 in sends/recvs instead of qu[3]\n");
}
/* an xr or xs reference to an array element
* becomes an exclusion tag on the array itself -
@@ -2885,15 +3296,32 @@
|| (!n->lft && s->nel > 0))
{ cat3("[", n->lft, "]");
} else
- { cat3("[ Index(", n->lft, ", ");
+ { /* attempt to catch arrays that are indexed with an array element in the same array
+ * this causes trouble in the verifier in the backtracking
+ * e.g., restoring a[?] in the assignment: a [a[1]] = x where a[1] == 1
+ * but it is hard when the array is inside a structure, so the names dont match
+ */
+#if 0
+ if (n->lft->ntyp == NAME)
+ { printf("%4d: Basename %s index %s\n",
+ n->lft->ln, s->name, n->lft->sym->name);
+ }
+#endif
+ cat3("[ Index(", n->lft, ", ");
fprintf(fd, "%d) ]", s->nel);
- }
- }
- }
+ } }
+ } else
+ { if (n->lft /* effectively a scalar, but with an index */
+ && (n->lft->ntyp != CONST
+ || n->lft->val != 0))
+ { fatal("ref to scalar '%s' using array index", (char *) ptr);
+ } }
+
if (s->type == STRUCT && n->rgt && n->rgt->lft)
{ putname(fd, ".", n->rgt->lft, m, "");
}
- fprintf(fd, suff);
+shortcut:
+ fprintf(fd, suff, 0);
}
void
@@ -2908,7 +3336,11 @@
putstmnt(fd, n->lft->lft, m); /* pid */
fprintf(fd, "]");
}
- fprintf(fd, ".%s", n->sym->name);
+ if (ltl_mode)
+ { fprintf(fd, ":%s", n->sym->name);
+ } else
+ { fprintf(fd, ".%s", n->sym->name);
+ }
} else
{ if (Sym_typ(n) < SHORT)
{ promoted = 1;
--- a/sys/src/cmd/spin/pangen2.h
+++ b/sys/src/cmd/spin/pangen2.h
@@ -1,32 +1,15 @@
/***** spin: pangen2.h *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
-static char *Nvr1[] = { /* allow separate compilation */
- "#ifdef VERI",
- "void",
- "check_claim(int st)",
- "{",
- " if (st == endclaim)",
- " uerror(\"claim violated!\");",
- " if (stopstate[VERI][st])",
- " uerror(\"end state in claim reached\");",
- "}",
+static const char *Pre0[] = {
+ "#ifdef SC",
+ " #define _FILE_OFFSET_BITS 64", /* allows file sizes greater than 2Gb */
"#endif",
- 0,
-};
-
-static char *Pre0[] = {
-"#ifdef SC",
- "#define _FILE_OFFSET_BITS 64", /* to allow file sizes greater than 2Gb */
-"#endif",
"#include <stdio.h>",
"#include <signal.h>",
"#include <stdlib.h>",
@@ -38,12 +21,14 @@
"#include <time.h>",
"#else",
"#include <unistd.h>",
- "#include <sys/times.h>", /* new 4.3.0 */
+ "#include <sys/times.h>",
"#endif",
"#include <sys/types.h>", /* defines off_t */
"#include <sys/stat.h>",
+ "#include <limits.h>",
"#include <fcntl.h>",
- "#define Offsetof(X, Y) ((unsigned long)(&(((X *)0)->Y)))",
+
+ "#define Offsetof(X, Y) ((ulong)(&(((X *)0)->Y)))",
"#ifndef max",
"#define max(a,b) (((a)<(b)) ? (b) : (a))",
"#endif",
@@ -53,12 +38,62 @@
0,
};
-static char *Preamble[] = {
+static const char *Separate[] = {
+ "#ifdef COLLAPSE",
+ " #if (NCORE>1 && !defined(SEP_STATE)) || defined(BFS_PAR)",
+ " volatile ulong *ncomps; /* in shared memory */",
+ " #else",
+ " ulong ncomps[256+2];",
+ " #endif",
+ "#endif",
+ "Trans ***trans; /* 1 ptr per state per proctype */\n",
+ "",
+ "#if VECTORSZ>32000",
+ " int P_o[MAXPROC], P_o_tmp[MAXPROC+1];",
+ " int Q_o[MAXQ], Q_o_tmp[MAXPROC+1];",
+ "",
+ " int *proc_offset = (int *) P_o;",
+ " int *q_offset = (int *) Q_o;",
+ "#else",
+ " short P_o[MAXPROC], P_o_tmp[MAXPROC+1];",
+ " short Q_o[MAXQ], Q_o_tmp[MAXPROC+1];",
+ "",
+ " short *proc_offset = (short *) P_o;",
+ " short *q_offset = (short *) Q_o;",
+ "#endif",
+ "uchar P_s[MAXPROC+1], P_s_tmp[MAXPROC+1];",
+ "uchar Q_s[MAXQ+1], Q_s_tmp[MAXQ+1];",
+ "uchar *proc_skip = (uchar *) P_s;",
+ "uchar *q_skip = (uchar *) Q_s;",
+ "",
+ "#ifdef TRIX",
+ " TRIX_v6 *freebodies;",
+ " TRIX_v6 *processes[MAXPROC+1];",
+ " TRIX_v6 *channels[MAXQ+1];",
+ " long _p_count[MAXPROC];",
+ " long _c_count[MAXPROC];",
+ "#endif\n",
+ "ulong vsize; /* vector size in bytes */",
+ "#ifdef SVDUMP",
+ " int vprefix=0, svfd; /* runtime option -pN */",
+ "#endif",
+ "char *tprefix = \"trail\"; /* runtime option -tsuffix */",
+ "short boq = -1; /* blocked_on_queue status */",
+ "int _; /* predefined write-only variable */",
+ "#ifdef PEG",
+ " long peg[NTRANS];",
+ "#endif",
+ 0,
+};
+static const char *Preamble[] = {
+ "#ifdef RANDOMIZE",
+ " #define T_RAND RANDOMIZE",
+ "#endif",
"#ifdef CNTRSTACK",
- "#define onstack_now() (LL[trpt->j6] && LL[trpt->j7])",
- "#define onstack_put() LL[trpt->j6]++; LL[trpt->j7]++",
- "#define onstack_zap() LL[trpt->j6]--; LL[trpt->j7]--",
+ " #define onstack_now() (LL[trpt->j6] && LL[trpt->j7])",
+ " #define onstack_put() LL[trpt->j6]++; LL[trpt->j7]++",
+ " #define onstack_zap() LL[trpt->j6]--; LL[trpt->j7]--",
"#endif",
"#if !defined(SAFETY) && !defined(NOCOMP)",
@@ -68,13 +103,13 @@
* S_A remembers how many leading bytes in the sv
* are used for these markers + fairness bits
*/
- "#define V_A (((now._a_t&1)?2:1) << (now._a_t&2))",
- "#define A_V (((now._a_t&1)?1:2) << (now._a_t&2))",
- "int S_A = 0;",
+ " #define V_A (((now._a_t&1)?2:1) << (now._a_t&2))",
+ " #define A_V (((now._a_t&1)?1:2) << (now._a_t&2))",
+ " int S_A = 0;",
"#else",
- "#define V_A 0",
- "#define A_V 0",
- "#define S_A 0",
+ " #define V_A 0",
+ " #define A_V 0",
+ " #define S_A 0",
"#endif",
"#ifdef MA",
@@ -82,7 +117,7 @@
"#undef onstack_put",
"#undef onstack_zap",
"#define onstack_put() ;",
- "#define onstack_zap() gstore((char *) &now, vsize, 4)",
+ "#define onstack_zap() g_store((char *) &now, vsize, 4)",
"#else",
"#if defined(FULLSTACK) && !defined(BITSTATE)",
"#define onstack_put() trpt->ostate = Lstate",
@@ -93,165 +128,284 @@
" }",
"#endif",
"#endif",
- "struct H_el {",
- " struct H_el *nxt;",
- "#ifdef FULLSTACK",
- " unsigned int tagged;",
- "#if defined(BITSTATE) && !defined(NOREDUCE) && !defined(SAFETY)",
- " unsigned int proviso;", /* uses just 1 bit 0/1 */
- "#endif",
- "#endif",
- "#if defined(CHECK) || (defined(COLLAPSE) && !defined(FULLSTACK))",
- " unsigned long st_id;",
- "#endif",
- "#ifdef COLLAPSE",
- "#if VECTORSZ<65536",
- " unsigned short ln;", /* length of vector */
- "#else",
- " unsigned long ln;", /* length of vector */
- "#endif",
- "#endif",
- "#if !defined(SAFETY) || defined(REACH)",
- " unsigned int D;",
- "#endif",
- " unsigned state;",
- "} **H_tab, **S_Tab;\n",
-
- "typedef struct Trail {",
- " int st; /* current state */",
- " uchar pr; /* process id */",
- " uchar tau; /* 8 bit-flags */",
- " uchar o_pm; /* 8 more bit-flags */",
- "#if 0",
- " Meaning of bit-flags:",
- " tau&1 -> timeout enabled",
- " tau&2 -> request to enable timeout 1 level up (in claim)",
- " tau&4 -> current transition is a claim move",
- " tau&8 -> current transition is an atomic move",
- " tau&16 -> last move was truncated on stack",
- " tau&32 -> current transition is a preselected move",
- " tau&64 -> at least one next state is not on the stack",
- " tau&128 -> current transition is a stutter move",
-
- " o_pm&1 -> the current pid moved -- implements else",
- " o_pm&2 -> this is an acceptance state",
- " o_pm&4 -> this is a progress state",
- " o_pm&8 -> fairness alg rule 1 undo mark",
- " o_pm&16 -> fairness alg rule 3 undo mark",
- " o_pm&32 -> fairness alg rule 2 undo mark",
- " o_pm&64 -> the current proc applied rule2",
- " o_pm&128 -> a fairness, dummy move - all procs blocked",
- "#endif",
- "#if defined(FULLSTACK) && defined(MA) && !defined(BFS)",
- " uchar proviso;",
- "#endif",
- "#ifndef BFS",
- " uchar o_n, o_ot; /* to save locals */",
- "#endif",
- " uchar o_m;",
- "#ifdef EVENT_TRACE",
- "#if nstates_event<256",
- " uchar o_event;",
- "#else",
- " unsigned short o_event;",
- "#endif",
- "#endif",
- " int o_tt;",
- "#ifndef BFS",
- " short o_To;",
- "#ifdef RANDOMIZE",
- " short oo_i;",
- "#endif",
- "#endif",
- "#if defined(HAS_UNLESS) && !defined(BFS)",
- " int e_state; /* if escape trans - state of origin */",
- "#endif",
- "#if (defined(FULLSTACK) && !defined(MA)) || defined(BFS)",
- " struct H_el *ostate; /* pointer to stored state */",
- "#endif",
- /* CNTRSTACK when !NOREDUCE && BITSTATE && SAFETY, uses LL[] */
- "#if defined(CNTRSTACK) && !defined(BFS)",
- " long j6, j7;",
- "#endif",
- " Trans *o_t;", /* transition fct, next state */
- "#ifdef HAS_SORTED",
- " short ipt;", /* insertion slot in q */
- "#endif",
- " union {",
- " int oval;", /* single backup value of variable */
- " int *ovals;", /* ptr to multiple values */
- " } bup;",
- "} Trail;",
+ "H_el **H_tab, **S_Tab;",
+ "/* #ifndef BFS_PAR */",
+ " H_el *Lstate;",
+ "/* #endif */",
"Trail *trail, *trpt;",
-
"FILE *efd;",
"uchar *this;",
"long maxdepth=10000;",
"long omaxdepth=10000;",
+ "#ifdef BCS",
+ " /* bitflags in trpt->bcs */",
+ " #define B_PHASE1 1",
+ " #define B_PHASE2 2",
+ " #define B_FORCED 4",
+ "int sched_max = 0;",
+ "#endif",
+ "",
+ "double quota; /* time limit */",
+ "#if NCORE>1",
+ " long z_handoff = -1;",
+ "#endif",
"#ifdef SC", /* stack cycling */
- "char *stackfile;",
+ " char *stackfile;",
"#endif",
"uchar *SS, *LL;",
+ "",
+ "uchar reversing = 0;",
"uchar HASH_NR = 0;",
"",
"double memcnt = (double) 0;",
- "double memlim = (double) (1<<30);",
+ "double memlim = (double) (1<<30); /* 1 GB */",
+ "#if NCORE>1",
+ "double mem_reserved = (double) 0;",
+ "#endif",
"",
"/* for emalloc: */",
"static char *have;",
"static long left = 0L;",
"static double fragment = (double) 0;",
- "static unsigned long grow;",
+ "static ulong grow;",
"",
+#if 1
"unsigned int HASH_CONST[] = {",
+ " /* generated by hashgen 421 -- assumes 4 bytes per int */",
+ " 0x100d4e63, 0x0fc22f87, 0xa7155c77, 0x78f2c3b9,",
+ " 0xde32d207, 0xc27d305b, 0x1bb3fb2b, 0x2798c7a5,",
+ " 0x9c675ffd, 0x777d9081, 0x07aef2f1, 0xae08922f,",
+ " 0x5bd365b7, 0xed51c47b, 0x9b5aeea1, 0xbcc9d431,",
+ " 0x396d8fff, 0xa2fd1367, 0x08616521, 0x5e84991f,",
+ " 0x87495bc5, 0x2930039b, 0xceb6a593, 0xfe522d63,",
+ " 0x7ff60baf, 0xf89b1fbf, 0x74c01755, 0xe0c559bf,",
+ " 0x3669fc47, 0x8756d3bf, 0x14f78445, 0x24c41779,",
+ " 0x0af7b129, 0xde22368d, 0x3e1c01e3, 0xaf773e49,",
+ " 0x5b762459, 0x86d12911, 0x0953a3af, 0xb66dc23d,",
+ " 0x96b3bd4f, 0x19b1dd51, 0xd886fbc3, 0xa7f3a025,",
+ " 0xccb48e63, 0x87d8f027, 0x2bea270d, 0xdb0e9379,",
+ " 0x78c09f21, 0x0cbbfe07, 0xea4bc7c3, 0x5bfbc3c9,",
+ " 0x3c6e53fd, 0xab320cdd, 0x31041409, 0x416e7485,",
+ " 0xe41d75fd, 0xc3c5060f, 0x201a9dc1, 0x93dee72b,",
+ " 0x6461305f, 0xc571dec5, 0xa1fd21c5, 0xfb421ce1,",
+ " 0x7f024b05, 0xfa518819, 0x6c9777fb, 0x0d4d9351,",
+ " 0x08b33861, 0xccb9d0f3, 0x34112791, 0xe962d7c9,",
+ " 0x8d742211, 0xcd9c47a1, 0x64437b69, 0x5fe40feb,",
+ " 0x806113cb, 0x10e1d593, 0x821851b3, 0x057a1ff3,",
+ " 0x8ededc0b, 0x90dd5b31, 0x635ff359, 0x68dbcd35,",
+ " 0x1050ff4f, 0xdbb07257, 0x486336db, 0x83af1e75,",
+ " 0x432f1799, 0xc1d0e7e7, 0x21f4eb5b, 0x881ec2c1,",
+ " 0x23f3b539, 0x6cdfb80d, 0x71d474cf, 0x97d5d4a9,",
+ " 0xf721d2e5, 0xb5ff3711, 0x3f2e58cd, 0x4e06e3d9,",
+ " 0x7d711739, 0x927887df, 0x7d57ad71, 0x232eb767,",
+ " 0xe3f5cc51, 0x6576b443, 0xed17bf1f, 0x8828b637,",
+ " 0xc940f6ab, 0xc7b830ef, 0x11ed8a13, 0xaff20949,",
+ " 0xf28a8465, 0x0da10cf9, 0xb512497d, 0x44accae1,",
+ " 0x95e0929f, 0xe08c8901, 0xfd22d6c9, 0xb6a5c029,",
+ " 0xaadb428d, 0x6e8a453d, 0x3d5c0195, 0x8bf4ae39,",
+ " 0xbf83ab19, 0x3e9dac33, 0xc4df075d, 0x39472d71,",
+ " 0xb8647725, 0x1a6d4887, 0x78a03577, 0xafd76ef7,",
+ " 0xc1a1d6b3, 0x1afb33c5, 0x87896299, 0x5cc992ef,",
+ " 0x7f805d0d, 0x089a039b, 0xa353cc27, 0x57b296b3,",
+ " 0x52badec9, 0xc916e431, 0x09171957, 0x14996d51,",
+ " 0xe87e32c7, 0xb4fdbb5d, 0xdd216a03, 0x4ddd3fff,",
+ " 0x767d5c57, 0x79c97509, 0xab70543b, 0xc5feca4f,",
+ " 0x8eb37b89, 0x20a2cefd, 0xf4b00b91, 0xf166593d,",
+ " 0x7bf50f65, 0x753e6c8b, 0xfb5b81dd, 0xf2d45ef5,",
+ " 0x9741c04f, 0x300da48d, 0x01dc4121, 0xa112cd47,",
+ " 0x0223b24b, 0xa89fbce7, 0x681e1f7b, 0xe7c6aedf,",
+ " 0x1fd3d523, 0x561ba723, 0xf54042fb, 0x1a516751,",
+ " 0xcd085bd5, 0xe74246d5, 0x8b170b5d, 0x249985e9,",
+ " 0x5b4d9cf7, 0xe9912323, 0x5fc0f339, 0x41f8f051,",
+ " 0x8a296fb1, 0x62909f51, 0x2c05d695, 0x095efccb,",
+ " 0xa91574f1, 0x0f5cc6c3, 0x23a2ca2b, 0xc6053ec1,",
+ " 0xeb19e081, 0x3d1b3997, 0xb0c5f3cd, 0xe5d85b35,",
+ " 0x1cb1bdf1, 0x0c8f278f, 0x518249c3, 0x9f61b68d,",
+ " 0xade0919d, 0x779e29c3, 0xdbac9485, 0x2ce149a9,",
+ " 0x254c2409, 0x205b34fb, 0xc8ab1a89, 0x6b4a2585,",
+ " 0x2303d94b, 0x8fa186b9, 0x49826da5, 0xd23a37ad,",
+ " 0x680b18c9, 0xa46fbd7f, 0xe42c2cf9, 0xf7cfcb5f,",
+ " 0xb4842b8b, 0xe483780d, 0x66cf756b, 0x3eb73781,",
+ " 0x41ca17a5, 0x59f91b0f, 0x92fb67d9, 0x0a5c330f,",
+ " 0x46013fdb, 0x3b0634af, 0x9024f533, 0x96a001a7,",
+ " 0x15bcd793, 0x3a311fb1, 0x78913b8b, 0x9d4a5ddf,",
+ " 0x33189b31, 0xa99e8283, 0xf7cb29e9, 0x12d64a27,",
+ " 0xeda770ff, 0xa7320297, 0xbd3c14a5, 0x96d0156f,",
+ " 0x0115db95, 0x7f79f52b, 0xa6d52521, 0xa063d4bd,",
+ " 0x9cb5e039, 0x42cf8195, 0xcb716835, 0x1bc21273,",
+ " 0x5a67ad27, 0x4b3b0545, 0x162cda67, 0x0489166b,",
+ " 0x85fd06a9, 0x562b037d, 0x995bc1f3, 0xe144e78b,",
+ " 0x1e749f69, 0xa36df057, 0xcfee1667, 0x8c4116b7,",
+ " 0x94647fe3, 0xe6899df7, 0x6d218981, 0xf1069079,",
+ " 0xd1851a33, 0xf424fc83, 0x24467005, 0xad8caf59,",
+ " 0x1ae5da13, 0x497612f9, 0x10f6d1ef, 0xeaf4ff05,",
+ " 0x405f030b, 0x693b041d, 0x2065a645, 0x9fec71b3,",
+ " 0xc3bd1b0f, 0xf29217a3, 0x0f25e15d, 0xd48c2b97,",
+ " 0xce8acf2d, 0x0629489b, 0x1a5b0e01, 0x32d0c059,",
+ " 0x2d3664bf, 0xc45f3833, 0xd57f551b, 0xbdd991c5,",
+ " 0x9f97da9f, 0xa029c2a9, 0x5dd0cbdf, 0xe237ba41,",
+ " 0x62bb0b59, 0x93e7d037, 0x7e495619, 0x51b8282f,",
+ " 0x853e8ef3, 0x9b8abbeb, 0x055f66f9, 0x2736f7e5,",
+ " 0x8d7e6353, 0x143abb65, 0x4e2bb5b3, 0x872e1adf,",
+ " 0x8fcac853, 0xb7cf6e57, 0x12177f3d, 0x1d2da641,",
+ " 0x07856425, 0xc0ed53dd, 0x252271d9, 0x79874843,",
+ " 0x0aa8c9b5, 0x7e804f93, 0x2d080e09, 0x3929ddfd,",
+ " 0x36433dbd, 0xd6568c17, 0xe624e939, 0xb33189ef,",
+ " 0x29e68bff, 0x8aae2433, 0xe6335499, 0xc5facd9d,",
+ " 0xbd5afc65, 0x7a584fa7, 0xab191435, 0x64bbdeef,",
+ " 0x9f5cd8e1, 0xb3a1be05, 0xbd0c1753, 0xb00e2c7f,",
+ " 0x6a96e315, 0x96a31589, 0x660af5af, 0xc0438d43,",
+ " 0x17637373, 0x6460e8df, 0x7d458de9, 0xd76b923f,",
+ " 0x316f045f, 0x3ccbd035, 0x63f64d81, 0xd990d969,",
+ " 0x7c860a93, 0x99269ff7, 0x6fbcac8f, 0xd8cc562b,",
+ " 0x67141071, 0x09f85ea3, 0x1298f2dd, 0x41fa86e5,",
+ " 0xce1d7cf5, 0x6b232c9d, 0x8f093d4b, 0x3203ad4b,",
+ " 0x07d70d5f, 0x38c44c75, 0x0887c9ef, 0x1833acf5,",
+ " 0xa3607f85, 0x7d367573, 0x0ea4ffc3, 0xad2d09c1,",
+ " 0x7a1e664f, 0xef41dff5, 0x03563491, 0x67f30a1f,",
+ " 0x5ce5f9ef, 0xa2487a27, 0xe5077957, 0x9beb36fd,",
+ " 0x16e41251, 0x216799ef, 0x07181f8d, 0xc191c3cf,",
+ " 0xba21cab5, 0x73944eb7, 0xdf9eb69d, 0x5fef6cfd,",
+ " 0xd750a6f5, 0x04f3fa43, 0x7cb2d063, 0xd3bdb369,",
+ " 0x35f35981, 0x9f294633, 0x5e293517, 0x70e51d05,",
+ " 0xf8db618d, 0x66ee05db, 0x835eaa77, 0x166a02c3,",
+ " 0xb516f283, 0x94102293, 0x1ace50a5, 0x64072651,",
+ " 0x66df7b75, 0x02e1b261, 0x8e6a73b9, 0x19dddfe7,",
+ " 0xd551cf39, 0x391c17cb, 0xf4304de5, 0xcd67b8d1,",
+ " 0x25873e8d, 0x115b4c71, 0x36e062f3, 0xaec0c7c9,",
+ " 0xd929f79d, 0x935a661b, 0xda762b47, 0x170bd76b,",
+ " 0x1a955cb5, 0x341fb0ef, 0x7f366cef, 0xc98f60c7,",
+ " 0xa4181af3, 0xa94a8837, 0x5fa3bc43, 0x11c638c1,",
+ " 0x4e66fabb, 0x30ab85cf, 0x250704ef, 0x8bf3bc07,",
+ " 0x6d2cd5ab, 0x613ef9c3, 0xb8e62149, 0x0404fd91,",
+ " 0xa04fd9b1, 0xa5e389eb, 0x9543bd23, 0xad6ca1f9,",
+ " 0x210c49ab, 0xf8e9532b, 0x854fba89, 0xdc7fc6bb,",
+ " 0x48a051a7, 0x6b2f383b, 0x61a4b433, 0xd3af231b,",
+ " 0xc5023fc7, 0xa5aa85df, 0xa0cd1157, 0x4206f64d,",
+ " 0x3fea31c3, 0x62d510a1, 0x13988957, 0x6a11a033,",
+ " 0x46f2a3b7, 0x2784ef85, 0x229eb9eb, 0x9c0c3053,",
+ " 0x5b7ead39, 0x82ae9afb, 0xf99e9fb3, 0x914b6459,",
+ " 0xaf05edd7, 0xc82710dd, 0x8fc1ea1f, 0x7e0d7a8d,",
+ " 0x7c7592e9, 0x65321017, 0xea57553f, 0x4aeb49ff,",
+ " 0x5239ae4d, 0x4b4b4585, 0x94091c21, 0x7eaaf4cb,",
+ " 0x6b489d6f, 0xecb9c0c3, 0x29a7af63, 0xaf117a0d,",
+ " 0x969ea6cd, 0x7658a34d, 0x5fc0bba9, 0x26e99b7f,",
+ " 0x7a6f260f, 0xe37c34f1, 0x1a1569bb, 0xc3bc7371,",
+ " 0x8567543d, 0xad0c46a9, 0xa1264fd9, 0x16f10b29,",
+ " 0x5e00dd3b, 0xf85b6bcd, 0xa2d32d8b, 0x4a3c8d43,",
+ " 0x6b33b959, 0x4fd1e6c9, 0x7938b8a9, 0x1ec795c7,",
+ " 0xe2ef3409, 0x83c16b9d, 0x0d3fd9eb, 0xeb461ad7,",
+ " 0xb09c831d, 0xaf052001, 0x7911164d, 0x1a9dc191,",
+ " 0xb52a0815, 0x0f732157, 0xc68c4831, 0x12cf3cbb };",
+#else
+ "unsigned int HASH_CONST[] = {",
" /* asuming 4 bytes per int */",
- " 0x88888EEF, 0x00400007,",
- " 0x04c11db7, 0x100d4e63,",
- " 0x0fc22f87, 0x3ff0c3ff,",
- " 0x38e84cd7, 0x02b148e9,",
- " 0x98b2e49d, 0xb616d379,",
- " 0xa5247fd9, 0xbae92a15,",
- " 0xb91c8bc5, 0x8e5880f3,",
- " 0xacd7c069, 0xb4c44bb3,",
- " 0x2ead1fb7, 0x8e428171,",
- " 0xdbebd459, 0x828ae611,",
- " 0x6cb25933, 0x86cdd651,",
- " 0x9e8f5f21, 0xd5f8d8e7,",
- " 0x9c4e956f, 0xb5cf2c71,",
- " 0x2e805a6d, 0x33fc3a55,",
- " 0xaf203ed1, 0xe31f5909,",
- " 0x5276db35, 0x0c565ef7,",
- " 0x273d1aa5, 0x8923b1dd,",
- " 0",
- "};",
- "int mreached=0, done=0, errors=0, Nrun=1;",
+ " 0x100d4e63, 0x0fc22f87,",
+ " 0x3ff0c3ff, 0x38e84cd7,",
+ " 0x02b148e9, 0x98b2e49d,",
+ " 0xb616d379, 0xa5247fd9,",
+ " 0xbae92a15, 0xb91c8bc5,",
+ " 0x8e5880f3, 0xacd7c069,",
+ " 0xb4c44bb3, 0x2ead1fb7,",
+ " 0x8e428171, 0xdbebd459,",
+ " 0x00400007, 0x04c11db7,",
+ " 0x828ae611, 0x6cb25933,",
+ " 0x86cdd651, 0x9e8f5f21,",
+ " 0xd5f8d8e7, 0x9c4e956f,",
+ " 0xb5cf2c71, 0x2e805a6d,",
+ " 0x33fc3a55, 0xaf203ed1,",
+ " 0xe31f5909, 0x5276db35,",
+ " 0x0c565ef7, 0x273d1aa5,",
+ " 0x8923b1dd, 0xa9acaac5,",
+ " 0xd1f69207, 0xedfd944b,",
+ " 0x9a68e46b, 0x5355e13f,",
+ " 0x7eeb44f9, 0x932beea9,",
+ " 0x330c4cd3, 0x87f34e5f,",
+ " 0x1b5851b7, 0xb9ca6447,",
+ " 0x58f96a8f, 0x1b3b5307,",
+ " 0x31c387b3, 0xf35f0f35,",
+ " 0xa0acc4df, 0xf3140303,",
+ " 0x2446245d, 0xe4b8f4ef,",
+ " 0x5c007383, 0x68e648af,",
+ " 0x1814fba7, 0xcdf731b5,",
+ " 0xd09ccb4b, 0xb92d0eff,",
+ " 0xcc3c6b67, 0xd3af6a57,",
+ " 0xf44fc3f5, 0x5bb67623,",
+ " 0xaeb9c953, 0x5e0ac739,",
+ " 0x3a7fda09, 0x5edf39eb,",
+ " 0x661eefd9, 0x6423f0d1,",
+ " 0x910fe413, 0x9ec92297,",
+ " 0x4bd8159d, 0xa7b16ee1,",
+ " 0x89d484e9, 0x7f305cb3,",
+ " 0xc5f303e7, 0x415deeef,",
+ " 0x09986f89, 0x7e9c4117,",
+ " 0x0b7cbedb, 0xf9ed7561,",
+ " 0x7a20ac99, 0xf05adef3,",
+ " 0x5893d75b, 0x44d73327,",
+ " 0xb583c873, 0x324d2145,",
+ " 0x7fa3829b, 0xe4b47a23,",
+ " 0xe256d94f, 0xb1fd8959,",
+ " 0xe561a321, 0x1435ac09,",
+ " 0xdd62408b, 0x02ec0bcb,",
+ " 0x5469b785, 0x2f4f50bb,",
+ " 0x20f19395, 0xf96ba085,",
+ " 0x2381f937, 0x768e2a11 };",
+#endif
+ "",
+ "#if NCORE>1",
+ "extern int core_id;",
+ "#endif",
+ "long mreached=0;",
+ "int done=0, errors=0, Nrun=1;",
+ "int c_init_done=0;",
+ "char *c_stack_start = (char *) 0;",
"double nstates=0, nlinks=0, truncs=0, truncs2=0;",
"double nlost=0, nShadow=0, hcmp=0, ngrabs=0;",
+ "#ifdef BFS_PAR",
+ "extern ulong bfs_punt;",
+ "#endif",
+ "#ifdef PUTPID",
+ "char *progname;",
+ "#endif",
+ "#if defined(ZAPH) && defined(BITSTATE)",
+ "double zstates = 0;",
+ "#endif",
+ "/* int c_init_run; */",
+ "#ifdef REVERSE",
+ " #define P_REVERSE",
+ "#endif",
+ "#ifdef T_REVERSE",
+ " int t_reverse = 1;", /* can be modified with a parameter */
+ "#else",
+ " int t_reverse = 0;",
+ "#endif",
"#ifdef BFS",
"double midrv=0, failedrv=0, revrv=0;",
"#endif",
- "unsigned long nr_states=0; /* nodes in DFA */",
+ "ulong nr_states=0; /* nodes in DFA */",
"long Fa=0, Fh=0, Zh=0, Zn=0;",
"long PUT=0, PROBE=0, ZAPS=0;",
"long Ccheck=0, Cholds=0;",
"int a_cycles=0, upto=1, strict=0, verbose = 0, signoff = 0;",
"#ifdef HAS_CODE",
- "int gui = 0, coltrace = 0, readtrail = 0, whichtrail = 0, onlyproc = -1, silent = 0;",
+ "int gui = 0, coltrace = 0, readtrail = 0;",
+ "int whichtrail = 0, whichclaim = -1, onlyproc = -1, silent = 0;",
+ "char *claimname;",
"#endif",
- "int state_tables=0, fairness=0, no_rck=0, Nr_Trails=0;",
- "char simvals[128];",
+ "int state_tables=0, fairness=0, no_rck=0, Nr_Trails=0, dodot=0;",
+ "char simvals[256];",
"#ifndef INLINE",
"int TstOnly=0;",
"#endif",
- "unsigned long mask, nmask;",
+ "ulong mask, nmask;",
"#ifdef BITSTATE",
- "int ssize=23; /* 1 Mb */",
+ "int ssize=27; /* 16 Mb */",
"#else",
- "int ssize=19; /* 512K slots */",
+ "int ssize=24; /* 16M slots */",
"#endif",
"int hmax=0, svmax=0, smax=0;",
"int Maxbody=0, XX;",
- "uchar *noptr; /* used by macro Pptr(x) */",
+ "uchar *noptr, *noqptr; /* used by Pptr(x) and Qptr(x) */",
"#ifdef VAR_RANGES",
"void logval(char *, int);",
"void dumpranges(void);",
@@ -260,36 +414,55 @@
"#ifdef MA",
"#define INLINE_REV",
"extern void dfa_init(unsigned short);",
- "extern int dfa_member(unsigned long);",
+ "extern int dfa_member(ulong);",
"extern int dfa_store(uchar *);",
"unsigned int maxgs = 0;",
"#endif",
-
- "State comp_now; /* compressed state vector */",
- "State comp_msk;",
- "uchar *Mask = (uchar *) &comp_msk;",
+ "",
+ "#ifdef ALIGNED",
+ " State comp_now __attribute__ ((aligned (8)));",
+ " /* gcc 64-bit aligned for Itanium2 systems */",
+ " /* MAJOR runtime penalty if not used on those systems */",
+ "#else",
+ " State comp_now; /* compressed state vector */",
+ "#endif",
+ "",
+ "#ifndef HC",
+ " #ifdef BFS_PAR",
+ " State tmp_msk;",
+ " #endif",
+ " State comp_msk;",
+ " uchar *Mask = (uchar *) &comp_msk;",
+ "#endif",
"#ifdef COLLAPSE",
- "State comp_tmp;",
- "static char *scratch = (char *) &comp_tmp;",
+ " State comp_tmp;",
+ " static char *scratch = (char *) &comp_tmp;",
"#endif",
-
- "Stack *stack; /* for queues, processes */",
+ "",
+ "_Stack *stack; /* for queues, processes */",
"Svtack *svtack; /* for old state vectors */",
"#ifdef BITSTATE",
- "static unsigned hfns = 3; /* new default */",
+ "static unsigned int hfns = 3; /* new default */",
"#endif",
- "static unsigned long j1;",
- "static unsigned long K1, K2;",
- "static unsigned long j2, j3, j4;",
+ "static ulong j1_spin, j2_spin; /* 5.2.1: avoid nameclash with math.h */",
+ "static ulong j3_spin, j4_spin;",
+ "ulong K1, K2;",
"#ifdef BITSTATE",
-#ifndef POWOW
- "static long udmem;",
-#endif
+ "long udmem;",
"#endif",
+ "#ifndef BFS_PAR",
"static long A_depth = 0;",
- "long depth = 0;", /* not static to support -S2 option, but possible clash with embedded code */
- "static uchar warned = 0, iterative = 0, like_java = 0, every_error = 0;",
- "static uchar noasserts = 0, noends = 0, bounded = 0;",
+ "#endif",
+ "long depth = 0;",
+ "long depthfound = -1; /* loop detection */",
+ /* depth: not static to support -S2, but possible clash with embedded code */
+ "#if NCORE>1",
+ "long nr_handoffs = 0;",
+ "#endif",
+ "uchar warned = 0, iterative = 0, exclusive = 0, like_java = 0, every_error = 0;",
+ "uchar noasserts = 0, noends = 0, bounded = 0;",
+ "uint s_rand = 12345; /* default seed */",
+
"#if SYNC>0 && ASYNC==0",
"void set_recvs(void);",
"int no_recvs(int);",
@@ -302,17 +475,32 @@
"#define UnBlock /* don't bother */",
"#endif\n",
"#ifdef BITSTATE",
- "int (*bstore)(char *, int);",
+ "int (*b_store)(char *, int);",
"int bstore_reg(char *, int);",
-#ifndef POWOW
"int bstore_mod(char *, int);",
-#endif
"#endif",
+ "",
+ "void dfs_uerror(char *);",
+ "void dfs_Uerror(char *);",
+ "#ifdef BFS_PAR",
+ "void bfs_uerror(char *);",
+ "void bfs_Uerror(char *);",
+ "#endif",
+ "void (*uerror)(char *);",
+ "void (*Uerror)(char *);",
+ "void (*hasher)(uchar *, int);",
+ "void (*o_hash)(uchar *, int, int);",
+ "void d_hash(uchar *, int);",
+ "void m_hash(uchar *, int);",
+ "void d_sfh(uchar *, int);",
+ "void o_hash32(uchar *, int, int);",
+ "void o_hash64(uchar *, int, int);",
+ "",
"void active_procs(void);",
"void cleanup(void);",
"void do_the_search(void);",
"void find_shorter(int);",
- "void iniglobals(void);",
+ "void iniglobals(int);",
"void stopped(int);",
"void wrapup(void);",
"int *grab_ints(int);",
@@ -320,7 +508,7 @@
0,
};
-static char *Tail[] = {
+static const char *Tail[] = {
"Trans *",
"settr( int t_id, int a, int b, int c, int d,",
" char *t, int g, int tpe0, int tpe1)",
@@ -425,10 +613,14 @@
"}",
"#endif",
"void",
- "retrans(int n, int m, int is, short srcln[], uchar reach[])",
+ "retrans(int n, int m, int is, short srcln[], uchar reach[], uchar lpstate[])",
" /* process n, with m states, is=initial state */",
"{ Trans *T0, *T1, *T2, *T3;",
- " int i, k;",
+ " Trans *T4, *T5; /* t_reverse or has_unless */",
+ " int i;",
+ "#if defined(HAS_UNLESS) || !defined(NOREDUCE)",
+ " int k;",
+ "#endif",
"#ifndef NOREDUCE",
" int g, h, j, aa;",
"#endif",
@@ -436,7 +628,7 @@
" int p;",
"#endif",
" if (state_tables >= 4)",
- " { printf(\"STEP 1 proctype %%s\\n\", ",
+ " { printf(\"STEP 1 %%s\\n\", ",
" procname[n]);",
" for (i = 1; i < m; i++)",
" for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
@@ -477,7 +669,7 @@
" } while (cnt);",
" if (state_tables >= 3)",
- " { printf(\"STEP 2 proctype %%s\\n\", ",
+ " { printf(\"STEP 2 %%s\\n\", ",
" procname[n]);",
" for (i = 1; i < m; i++)",
" for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
@@ -490,7 +682,9 @@
"#if 0",
" printf(\"\\t\\tpull %%d (%%d) to %%d\\n\",",
" T1->st, T1->forw, i);",
- "#endif",
+ "#endif", /* pull linenumber ref as well: */
+ " srcln[i] = srcln[T1->st]; /* Oyvind Teig, 5.2.0 */",
+ "",
" if (!trans[n][T1->st]) continue;",
" T0 = cpytr(trans[n][T1->st]);",
" trans[n][i] = T0;",
@@ -502,6 +696,7 @@
" printf(\"\\t\\tpull %%d (%%d) to %%d\\n\",",
" T1->st, T1->forw, i);",
"#endif",
+ " /* srcln[i] = srcln[T1->st]; gh: not useful */",
" if (!trans[n][T1->st]) continue;",
" T0->nxt = cpytr(trans[n][T1->st]);",
" T0 = T0->nxt;",
@@ -509,7 +704,7 @@
" imed(T0, T1->st, n, i);",
" } } }",
" if (state_tables >= 2)",
- " { printf(\"STEP 3 proctype %%s\\n\", ",
+ " { printf(\"STEP 3 %%s\\n\", ",
" procname[n]);",
" for (i = 1; i < m; i++)",
" for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
@@ -525,8 +720,8 @@
" * and prepend them to the transition-",
" * list of state i",
" */",
- " if (!like_java) /* the default */",
- " { for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
+ " if (!like_java) /* the default */",
+ " { for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
" for (k = HAS_UNLESS-1; k >= 0; k--)",
" { if (p = T0->escp[k])",
" for (T1 = trans[n][p]; T1; T1 = T1->nxt)",
@@ -537,9 +732,8 @@
" T2->nxt = trans[n][i];",
" trans[n][i] = T2;",
" } }",
- " } else /* outermost unless checked first */",
- " { Trans *T4;",
- " T4 = T3 = (Trans *) 0;",
+ " } else /* outermost unless checked first */",
+ " { T4 = T3 = (Trans *) 0;",
" for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
" for (k = HAS_UNLESS-1; k >= 0; k--)",
" { if (p = T0->escp[k])",
@@ -557,22 +751,21 @@
" { T3->nxt = trans[n][i];",
" trans[n][i] = T4;",
" }",
- " }",
+ " }",
" }",
"#endif",
"#ifndef NOREDUCE",
" for (i = 1; i < m; i++)",
- " {",
- " if (a_cycles)",
+ " { if (a_cycles)",
" { /* moves through these states are visible */",
- "#if PROG_LAB>0 && defined(HAS_NP)",
+ " #if PROG_LAB>0 && defined(HAS_NP)",
" if (progstate[n][i])",
" goto degrade;",
" for (T1 = trans[n][i]; T1; T1 = T1->nxt)",
" if (progstate[n][T1->st])",
" goto degrade;",
- "#endif",
+ " #endif",
" if (accpstate[n][i] || visstate[n][i])",
" goto degrade;",
" for (T1 = trans[n][i]; T1; T1 = T1->nxt)",
@@ -668,19 +861,44 @@
" continue;",
" stopstate[n][T2->st] = 1;",
" }",
- " if (state_tables)",
- " { printf(\"proctype \");",
- " if (!strcmp(procname[n], \":init:\"))",
- " printf(\"init\\n\");",
- " else",
- " printf(\"%%s\\n\", procname[n]);",
+ " if (state_tables && !verbose)",
+ " { if (dodot)",
+ " { char buf[256], *q = buf, *p = procname[n];",
+ " while (*p != '\\0')",
+ " { if (*p != ':')",
+ " { *q++ = *p;",
+ " }",
+ " p++;",
+ " }",
+ " *q = '\\0';",
+ " printf(\"digraph \");",
+ " switch (Btypes[n]) {",
+ " case I_PROC: printf(\"init {\\n\"); break;",
+ " case N_CLAIM: printf(\"claim_%%s {\\n\", buf); break;",
+ " case E_TRACE: printf(\"notrace {\\n\"); break;",
+ " case N_TRACE: printf(\"trace {\\n\"); break;",
+ " default: printf(\"p_%%s {\\n\", buf); break;",
+ " }",
+ " printf(\"size=\\\"8,10\\\";\\n\");",
+ " printf(\" GT [shape=box,style=dotted,label=\\\"%%s\\\"];\\n\", buf);",
+ " printf(\" GT -> S%%d;\\n\", is);",
+ " } else",
+ " { switch (Btypes[n]) {",
+ " case I_PROC: printf(\"init\\n\"); break;",
+ " case N_CLAIM: printf(\"claim %%s\\n\", procname[n]); break;",
+ " case E_TRACE: printf(\"notrace assertion\\n\"); break;",
+ " case N_TRACE: printf(\"trace assertion\\n\"); break;",
+ " default: printf(\"proctype %%s\\n\", procname[n]); break;",
+ " } }",
" for (i = 1; i < m; i++)",
- " reach[i] = 1;",
+ " { reach[i] = 1;",
+ " }",
" tagtable(n, m, is, srcln, reach);",
+ " if (dodot) printf(\"}\\n\");",
" } else",
" for (i = 1; i < m; i++)",
" { int nrelse;",
- " if (strcmp(procname[n], \":never:\") != 0)",
+ " if (Btypes[n] != N_CLAIM)",
" { for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
" { if (T0->st == i",
" && strcmp(T0->tp, \"(1)\") == 0)",
@@ -703,16 +921,84 @@
" printf(\" 'else' stmnts\\n\");",
" pan_exit(1);",
" } }",
- " if (!state_tables && strcmp(procname[n], \":never:\") == 0)",
- " { int h = 0;",
+ "#if !defined(LOOPSTATE) && !defined(BFS_PAR)",
+ " if (state_tables)",
+ "#endif",
+ " do_dfs(n, m, is, srcln, reach, lpstate);",
+ "",
+ " if (!t_reverse)",
+ " { return;",
+ " }",
+ " /* process n, with m states, is=initial state -- reverse list */",
+ " if (!state_tables && Btypes[n] != N_CLAIM)",
+ " { for (i = 1; i < m; i++)", /* for each state */
+ " { Trans *Tx = (Trans *) 0; /* list of escapes */",
+ " Trans *Ty = (Trans *) 0; /* its tail element */",
+ " T1 = (Trans *) 0; /* reversed list */",
+ " T2 = (Trans *) 0; /* its tail */",
+ " T3 = (Trans *) 0; /* remembers possible 'else' */",
+ "",
+ " /* find unless-escapes, they should go first */",
+ " T4 = T5 = T0 = trans[n][i];",
+ " #ifdef HAS_UNLESS",
+ " while (T4 && T4->e_trans) /* escapes are first in orig list */",
+ " { T5 = T4; /* remember predecessor */",
+ " T4 = T4->nxt;",
+ " }",
+ " #endif",
+ " /* T4 points to first non-escape, T5 to its parent, T0 to original list */",
+ " if (T4 != T0) /* there was at least one escape */",
+ " { T3 = T5->nxt; /* start of non-escapes */",
+ " T5->nxt = (Trans *) 0; /* separate */",
+ " Tx = T0; /* start of the escapes */",
+ " Ty = T5; /* its tail */",
+ " T0 = T3; /* the rest, to be reversed */",
+ " }",
+ " /* T0 points to first non-escape, Tx to the list of escapes, Ty to its tail */",
+ "",
+ " /* first tail-add non-escape transitions, reversed */",
+ " T3 = (Trans *) 0;", /* remember a possible 'else' */
+ " for (T5 = T0; T5; T5 = T4)",
+ " { T4 = T5->nxt;",
+ " #ifdef HAS_UNLESS",
+ " if (T5->e_trans)",
+ " { printf(\"error: cannot happen!\\n\");",
+ " continue;",
+ " }",
+ " #endif",
+ " if (strcmp(T5->tp, \"else\") == 0)",
+ " { T3 = T5;",
+ " T5->nxt = (Trans *) 0;",
+ " } else",
+ " { T5->nxt = T1;",
+ " if (!T1) { T2 = T5; }",
+ " T1 = T5;",
+ " } }",
+ " /* T3 points to a possible else, which is removed from the list */",
+ " /* T1 points to the reversed list so far (without escapes) */",
+ " /* T2 points to the tail element -- where the else should go */",
+ " if (T2 && T3)",
+ " { T2->nxt = T3; /* add else */",
+ " } else",
+ " { if (T3) /* there was an else, but there's no tail */",
+ " { if (!T1) /* and no reversed list */",
+ " { T1 = T3; /* odd, but possible */",
+ " } else /* even stranger */",
+ " { T1->nxt = T3;",
+ " } } }",
+ "",
+ " /* add in the escapes, to that they appear at the front */",
+ " if (Tx && Ty) { Ty->nxt = T1; T1 = Tx; }",
+ "",
+ " trans[n][i] = T1;",
+ " /* reversed, with escapes first and else last */",
+ " } }",
+ " if (state_tables && verbose)",
+ " { printf(\"FINAL proctype %%s\\n\", ",
+ " procname[n]);",
" for (i = 1; i < m; i++)",
" for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
- " if (T0->forw > h) h = T0->forw;",
- " h++;",
- " frm_st0 = (short *) emalloc(h * sizeof(short));",
- " for (i = 1; i < m; i++)",
- " for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
- " frm_st0[T0->forw] = i;",
+ " crack(n, i, T0, srcln);",
" }",
"}",
"void",
@@ -731,7 +1017,12 @@
" reach[is] = 0;",
" if (state_tables)",
" for (z = trans[n][is]; z; z = z->nxt)",
- " crack(n, is, z, srcln);",
+ " { if (dodot)",
+ " dot_crack(n, is, z);",
+ " else",
+ " crack(n, is, z, srcln);",
+ " }",
+ "",
" for (z = trans[n][is]; z; z = z->nxt)",
" {",
"#ifdef HAS_UNLESS",
@@ -747,7 +1038,48 @@
"#endif",
" }",
"}",
+ "",
+ "extern Trans *t_id_lkup[];", /* needed by BFS_PAR */
+ "",
"void",
+ "dfs_table(int n, int m, int is, short srcln[], uchar reach[], uchar lpstate[])",
+ "{ Trans *z;\n",
+ " if (is >= m || is <= 0 || !trans[n][is])",
+ " return;",
+ " if ((reach[is] & (4|8|16)) != 0)",
+ " { if ((reach[is] & (8|16)) == 16) /* on stack, not yet recorded */",
+ " { lpstate[is] = 1;",
+ " reach[is] |= 8; /* recorded */",
+ " if (state_tables && verbose)",
+ " { printf(\"state %%d line %%d is a loopstate\\n\", is, srcln[is]);",
+ " } }",
+ " return;",
+ " }",
+ " reach[is] |= (4|16); /* visited | onstack */",
+ " for (z = trans[n][is]; z; z = z->nxt)",
+ " { t_id_lkup[z->t_id] = z;", /* needed by BFS_PAR */
+ "#ifdef HAS_UNLESS",
+ " int i, j;",
+ "#endif",
+ " dfs_table(n, m, z->st, srcln, reach, lpstate);",
+ "#ifdef HAS_UNLESS",
+ " for (i = 0; i < HAS_UNLESS; i++)",
+ " { j = trans[n][is]->escp[i];",
+ " if (!j) break;",
+ " dfs_table(n, m, j, srcln, reach, lpstate);",
+ " }",
+ "#endif",
+ " }",
+ " reach[is] &= ~16; /* no longer on stack */",
+ "}",
+ "void",
+ "do_dfs(int n, int m, int is, short srcln[], uchar reach[], uchar lpstate[])",
+ "{ int i;",
+ " dfs_table(n, m, is, srcln, reach, lpstate);",
+ " for (i = 0; i < m; i++)",
+ " reach[i] &= ~(4|8|16);",
+ "}",
+ "void",
"crack(int n, int j, Trans *z, short srcln[])",
"{ int i;\n",
" if (!z) return;",
@@ -765,19 +1097,19 @@
" }",
"#endif",
" printf(\"]\");",
- " printf(\" [%%s%%s%%s%%s%%s] line %%d => \",",
+ " printf(\" [%%s%%s%%s%%s%%s] %%s:%%d => \",",
" z->atom&6?\"A\":z->atom&32?\"D\":\"-\",",
" accpstate[n][j]?\"a\" :\"-\",",
" stopstate[n][j]?\"e\" : \"-\",",
" progstate[n][j]?\"p\" : \"-\",",
" z->atom & 8 ?\"L\":\"G\",",
- " srcln[j]);",
+ " PanSource, srcln[j]);",
" for (i = 0; z->tp[i]; i++)",
" if (z->tp[i] == \'\\n\')",
" printf(\"\\\\n\");",
" else",
" putchar(z->tp[i]);",
- " if (z->qu[0])",
+ " if (verbose && z->qu[0])",
" { printf(\"\\t[\");",
" for (i = 0; i < 6; i++)",
" if (z->qu[i])",
@@ -787,6 +1119,32 @@
" }",
" printf(\"\\n\");",
" fflush(stdout);",
+ "}",
+ "/* spin -a m.pml; cc -o pan pan.c; ./pan -D | dot -Tps > foo.ps; ps2pdf foo.ps */",
+ "void",
+ "dot_crack(int n, int j, Trans *z)",
+ "{ int i;\n",
+ " if (!z) return;",
+ " printf(\"\tS%%d -> S%%d [color=black\", j, z->st);",
+ "",
+ " if (z->atom&6) printf(\",style=dashed\");", /* A */
+ " else if (z->atom&32) printf(\",style=dotted\");", /* D */
+ " else if (z->atom&8) printf(\",style=solid\");", /* L */
+ " else printf(\",style=bold\");", /* G */
+ /* other styles: filled dotted */
+ "",
+ " printf(\",label=\\\"\");",
+ " for (i = 0; z->tp[i]; i++)",
+ " { if (z->tp[i] == \'\\\\\'",
+ " && z->tp[i+1] == \'n\')",
+ " { i++; printf(\" \");",
+ " } else",
+ " { putchar(z->tp[i]);",
+ " } }",
+ " printf(\"\\\"];\\n\");",
+ " if (accpstate[n][j]) printf(\" S%%d [color=red,style=bold];\\n\", j);",
+ " else if (progstate[n][j]) printf(\" S%%d [color=green,style=bold];\\n\", j);",
+ " if (stopstate[n][j]) printf(\" S%%d [color=blue,style=bold,shape=box];\\n\", j);",
"}",
"",
"#ifdef VAR_RANGES",
--- a/sys/src/cmd/spin/pangen3.c
+++ b/sys/src/cmd/spin/pangen3.c
@@ -1,22 +1,20 @@
/***** spin: pangen3.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include "spin.h"
#include "y.tab.h"
+#include <assert.h>
-extern FILE *th;
-extern int claimnr, eventmapnr;
+extern FILE *th, *tc;
+extern int eventmapnr, old_priority_rules;
typedef struct SRC {
- short ln, st; /* linenr, statenr */
+ int ln, st; /* linenr, statenr */
Symbol *fn; /* filename */
struct SRC *nxt;
} SRC;
@@ -28,6 +26,8 @@
static SRC *frst = (SRC *) 0;
static SRC *skip = (SRC *) 0;
+extern int ltl_mode;
+
extern void sr_mesg(FILE *, int, int);
static void
@@ -34,10 +34,10 @@
putnr(int n)
{
if (col++ == 8)
- { fprintf(th, "\n\t");
+ { fprintf(tc, "\n\t"); /* was th */
col = 1;
}
- fprintf(th, "%3d, ", n);
+ fprintf(tc, "%3d, ", n); /* was th */
}
static void
@@ -47,7 +47,7 @@
return;
if (lastfnm)
- fprintf(th, "{ %s, %d, %d },\n\t",
+ fprintf(tc, "{ \"%s\", %d, %d },\n\t", /* was th */
lastfnm->name,
lastfrom,
j-1);
@@ -59,41 +59,67 @@
putfnm_flush(int j)
{
if (lastfnm)
- fprintf(th, "{ %s, %d, %d }\n",
+ fprintf(tc, "{ \"%s\", %d, %d }\n", /* was th */
lastfnm->name,
lastfrom, j);
}
-void
-putskip(int m) /* states that need not be reached */
+static SRC *
+newsrc(int m, SRC *n)
{ SRC *tmp;
-
- for (tmp = skip; tmp; tmp = tmp->nxt)
- if (tmp->st == m)
- return;
tmp = (SRC *) emalloc(sizeof(SRC));
- tmp->st = (short) m;
- tmp->nxt = skip;
- skip = tmp;
+ tmp->st = m;
+ tmp->nxt = n;
+ return tmp;
}
void
+putskip(int m) /* states that need not be reached */
+{ SRC *tmp, *lst = (SRC *)0;
+ /* 6.4.0: now an ordered list */
+ for (tmp = skip; tmp; lst = tmp, tmp = tmp->nxt)
+ { if (tmp->st == m)
+ { return;
+ }
+ if (tmp->st > m) /* insert before */
+ { if (tmp == skip)
+ { tmp = newsrc(m, skip);
+ skip = tmp;
+ } else
+ { assert(lst);
+ tmp = newsrc(m, lst->nxt);
+ lst->nxt = tmp;
+ }
+ return;
+ } }
+ /* insert at the end */
+ if (lst)
+ { lst->nxt = newsrc(m, 0);
+ } else /* empty list */
+ { skip = newsrc(m, 0);
+ }
+}
+
+void
unskip(int m) /* a state that needs to be reached after all */
-{ SRC *tmp, *lst=(SRC *)0;
+{ SRC *tmp, *lst = (SRC *)0;
for (tmp = skip; tmp; lst = tmp, tmp = tmp->nxt)
- if (tmp->st == m)
+ { if (tmp->st == m)
{ if (tmp == skip)
skip = skip->nxt;
- else
+ else if (lst) /* always true, but helps coverity */
lst->nxt = tmp->nxt;
break;
}
+ if (tmp->st > m)
+ { break; /* m is not in list */
+ } }
}
void
putsrc(Element *e) /* match states to source lines */
-{ SRC *tmp;
+{ SRC *tmp, *lst = (SRC *)0;
int n, m;
if (!e || !e->n) return;
@@ -100,32 +126,51 @@
n = e->n->ln;
m = e->seqno;
-
- for (tmp = frst; tmp; tmp = tmp->nxt)
- if (tmp->st == m)
+ /* 6.4.0: now an ordered list */
+ for (tmp = frst; tmp; lst = tmp, tmp = tmp->nxt)
+ { if (tmp->st == m)
{ if (tmp->ln != n || tmp->fn != e->n->fn)
- printf("putsrc mismatch %d - %d, file %s\n", n,
+ printf("putsrc mismatch seqno %d, line %d - %d, file %s\n", m, n,
tmp->ln, tmp->fn->name);
return;
}
- tmp = (SRC *) emalloc(sizeof(SRC));
- tmp->ln = (short) n;
- tmp->st = (short) m;
+ if (tmp->st > m) /* insert before */
+ { if (tmp == frst)
+ { tmp = newsrc(m, frst);
+ frst = tmp;
+ } else
+ { assert(lst);
+ tmp = newsrc(m, lst->nxt);
+ lst->nxt = tmp;
+ }
+ tmp->ln = n;
+ tmp->fn = e->n->fn;
+ return;
+ } }
+ /* insert at the end */
+ tmp = newsrc(m, lst?lst->nxt:0);
+ tmp->ln = n;
tmp->fn = e->n->fn;
- tmp->nxt = frst;
- frst = tmp;
+ if (lst)
+ { lst->nxt = tmp;
+ } else
+ { frst = tmp;
+ }
}
static void
dumpskip(int n, int m)
{ SRC *tmp, *lst;
+ FILE *tz = tc; /* was th */
int j;
- fprintf(th, "uchar reached%d [] = {\n\t", m);
+ fprintf(tz, "uchar reached%d [] = {\n\t", m);
+ tmp = skip;
+ lst = (SRC *) 0;
for (j = 0, col = 0; j <= n; j++)
- { lst = (SRC *) 0;
- for (tmp = skip; tmp; lst = tmp, tmp = tmp->nxt)
- if (tmp->st == j)
+ { /* find j in the sorted list */
+ for ( ; tmp; lst = tmp, tmp = tmp->nxt)
+ { if (tmp->st == j)
{ putnr(1);
if (lst)
lst->nxt = tmp->nxt;
@@ -133,12 +178,17 @@
skip = tmp->nxt;
break;
}
+ if (tmp->st > j)
+ { putnr(0);
+ break; /* j is not in the list */
+ } }
+
if (!tmp)
- putnr(0);
- }
- fprintf(th, "};\n");
- if (m == claimnr)
- fprintf(th, "#define reached_claim reached%d\n", m);
+ { putnr(0);
+ } }
+ fprintf(tz, "};\n");
+ fprintf(tz, "uchar *loopstate%d;\n", m);
+
if (m == eventmapnr)
fprintf(th, "#define reached_event reached%d\n", m);
@@ -149,27 +199,34 @@
dumpsrc(int n, int m)
{ SRC *tmp, *lst;
int j;
+ static int did_claim = 0;
+ FILE *tz = tc; /* was th */
- fprintf(th, "short src_ln%d [] = {\n\t", m);
+ fprintf(tz, "\nshort src_ln%d [] = {\n\t", m);
+ tmp = frst;
for (j = 0, col = 0; j <= n; j++)
- { lst = (SRC *) 0;
- for (tmp = frst; tmp; lst = tmp, tmp = tmp->nxt)
- if (tmp->st == j)
+ { for ( ; tmp; tmp = tmp->nxt)
+ { if (tmp->st == j)
{ putnr(tmp->ln);
break;
}
+ if (tmp->st > j)
+ { putnr(0);
+ break;
+ } }
if (!tmp)
- putnr(0);
- }
- fprintf(th, "};\n");
+ { putnr(0);
+ } }
+ fprintf(tz, "};\n");
lastfnm = (Symbol *) 0;
- lastdef.name = "\"-\"";
- fprintf(th, "S_F_MAP src_file%d [] = {\n\t", m);
+ lastdef.name = "-";
+ fprintf(tz, "S_F_MAP src_file%d [] = {\n\t", m);
+ tmp = frst;
+ lst = (SRC *) 0;
for (j = 0, col = 0; j <= n; j++)
- { lst = (SRC *) 0;
- for (tmp = frst; tmp; lst = tmp, tmp = tmp->nxt)
- if (tmp->st == j)
+ { for ( ; tmp; lst = tmp, tmp = tmp->nxt)
+ { if (tmp->st == j)
{ putfnm(j, tmp->fn);
if (lst)
lst->nxt = tmp->nxt;
@@ -177,14 +234,20 @@
frst = tmp->nxt;
break;
}
+ if (tmp->st > j)
+ { putfnm(j, &lastdef);
+ break;
+ } }
if (!tmp)
- putfnm(j, &lastdef);
- }
+ { putfnm(j, &lastdef);
+ } }
putfnm_flush(j);
- fprintf(th, "};\n");
+ fprintf(tz, "};\n");
- if (m == claimnr)
- fprintf(th, "#define src_claim src_ln%d\n", m);
+ if (pid_is_claim(m) && !did_claim)
+ { fprintf(tz, "short *src_claim;\n");
+ did_claim++;
+ }
if (m == eventmapnr)
fprintf(th, "#define src_event src_ln%d\n", m);
@@ -237,7 +300,27 @@
case GT: Cat1(">"); break;
case LT: Cat1("<"); break;
case NE: Cat1("!="); break;
- case EQ: Cat1("=="); break;
+ case EQ:
+ if (ltl_mode
+ && now->lft->ntyp == 'p'
+ && now->rgt->ntyp == 'q') /* remote ref */
+ { Lextok *p = now->lft->lft;
+
+ fprintf(fd, "(");
+ fprintf(fd, "%s", p->sym->name);
+ if (p->lft)
+ { fprintf(fd, "[");
+ putstmnt(fd, p->lft, 0); /* pid */
+ fprintf(fd, "]");
+ }
+ fprintf(fd, "@");
+ fprintf(fd, "%s", now->rgt->sym->name);
+ fprintf(fd, ")");
+ break;
+ }
+ Cat1("==");
+ break;
+
case OR: Cat1("||"); break;
case AND: Cat1("&&"); break;
case LSHIFT: Cat1("<<"); break;
@@ -298,6 +381,22 @@
case ENABLED: Cat3("enabled(", now->lft, ")");
break;
+ case GET_P: if (old_priority_rules)
+ { fprintf(fd, "1");
+ } else
+ { Cat3("get_priority(", now->lft, ")");
+ }
+ break;
+
+ case SET_P: if (!old_priority_rules)
+ { fprintf(fd, "set_priority(");
+ comwork(fd, now->lft->lft, m);
+ fprintf(fd, ", ");
+ comwork(fd, now->lft->rgt, m);
+ fprintf(fd, ")");
+ }
+ break;
+
case EVAL: Cat3("eval(", now->lft, ")");
break;
@@ -320,12 +419,14 @@
}
break;
- case ASGN: comwork(fd,now->lft,m);
+ case ASGN:
+ if (check_track(now) == STRUCT) { break; }
+ comwork(fd,now->lft,m);
fprintf(fd," = ");
comwork(fd,now->rgt,m);
break;
- case PRINT: { char c, buf[512];
+ case PRINT: { char c, buf[1024];
strncpy(buf, now->sym->name, 510);
for (i = j = 0; i < 510; i++, j++)
{ c = now->sym->name[i];
@@ -349,9 +450,23 @@
comwork(fd, now->lft, m);
fprintf(fd, ")");
break;
- case NAME: putname(fd, "", now, m, "");
+ case NAME:
+ putname(fd, "", now, m, "");
break;
- case 'p': putremote(fd, now, m);
+
+ case 'p':
+ if (ltl_mode)
+ { fprintf(fd, "%s", now->lft->sym->name); /* proctype */
+ if (now->lft->lft)
+ { fprintf(fd, "[");
+ putstmnt(fd, now->lft->lft, 0); /* pid */
+ fprintf(fd, "]");
+ }
+ fprintf(fd, ":"); /* remote varref */
+ fprintf(fd, "%s", now->sym->name); /* varname */
+ break;
+ }
+ putremote(fd, now, m);
break;
case 'q': fprintf(fd, "%s", now->sym->name);
break;
@@ -366,7 +481,7 @@
case ELSE: fprintf(fd, "else"); break;
case '@': fprintf(fd, "-end-"); break;
- case D_STEP: fprintf(fd, "D_STEP"); break;
+ case D_STEP: fprintf(fd, "D_STEP%d", now->ln); break;
case ATOMIC: fprintf(fd, "ATOMIC"); break;
case NON_ATOMIC: fprintf(fd, "sub-sequence"); break;
case IF: fprintf(fd, "IF"); break;
--- a/sys/src/cmd/spin/pangen3.h
+++ b/sys/src/cmd/spin/pangen3.h
@@ -1,22 +1,19 @@
/***** spin: pangen3.h *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
-static char *Head0[] = {
+static const char *Head0[] = {
"#if defined(BFS) && defined(REACH)",
- "#undef REACH", /* redundant with bfs */
+ " #undef REACH", /* redundant with bfs */
"#endif",
"#ifdef VERI",
- "#define BASE 1",
+ " #define BASE 1",
"#else",
- "#define BASE 0",
+ " #define BASE 0",
"#endif",
"typedef struct Trans {",
" short atom; /* if &2 = atomic trans; if &8 local */",
@@ -37,108 +34,131 @@
" int back; /* index return transition */",
" struct Trans *nxt;",
"} Trans;\n",
- "#define qptr(x) (((uchar *)&now)+(int)q_offset[x])",
- "#define pptr(x) (((uchar *)&now)+(int)proc_offset[x])",
-/* "#define Pptr(x) ((proc_offset[x])?pptr(x):noptr)", */
+
+ "#ifdef TRIX",
+ " #define qptr(x) (channels[x]->body)",
+ " #define pptr(x) (processes[x]->body)",
+ "#else",
+ " #define qptr(x) (((uchar *)&now)+(int)q_offset[x])",
+ " #define pptr(x) (((uchar *)&now)+(int)proc_offset[x])",
+/* " #define Pptr(x) ((proc_offset[x])?pptr(x):noptr)", */
+ "#endif",
"extern uchar *Pptr(int);",
+ "extern uchar *Qptr(int);",
- "#define q_sz(x) (((Q0 *)qptr(x))->Qlen)\n",
- "#ifndef VECTORSZ",
- "#define VECTORSZ 1024 /* sv size in bytes */",
+ "#define q_sz(x) (((Q0 *)qptr(x))->Qlen)",
+ "",
+ "#ifdef TRIX",
+ " #ifdef VECTORSZ",
+ " #undef VECTORSZ", /* backward compatibility */
+ " #endif",
+ " #if WS==4",
+ " #define VECTORSZ 2056 /* ((MAXPROC+MAXQ+4)*sizeof(uchar *)) */",
+ " #else",
+ " #define VECTORSZ 4112 /* the formula causes probs in preprocessing */",
+ " #endif",
+ "#else",
+ " #ifndef VECTORSZ",
+ " #define VECTORSZ 1024 /* sv size in bytes */",
+ " #endif",
"#endif\n",
+ "#define MAXQ 255",
+ "#define MAXPROC 255",
+ "",
0,
};
-static char *Header[] = {
+static const char *Header[] = {
"#ifdef VERBOSE",
- "#ifndef CHECK",
- "#define CHECK",
- "#endif",
- "#ifndef DEBUG",
- "#define DEBUG",
- "#endif",
+ " #ifndef CHECK",
+ " #define CHECK",
+ " #endif",
+ " #ifndef DEBUG",
+ " #define DEBUG",
+ " #endif",
"#endif",
"#ifdef SAFETY",
- "#ifndef NOFAIR",
- "#define NOFAIR",
- "#endif",
+ " #ifndef NOFAIR",
+ " #define NOFAIR",
+ " #endif",
"#endif",
+#if 0
+ NOREDUCE BITSTATE SAFETY MA WS>4
+ CNTRSTACK: - + + d -
+ FULLSTACK: + d - - d
+ - + d d d
+ - + + d +
+ - - d d d
+ Neither: + d + d d
+ + d d + d
+#endif
"#ifdef NOREDUCE",
- "#ifndef XUSAFE",
- "#define XUSAFE",
- "#endif",
- "#if !defined(SAFETY) && !defined(MA)",
- "#define FULLSTACK",
- "#endif",
+ " #ifndef XUSAFE",
+ " #define XUSAFE",
+ " #endif",
+ " #if !defined(SAFETY) && !defined(MA)",
+ " #define FULLSTACK", /* => NOREDUCE && !SAFETY && !MA */
+ " #endif",
"#else",
- "#ifdef BITSTATE",
- "#ifdef SAFETY && !defined(HASH64)",
- "#define CNTRSTACK",
- "#else",
- "#define FULLSTACK",
- "#endif",
- "#else",
- "#define FULLSTACK",
- "#endif",
+ " #ifdef BITSTATE",
+ " #if defined(SAFETY) && WS<=4",
+ " #define CNTRSTACK", /* => !NOREDUCE && BITSTATE && SAFETY && WS<=4 */
+ " #else",
+ " #define FULLSTACK", /* => !NOREDUCE && BITSTATE && (!SAFETY || WS>4) */
+ " #endif",
+ " #else",
+ " #define FULLSTACK", /* => !NOREDUCE && !BITSTATE */
+ " #endif",
"#endif",
"#ifdef BITSTATE",
- "#ifndef NOCOMP",
- "#define NOCOMP",
- "#endif",
- "#if !defined(LC) && defined(SC)",
- "#define LC",
- "#endif",
+ " #ifndef NOCOMP",
+ " #define NOCOMP",
+ " #endif",
+ " #if !defined(LC) && defined(SC)",
+ " #define LC",
+ " #endif",
"#endif",
"#if defined(COLLAPSE2) || defined(COLLAPSE3) || defined(COLLAPSE4)",
- "/* accept the above for backward compatibility */",
- "#define COLLAPSE",
+ " /* accept the above for backward compatibility */",
+ " #define COLLAPSE",
"#endif",
"#ifdef HC",
- "#undef HC",
- "#define HC4",
+ " #undef HC",
+ " #define HC4",
"#endif",
- "#ifdef HC0", /* 32 bits */
- "#define HC 0",
- "#endif",
- "#ifdef HC1", /* 32+8 bits */
- "#define HC 1",
- "#endif",
- "#ifdef HC2", /* 32+16 bits */
- "#define HC 2",
- "#endif",
- "#ifdef HC3", /* 32+24 bits */
- "#define HC 3",
- "#endif",
- "#ifdef HC4", /* 32+32 bits - combine with -DMA=8 */
- "#define HC 4",
- "#endif",
- "#ifdef COLLAPSE",
- "unsigned long ncomps[256+2];",
- "#endif",
-
- "#define MAXQ 255",
- "#define MAXPROC 255",
- "#define WS sizeof(long) /* word size in bytes */",
- "typedef struct Stack { /* for queues and processes */",
+ "#if defined(HC0) || defined(HC1) || defined(HC2) || defined(HC3) || defined(HC4)",
+ " #define HC 4", /* 2x32 bits */
+ "#endif", /* really only one hashcompact mode, not 5 */
+ "",
+ "typedef struct _Stack { /* for queues and processes */",
"#if VECTORSZ>32000",
" int o_delta;",
- " int o_offset;",
- " int o_skip;",
+ " #ifndef TRIX",
+ " int o_offset;",
+ " int o_skip;",
+ " #endif",
" int o_delqs;",
"#else",
" short o_delta;",
- " short o_offset;",
- " short o_skip;",
+ " #ifndef TRIX",
+ " short o_offset;",
+ " short o_skip;",
+ " #endif",
" short o_delqs;",
"#endif",
" short o_boq;",
+ "#ifdef TRIX",
+ " short parent;",
+ " char *b_ptr;", /* used in delq/q_restor and delproc/p_restor */
+ "#else",
+ " char *body;", /* full copy of state vector in non-trix mode */
+ "#endif",
"#ifndef XUSAFE",
" char *o_name;",
"#endif",
- " char *body;",
- " struct Stack *nxt;",
- " struct Stack *lst;",
- "} Stack;\n",
+ " struct _Stack *nxt;",
+ " struct _Stack *lst;",
+ "} _Stack;\n",
"typedef struct Svtack { /* for complete state vector */",
"#if VECTORSZ>32000",
" int o_delta;",
@@ -153,35 +173,15 @@
0,
};
-static char *Header0[] = {
+static const char *Header0[] = {
" char *body;",
" struct Svtack *nxt;",
" struct Svtack *lst;",
"} Svtack;\n",
- "Trans ***trans; /* 1 ptr per state per proctype */\n",
- "#if defined(FULLSTACK) || defined(BFS)",
- "struct H_el *Lstate;",
- "#endif",
- "int depthfound = -1; /* loop detection */",
- "#if VECTORSZ>32000",
- "int proc_offset[MAXPROC];",
- "int q_offset[MAXQ];",
- "#else",
- "short proc_offset[MAXPROC];",
- "short q_offset[MAXQ];",
- "#endif",
- "uchar proc_skip[MAXPROC];",
- "uchar q_skip[MAXQ];",
- "unsigned long vsize; /* vector size in bytes */",
- "#ifdef SVDUMP",
- "int vprefix=0, svfd; /* runtime option -pN */",
- "#endif",
- "char *tprefix = \"trail\"; /* runtime option -tsuffix */",
- "short boq = -1; /* blocked_on_queue status */",
0,
};
-static char *Head1[] = {
+static const char *Head1[] = {
"typedef struct State {",
" uchar _nr_pr;",
" uchar _nr_qs;",
@@ -207,24 +207,32 @@
#endif
" unsigned short _vsz;",
"#else",
- " unsigned long _vsz;",
+ " ulong _vsz;",
"#endif",
"#endif",
- "#ifdef HAS_LAST", /* cannot go before _cnt - see hstore() */
+ "#ifdef HAS_LAST", /* cannot go before _cnt - see h_store() */
" uchar _last; /* pid executed in last step */",
"#endif",
+
+ "#if defined(BITSTATE) && defined(BCS) && defined(STORE_CTX)",
+ " uchar _ctx; /* nr of context switches so far */",
+ "#endif",
+ "#if defined(BFS_PAR) && defined(L_BOUND)",
+ " uchar _l_bnd; /* bounded liveness */",
+ " uchar *_l_sds; /* seed state */",
+ "#endif",
"#ifdef EVENT_TRACE",
- "#if nstates_event<256",
- " uchar _event;",
- "#else",
- " unsigned short _event;",
- "#endif",
+ " #if nstates_event<256",
+ " uchar _event;",
+ " #else",
+ " unsigned short _event;",
+ " #endif",
"#endif",
0,
};
-static char *Addp0[] = {
+static const char *Addp0[] = {
/* addproc(....parlist... */ ")",
"{ int j, h = now._nr_pr;",
"#ifndef NOCOMP",
@@ -235,45 +243,66 @@
" if (TstOnly) return (h < MAXPROC);",
"#endif",
"#ifndef NOBOUNDCHECK",
- "/* redefine Index only within this procedure */",
- "#undef Index",
- "#define Index(x, y) Boundcheck(x, y, 0, 0, 0)",
+ " /* redefine Index only within this procedure */",
+ " #undef Index",
+ " #define Index(x, y) Boundcheck(x, y, 0, 0, 0)",
"#endif",
" if (h >= MAXPROC)",
" Uerror(\"too many processes\");",
+ "#ifdef V_TRIX",
+ " printf(\"%%4d: add process %%d\\n\", depth, h);",
+ "#endif",
" switch (n) {",
" case 0: j = sizeof(P0); break;",
0,
};
-static char *Addp1[] = {
+static const char *Addp1[] = {
" default: Uerror(\"bad proc - addproc\");",
" }",
+ " #ifdef BFS_PAR",
+ " bfs_prepmask(1); /* addproc */",
+ " #endif",
+
+ "#ifdef TRIX",
+ " vsize += sizeof(H_el *);",
+ "#else",
" if (vsize%%WS)",
" proc_skip[h] = WS-(vsize%%WS);",
" else",
" proc_skip[h] = 0;",
- "#ifndef NOCOMP",
- " for (k = vsize + (int) proc_skip[h]; k > vsize; k--)",
- " Mask[k-1] = 1; /* align */",
- "#endif",
+ " #if !defined(NOCOMP) && !defined(HC)",
+ " for (k = vsize + (int) proc_skip[h]; k > vsize; k--)",
+ " Mask[k-1] = 1; /* align */",
+ " #endif",
" vsize += (int) proc_skip[h];",
" proc_offset[h] = vsize;",
- "#ifdef SVDUMP",
+ " vsize += j;",
+ " #if defined(SVDUMP) && defined(VERBOSE)",
" if (vprefix > 0)",
" { int dummy = 0;",
" write(svfd, (uchar *) &dummy, sizeof(int)); /* mark */",
" write(svfd, (uchar *) &h, sizeof(int));",
" write(svfd, (uchar *) &n, sizeof(int));",
- "#if VECTORSZ>32000",
+ " #if VECTORSZ>32000",
" write(svfd, (uchar *) &proc_offset[h], sizeof(int));",
- "#else",
- " write(svfd, (uchar *) &proc_offset[h], sizeof(short));",
- "#endif",
" write(svfd, (uchar *) &now, vprefix-4*sizeof(int)); /* padd */",
+ " #else",
+ " write(svfd, (uchar *) &proc_offset[h], sizeof(short));",
+ " write(svfd, (uchar *) &now, vprefix-3*sizeof(int)-sizeof(short)); /* padd */",
+ " #endif",
" }",
+ " #endif",
"#endif",
+
" now._nr_pr += 1;",
+ "#if defined(BCS) && defined(CONSERVATIVE)",
+ " if (now._nr_pr >= CONSERVATIVE*8)",
+ " { printf(\"pan: error: too many processes -- recompile with \");",
+ " printf(\"-DCONSERVATIVE=%%d\\n\", CONSERVATIVE+1);",
+ " pan_exit(1);",
+ " }",
+ "#endif",
" if (fairness && ((int) now._nr_pr + 1 >= (8*NFAIR)/2))",
" { printf(\"pan: error: too many processes -- current\");",
" printf(\" max is %%d procs (-DNFAIR=%%d)\\n\",",
@@ -282,71 +311,127 @@
" NFAIR+1);",
" pan_exit(1);",
" }",
-
- " vsize += j;",
"#ifndef NOVSZ",
" now._vsz = vsize;",
"#endif",
- "#ifndef NOCOMP",
- " for (k = 1; k <= Air[n]; k++)",
- " Mask[vsize - k] = 1; /* pad */",
- " Mask[vsize-j] = 1; /* _pid */",
- "#endif",
" hmax = max(hmax, vsize);",
+
+ "#ifdef TRIX",
+ " #ifndef BFS",
+ " if (freebodies)",
+ " { processes[h] = freebodies;",
+ " freebodies = freebodies->nxt;",
+ " } else",
+ " { processes[h] = (TRIX_v6 *) emalloc(sizeof(TRIX_v6));",
+ " processes[h]->body = (uchar *) emalloc(Maxbody * sizeof(char));",
+ " }",
+ " processes[h]->modified = 1; /* addproc */",
+ " #endif",
+ " processes[h]->psize = j;",
+ " processes[h]->parent_pid = calling_pid;",
+ " processes[h]->nxt = (TRIX_v6 *) 0;",
+ "#else",
+ " #if !defined(NOCOMP) && !defined(HC)",
+ " for (k = 1; k <= Air[n]; k++)",
+ " Mask[vsize - k] = 1; /* pad */",
+ " Mask[vsize-j] = 1; /* _pid */",
+ " #endif",
+ " #ifdef BFS_PAR",
+ " bfs_fixmask(1); /* addproc */",
+ " #endif",
" if (vsize >= VECTORSZ)",
" { printf(\"pan: error, VECTORSZ too small, recompile pan.c\");",
- " printf(\" with -DVECTORSZ=N with N>%%d\\n\", vsize);",
+ " printf(\" with -DVECTORSZ=N with N>%%d\\n\", (int) vsize);",
" Uerror(\"aborting\");",
" }",
+ "#endif",
+
" memset((char *)pptr(h), 0, j);",
" this = pptr(h);",
" if (BASE > 0 && h > 0)",
- " ((P0 *)this)->_pid = h-BASE;",
- " else",
- " ((P0 *)this)->_pid = h;",
+ " { ((P0 *)this)->_pid = h-BASE;",
+ " } else",
+ " { ((P0 *)this)->_pid = h;",
+ " }",
" switch (n) {",
0,
};
-static char *Addq0[] = {
+static const char *Addq0[] = {
+ "",
"int",
- "addqueue(int n, int is_rv)",
+ "addqueue(int calling_pid, int n, int is_rv)",
"{ int j=0, i = now._nr_qs;",
- "#ifndef NOCOMP",
+ "#if !defined(NOCOMP) && !defined(TRIX)",
" int k;",
"#endif",
" if (i >= MAXQ)",
" Uerror(\"too many queues\");",
+ "#ifdef V_TRIX",
+ " printf(\"%%4d: add queue %%d\\n\", depth, i);",
+ "#endif",
" switch (n) {",
0,
};
-static char *Addq1[] = {
+static const char *Addq1[] = {
" default: Uerror(\"bad queue - addqueue\");",
" }",
+ " #ifdef BFS_PAR",
+ " bfs_prepmask(2); /* addqueue */",
+ " #endif",
+
+ "#ifdef TRIX",
+ " vsize += sizeof(H_el *);",
+ "#else",
" if (vsize%%WS)",
" q_skip[i] = WS-(vsize%%WS);",
" else",
" q_skip[i] = 0;",
- "#ifndef NOCOMP",
- " k = vsize;",
- "#ifndef BFS",
- " if (is_rv) k += j;",
- "#endif",
- " for (k += (int) q_skip[i]; k > vsize; k--)",
- " Mask[k-1] = 1;",
- "#endif",
+ " #if !defined(NOCOMP) && !defined(HC)",
+ " k = vsize;",
+ " #ifndef BFS",
+ " if (is_rv) k += j;",
+ " #endif",
+ " for (k += (int) q_skip[i]; k > vsize; k--)",
+ " Mask[k-1] = 1;",
+ " #endif",
" vsize += (int) q_skip[i];",
" q_offset[i] = vsize;",
- " now._nr_qs += 1;",
" vsize += j;",
+ " #ifdef BFS_PAR",
+ " bfs_fixmask(2); /* addqueue */",
+ " #endif",
+ "#endif",
+
+ " now._nr_qs += 1;",
"#ifndef NOVSZ",
" now._vsz = vsize;",
"#endif",
" hmax = max(hmax, vsize);",
+
+ "#ifdef TRIX",
+ " #ifndef BFS",
+ " if (freebodies)",
+ " { channels[i] = freebodies;",
+ " freebodies = freebodies->nxt;",
+ " } else",
+ " { channels[i] = (TRIX_v6 *) emalloc(sizeof(TRIX_v6));",
+ " channels[i]->body = (uchar *) emalloc(Maxbody * sizeof(char));",
+ " }",
+ " channels[i]->modified = 1; /* addq */",
+ " #endif",
+ " channels[i]->psize = j;",
+ " channels[i]->parent_pid = calling_pid;",
+ " channels[i]->nxt = (TRIX_v6 *) 0;",
+ "#else",
" if (vsize >= VECTORSZ)",
" Uerror(\"VECTORSZ is too small, edit pan.h\");",
- " memset((char *)qptr(i), 0, j);",
+ "#endif",
+
+ " if (j > 0)", /* zero if there are no queues */
+ " { memset((char *)qptr(i), 0, j);",
+ " }",
" ((Q0 *)qptr(i))->_t = n;",
" return i+1;",
"}\n",
@@ -353,7 +438,7 @@
0,
};
-static char *Addq11[] = {
+static const char *Addq11[] = {
"{ int j; uchar *z;\n",
"#ifdef HAS_SORTED",
" int k;",
@@ -362,6 +447,19 @@
" uerror(\"ref to uninitialized chan name (sending)\");",
" if (into >= (int) now._nr_qs || into < 0)",
" Uerror(\"qsend bad queue#\");",
+ "#if defined(TRIX) && !defined(BFS)",
+ " #ifndef TRIX_ORIG",
+ " (trpt+1)->q_bup = now._ids_[now._nr_pr+into];",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: channel %%d s save %%p from %%d\\n\",",
+ " depth, into, (trpt+1)->q_bup, now._nr_pr+into);",
+ " #endif",
+ " #endif",
+ " channels[into]->modified = 1; /* qsend */",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: channel %%d modified\\n\", depth, into);",
+ " #endif",
+ "#endif",
" z = qptr(into);",
" j = ((Q0 *)qptr(into))->Qlen;",
" switch (((Q0 *)qptr(into))->_t) {",
@@ -368,7 +466,7 @@
0,
};
-static char *Addq2[] = {
+static const char *Addq2[] = {
" case 0: printf(\"queue %%d was deleted\\n\", into+1);",
" default: Uerror(\"bad queue - qsend\");",
" }",
@@ -389,7 +487,7 @@
0,
};
-static char *Addq3[] = {
+static const char *Addq3[] = {
" case 0: printf(\"queue %%d was deleted\\n\", from+1);",
" }",
" Uerror(\"bad queue q-zero\");",
@@ -449,7 +547,11 @@
"short q_recver[MAXQ+1];",
"int",
"q_R_check(int x, int who)",
- "{ if (!q_recver[x])",
+ "{",
+ "#ifdef VERBOSE",
+ " printf(\"q_R_check x=%%d who=%%d\\n\", x, who);",
+ "#endif",
+ " if (!q_recver[x])",
" { q_recver[x] = who+1;",
"#if SYNC",
" if (q_zero(x))",
@@ -489,7 +591,7 @@
0,
};
-static char *Addq4[] = {
+static const char *Addq4[] = {
" case 0: printf(\"queue %%d was deleted\\n\", from+1);",
" }",
" Uerror(\"bad queue - q_full\");",
@@ -509,6 +611,19 @@
" int j, k, r=0;\n",
" if (!from--)",
" uerror(\"ref to uninitialized chan name (receiving)\");",
+ "#if defined(TRIX) && !defined(BFS)",
+ " #ifndef TRIX_ORIG",
+ " (trpt+1)->q_bup = now._ids_[now._nr_pr+from];",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: channel %%d r save %%p from %%d\\n\",",
+ " depth, from, (trpt+1)->q_bup, now._nr_pr+from);",
+ " #endif",
+ " #endif",
+ " channels[from]->modified = 1; /* qrecv */",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: channel %%d modified\\n\", depth, from);",
+ " #endif",
+ "#endif",
" if (from >= (int) now._nr_qs || from < 0)",
" Uerror(\"qrecv bad queue#\");",
" z = qptr(from);",
@@ -520,7 +635,7 @@
0,
};
-static char *Addq5[] = {
+static const char *Addq5[] = {
" case 0: printf(\"queue %%d was deleted\\n\", from+1);",
" default: Uerror(\"bad queue - qrecv\");",
" }",
@@ -528,7 +643,7 @@
"}",
"#endif\n",
"#ifndef BITSTATE",
- "#ifdef COLLAPSE",
+ " #ifdef COLLAPSE",
"long",
"col_q(int i, char *z)",
"{ int j=0, k;",
@@ -538,15 +653,22 @@
0,
};
-static char *Code0[] = {
+static const char *Code0[] = {
"void",
"run(void)",
"{ /* int i; */",
" memset((char *)&now, 0, sizeof(State));",
- " vsize = (unsigned long) (sizeof(State) - VECTORSZ);",
+ " vsize = (ulong) (sizeof(State) - VECTORSZ);",
"#ifndef NOVSZ",
" now._vsz = vsize;",
"#endif",
+ "#ifdef TRIX",
+ " if (VECTORSZ != sizeof(now._ids_))",
+ " { printf(\"VECTORSZ is %%d, but should be %%d in this mode\\n\",",
+ " VECTORSZ, (int) sizeof(now._ids_));",
+ " Uerror(\"VECTORSZ set incorrectly, recompile Spin (not pan.c)\");",
+ " }",
+ "#endif",
"/* optional provisioning statements, e.g. to */",
"/* set hidden variables, used as constants */",
"#ifdef PROV",
@@ -556,98 +678,117 @@
0,
};
-static char *R0[] = {
- " Maxbody = max(Maxbody, sizeof(P%d));",
+static const char *R0[] = {
+ " Maxbody = max(Maxbody, ((int) sizeof(P%d)));",
" reached[%d] = reached%d;",
- " accpstate[%d] = (uchar *) emalloc(nstates%d);",
- " progstate[%d] = (uchar *) emalloc(nstates%d);",
- " stopstate[%d] = (uchar *) emalloc(nstates%d);",
- " visstate[%d] = (uchar *) emalloc(nstates%d);",
- " mapstate[%d] = (short *) emalloc(nstates%d * sizeof(short));",
- "#ifdef HAS_CODE",
- " NrStates[%d] = nstates%d;",
- "#endif",
- " stopstate[%d][endstate%d] = 1;",
+ " accpstate[%d] = (uchar *) emalloc(_nstates%d);",
+ " progstate[%d] = (uchar *) emalloc(_nstates%d);",
+ " loopstate%d = loopstate[%d] = (uchar *) emalloc(_nstates%d);",
+ " stopstate[%d] = (uchar *) emalloc(_nstates%d);",
+ " visstate[%d] = (uchar *) emalloc(_nstates%d);",
+ " mapstate[%d] = (short *) emalloc(_nstates%d * sizeof(short));",
+ " stopstate[%d][_endstate%d] = 1;",
0,
};
-static char *R0a[] = {
- " retrans(%d, nstates%d, start%d, src_ln%d, reached%d);",
+static const char *R00[] = {
+ " NrStates[%d] = _nstates%d;",
0,
};
-static char *R0b[] = {
- " if (state_tables)",
- " { printf(\"\\nTransition Type: \");",
- " printf(\"A=atomic; D=d_step; L=local; G=global\\n\");",
- " printf(\"Source-State Labels: \");",
- " printf(\"p=progress; e=end; a=accept;\\n\");",
- "#ifdef MERGED",
- " printf(\"Note: statement merging was used. Only the first\\n\");",
- " printf(\" stmnt executed in each merge sequence is shown\\n\");",
- " printf(\" (use spin -a -o3 to disable statement merging)\\n\");",
- "#endif",
- " pan_exit(0);",
- " }",
+
+static const char *R0a[] = {
+ " retrans(%d, _nstates%d, _start%d, src_ln%d, reached%d, loopstate%d);",
0,
};
-static char *Code1[] = {
+static const char *Code1[] = {
"#ifdef NP",
- "#define ACCEPT_LAB 1 /* at least 1 in np_ */",
+ " #define ACCEPT_LAB 1 /* at least 1 in np_ */",
"#else",
- "#define ACCEPT_LAB %d /* user-defined accept labels */",
+ " #define ACCEPT_LAB %d /* user-defined accept labels */",
"#endif",
+ "#ifdef MEMCNT",
+ " #ifdef MEMLIM",
+ " #warning -DMEMLIM takes precedence over -DMEMCNT",
+ " #undef MEMCNT",
+ " #else",
+ " #if MEMCNT<20",
+ " #warning using minimal value -DMEMCNT=20 (=1MB)",
+ " #define MEMLIM (1)",
+ " #undef MEMCNT",
+ " #else",
+ " #if MEMCNT==20",
+ " #define MEMLIM (1)",
+ " #undef MEMCNT",
+ " #else",
+ " #if MEMCNT>=50",
+ " #error excessive value for MEMCNT",
+ " #else",
+ " #define MEMLIM (1<<(MEMCNT-20))",
+ " #endif",
+ " #endif",
+ " #endif",
+ " #endif",
+ "#endif",
+
+ "#if NCORE>1 && !defined(MEMLIM)",
+ " #define MEMLIM (2048) /* need a default, using 2 GB */",
+ "#endif",
0,
};
-static char *Code3[] = {
+static const char *Code3[] = {
"#define PROG_LAB %d /* progress labels */",
0,
};
-static char *R2[] = {
+static const char *R2[] = {
"uchar *accpstate[%d];",
"uchar *progstate[%d];",
+ "uchar *loopstate[%d];",
"uchar *reached[%d];",
"uchar *stopstate[%d];",
"uchar *visstate[%d];",
"short *mapstate[%d];",
"#ifdef HAS_CODE",
- "int NrStates[%d];",
+ " int NrStates[%d];",
"#endif",
0,
};
-static char *R3[] = {
- " Maxbody = max(Maxbody, sizeof(Q%d));",
+static const char *R3[] = {
+ " Maxbody = max(Maxbody, ((int) sizeof(Q%d)));",
0,
};
-static char *R4[] = {
- " r_ck(reached%d, nstates%d, %d, src_ln%d, src_file%d);",
+static const char *R4[] = {
+ " r_ck(reached%d, _nstates%d, %d, src_ln%d, src_file%d);",
0,
};
-static char *R5[] = {
+static const char *R5[] = {
" case %d: j = sizeof(P%d); break;",
0,
};
-static char *R6[] = {
+static const char *R6[] = {
" }",
" this = o_this;",
+ "#ifdef TRIX",
+ " re_mark_all(1); /* addproc */",
+ "#endif",
" return h-BASE;",
"#ifndef NOBOUNDCHECK",
- "#undef Index",
- "#define Index(x, y) Boundcheck(x, y, II, tt, t)",
+ " #undef Index",
+ " #define Index(x, y) Boundcheck(x, y, II, tt, t)",
"#endif",
"}\n",
"#if defined(BITSTATE) && defined(COLLAPSE)",
- "/* just to allow compilation, to generate the error */",
- "long col_p(int i, char *z) { return 0; }",
- "long col_q(int i, char *z) { return 0; }",
+ " /* just to allow compilation, to generate the error */",
+ " long col_p(int i, char *z) { return 0; }",
+ " long col_q(int i, char *z) { return 0; }",
"#endif",
"#ifndef BITSTATE",
- "#ifdef COLLAPSE",
+ " #ifdef COLLAPSE",
"long",
"col_p(int i, char *z)",
- "{ int j, k; unsigned long ordinal(char *, long, short);",
+ "{ int j, k; ulong ordinal(char *, long, short);",
" char *x, *y;",
" P0 *ptr = (P0 *) pptr(i);",
" switch (ptr->_t) {",
@@ -654,15 +795,150 @@
" case 0: j = sizeof(P0); break;",
0,
};
-static char *R8a[] = {
+static const char *R7a[] = {
+ "void\nre_mark_all(int whichway)",
+ "{ int j;",
+ " #ifdef V_TRIX",
+ " printf(\"%%d: re_mark_all channels %%d\\n\", depth, whichway);",
+ " #endif",
+ " #ifndef BFS",
+ " for (j = 0; j < now._nr_qs; j++)",
+ " channels[j]->modified = 1; /* channel index moved */",
+ " #endif",
+ " #ifndef TRIX_ORIG",
+ " if (whichway > 0)",
+ " { for (j = now._nr_pr + now._nr_qs - 1; j >= now._nr_pr; j--)",
+ " now._ids_[j] = now._ids_[j-1];",
+ " } else",
+ " { for (j = now._nr_pr; j < now._nr_pr + now._nr_qs; j++)",
+ " now._ids_[j] = now._ids_[j+1];",
+ " }",
+ " #endif",
+ "}",
+ 0,
+};
+
+static const char *R7b[] = {
+ "#ifdef BFS_PAR",
+ "inline void",
+ "bfs_prepmask(int caller)",
+ "{",
+ "#if !defined(NOCOMP) && !defined(HC)",
+ " memcpy((char *) &tmp_msk, (const char *) Mask, sizeof(State));",
+ " Mask = (uchar *) &tmp_msk;",
+ "#endif",
+ " switch (caller) {",
+ " case 1: /* addproc */",
+ "#if VECTORSZ>32000",
+ " memcpy((char *) P_o_tmp, (const char *) proc_offset, MAXPROC*sizeof(int));",
+ "#else",
+ " memcpy((char *) P_o_tmp, (const char *) proc_offset, MAXPROC*sizeof(short));",
+ "#endif",
+ " memcpy((char *) P_s_tmp, (const char *) proc_skip, MAXPROC*sizeof(uchar));",
+ " proc_offset = P_o_tmp;",
+ " proc_skip = (uchar *) &P_s_tmp[0];",
+ " break;",
+ " case 2: /* addqueue */",
+ "#if VECTORSZ>32000",
+ " memcpy((char *) Q_o_tmp, (const char *) q_offset, MAXQ*sizeof(int));",
+ "#else",
+ " memcpy((char *) Q_o_tmp, (const char *) q_offset, MAXQ*sizeof(short));",
+ "#endif",
+ " memcpy((char *) Q_s_tmp, (const char *) q_skip, MAXQ*sizeof(uchar));",
+ " q_offset = Q_o_tmp;",
+ " q_skip = (uchar *) &Q_s_tmp[0];",
+ " break;",
+ " case 3: /* no nothing */",
+ " break;",
+ " default: /* cannot happen */",
+ " Uerror(\"no good\");",
+ " break;",
+ " }",
+ "}",
+ "",
+ "typedef struct BFS_saves BFS_saves;",
+ "struct BFS_saves {",
+ " char *m;",
+ " BFS_saves *nxt;",
+ "} *bfs_save_po,",
+ " *bfs_save_ps,",
+ "#if !defined(NOCOMP) && !defined(HC)",
+ " *bfs_save_mask,",
+ "#endif",
+ " *bfs_save_qo,",
+ " *bfs_save_qs;",
+ "",
+ "extern volatile uchar *sh_malloc(ulong);",
+ "static int bfs_runs; /* 0 before local heaps are initialized */",
+ "",
+ "void",
+ "bfs_swoosh(BFS_saves **where, char **what, int howmuch)",
+ "{ BFS_saves *m;",
+ " for (m = *where; m; m = m->nxt)",
+ " { if (memcmp(m->m, *what, howmuch) == 0)",
+ " { *what = m->m;",
+ " return;",
+ " } }",
+ " m = (BFS_saves *) emalloc(sizeof(BFS_saves));",
+ " if (bfs_runs)",
+ " { m->m = (char *) sh_malloc(howmuch);",
+ " } else",
+ " { m->m = (char *) sh_pre_malloc(howmuch);",
+ " }",
+ " memcpy(m->m, *what, howmuch);",
+ " m->nxt = *where;",
+ " *where = m;",
+ " *what = m->m;",
+ "}",
+ "",
+ "void",
+ "bfs_fixmask(int caller)", /* 1=addproc, 2=addqueue */
+ "{",
+ "#if !defined(NOCOMP) && !defined(HC)",
+ " bfs_swoosh(&bfs_save_mask, (char **) &Mask, sizeof(State));",
+ "#endif",
+ "#ifndef TRIX",
+ " switch (caller) {",
+ " case 1: /* addproc */",
+ " #if VECTORSZ>32000",
+ " bfs_swoosh(&bfs_save_po, (char **) &proc_offset, MAXPROC*sizeof(int));",
+ " #else",
+ " bfs_swoosh(&bfs_save_po, (char **) &proc_offset, MAXPROC*sizeof(short));",
+ " #endif",
+ " bfs_swoosh(&bfs_save_ps, (char **) &proc_skip, MAXPROC*sizeof(uchar));",
+ " break;",
+ " case 2: /* addqueue */",
+ " #if VECTORSZ>32000",
+ " bfs_swoosh(&bfs_save_qo, (char **) &q_offset, MAXQ*sizeof(int));",
+ " #else",
+ " bfs_swoosh(&bfs_save_qo, (char **) &q_offset, MAXQ*sizeof(short));",
+ " #endif",
+ " bfs_swoosh(&bfs_save_qs, (char **) &q_skip, MAXQ*sizeof(uchar));",
+ " break;",
+ " case 3: /* do nothing */",
+ " break;",
+ " default:",
+ " Uerror(\"double plus ungood\");",
+ " break;",
+ " }",
+ "#endif",
+ "}",
+ "#endif",
+ 0,
+};
+static const char *R8a[] = {
" default: Uerror(\"bad proctype - collapse\");",
" }",
" if (z) x = z; else x = scratch;",
" y = (char *) ptr; k = proc_offset[i];",
-
+ "",
+ "#if !defined(NOCOMP) && !defined(HC)",
" for ( ; j > 0; j--, y++)",
" if (!Mask[k++]) *x++ = *y;",
-
+ "#else",
+ " memcpy(x, y, j);",
+ " x += j;",
+ "#endif",
" for (j = 0; j < WS-1; j++)",
" *x++ = 0;",
" x -= j;",
@@ -669,22 +945,28 @@
" if (z) return (long) (x - z);",
" return ordinal(scratch, x-scratch, (short) (2+ptr->_t));",
"}",
+ " #endif",
"#endif",
- "#endif",
0,
};
-static char *R8b[] = {
+static const char *R8b[] = {
" default: Uerror(\"bad qtype - collapse\");",
" }",
" if (z) x = z; else x = scratch;",
" y = (char *) ptr; k = q_offset[i];",
+ "#if NQS > 0",
" /* no need to store the empty slots at the end */",
" j -= (q_max[ptr->_t] - ptr->Qlen) * ((j - 2)/q_max[ptr->_t]);",
-
+ "#endif",
+ "",
+ "#if !defined(NOCOMP) && !defined(HC)",
" for ( ; j > 0; j--, y++)",
" if (!Mask[k++]) *x++ = *y;",
-
+ "#else",
+ " memcpy(x, y, j);",
+ " x += j;",
+ "#endif",
" for (j = 0; j < WS-1; j++)",
" *x++ = 0;",
" x -= j;",
@@ -691,16 +973,16 @@
" if (z) return (long) (x - z);",
" return ordinal(scratch, x-scratch, 1); /* chan */",
"}",
+ " #endif",
"#endif",
- "#endif",
0,
};
-static char *R12[] = {
+static const char *R12[] = {
"\t\tcase %d: r = ((Q%d *)z)->contents[slot].fld%d; break;",
0,
};
-char *R13[] = {
+const char *R13[] = {
"int ",
"unsend(int into)",
"{ int _m=0, j; uchar *z;\n",
@@ -709,6 +991,20 @@
"#endif",
" if (!into--)",
" uerror(\"ref to uninitialized chan (unsend)\");",
+ "#if defined(TRIX) && !defined(BFS)",
+ " #ifndef TRIX_ORIG",
+ " now._ids_[now._nr_pr+into] = trpt->q_bup;",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: channel %%d s restore %%p into %%d\\n\",",
+ " depth, into, trpt->q_bup, now._nr_pr+into);",
+ " #endif",
+ " #else",
+ " channels[into]->modified = 1; /* unsend */",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: channel %%d unmodify\\n\", depth, into);",
+ " #endif",
+ " #endif",
+ "#endif",
" z = qptr(into);",
" j = ((Q0 *)z)->Qlen;",
" ((Q0 *)z)->Qlen = --j;",
@@ -715,7 +1011,7 @@
" switch (((Q0 *)qptr(into))->_t) {",
0,
};
-char *R14[] = {
+const char *R14[] = {
" default: Uerror(\"bad queue - unsend\");",
" }",
" return _m;",
@@ -725,6 +1021,20 @@
"{ int j; uchar *z;\n",
" if (!from--)",
" uerror(\"ref to uninitialized chan (unrecv)\");",
+ "#if defined(TRIX) && !defined(BFS)",
+ " #ifndef TRIX_ORIG",
+ " now._ids_[now._nr_pr+from] = trpt->q_bup;",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: channel %%d r restore %%p into %%d\\n\",",
+ " depth, from, trpt->q_bup, now._nr_pr+from);",
+ " #endif",
+ " #else",
+ " channels[from]->modified = 1; /* unrecv */",
+ " #ifdef V_TRIX",
+ " printf(\"%%4d: channel %%d unmodify\\n\", depth, from);",
+ " #endif",
+ " #endif",
+ "#endif",
" z = qptr(from);",
" j = ((Q0 *)z)->Qlen;",
" if (strt) ((Q0 *)z)->Qlen = j+1;",
@@ -731,34 +1041,33 @@
" switch (((Q0 *)qptr(from))->_t) {",
0,
};
-char *R15[] = {
+const char *R15[] = {
" default: Uerror(\"bad queue - qrecv\");",
" }",
"}",
0,
};
-static char *Proto[] = {
+static const char *Proto[] = {
"",
"/** function prototypes **/",
- "char *emalloc(unsigned long);",
- "char *Malloc(unsigned long);",
+ "char *emalloc(ulong);",
+ "char *Malloc(ulong);",
"int Boundcheck(int, int, int, int, Trans *);",
- "int addqueue(int, int);",
+ "int addqueue(int, int, int);",
"/* int atoi(char *); */",
"/* int abort(void); */",
"int close(int);", /* should probably remove this */
#if 0
"#ifndef SC",
- "int creat(char *, unsigned short);",
- "int write(int, void *, unsigned);",
+ " int creat(char *, unsigned short);",
+ " int write(int, void *, unsigned);",
"#endif",
#endif
"int delproc(int, int);",
"int endstate(void);",
- "int hstore(char *, int);",
-"#ifdef MA",
- "int gstore(char *, int, uchar);",
-"#endif",
+ "int find_claim(char *);",
+ "int h_store(char *, int);",
+ "int pan_rand(void);",
"int q_cond(short, Trans *);",
"int q_full(int);",
"int q_len(int);",
@@ -766,21 +1075,33 @@
"int qrecv(int, int, int, int);",
"int unsend(int);",
"/* void *sbrk(int); */",
- "void Uerror(char *);",
- "void assert(int, char *, int, int, Trans *);",
+ "void spin_assert(int, char *, int, int, Trans *);",
+ "#ifdef BFS_PAR",
+ "void bfs_printf(const char *, ...);",
+ "volatile uchar *sh_pre_malloc(ulong);",
+ "#endif",
"void c_chandump(int);",
"void c_globals(void);",
"void c_locals(int, int);",
"void checkcycles(void);",
"void crack(int, int, Trans *, short *);",
+ "void d_sfh(uchar *, int);",
"void d_hash(uchar *, int);",
+ "void m_hash(uchar *, int);",
"void s_hash(uchar *, int);",
- "void r_hash(uchar *, int);",
"void delq(int);",
+ "void dot_crack(int, int, Trans *);",
"void do_reach(void);",
"void pan_exit(int);",
"void exit(int);",
- "void hinit(void);",
+ "#ifdef BFS_PAR",
+ " void bfs_setup_mem(void);",
+ "#endif",
+ "#ifdef BITSTATE",
+ " void sinit(void);",
+ "#else",
+ " void hinit(void);",
+ "#endif",
"void imed(Trans *, int, int, int);",
"void new_state(void);",
"void p_restor(int);",
@@ -787,44 +1108,320 @@
"void putpeg(int, int);",
"void putrail(void);",
"void q_restor(void);",
- "void retrans(int, int, int, short *, uchar *);",
+ "void retrans(int, int, int, short *, uchar *, uchar *);",
+ "void select_claim(int);",
"void settable(void);",
"void setq_claim(int, int, char *, int, char *);",
"void sv_restor(void);",
"void sv_save(void);",
"void tagtable(int, int, int, short *, uchar *);",
- "void uerror(char *);",
+ "void do_dfs(int, int, int, short *, uchar *, uchar *);",
"void unrecv(int, int, int, int, int);",
"void usage(FILE *);",
- "void wrap_stats(void);",
+ "void wrap_stats(void);\n",
+ "#ifdef MA",
+ " int g_store(char *, int, uchar);",
+ "#endif",
"#if defined(FULLSTACK) && defined(BITSTATE)",
- "int onstack_now(void);",
- "void onstack_init(void);",
- "void onstack_put(void);",
- "void onstack_zap(void);",
+ " int onstack_now(void);",
+ " void onstack_init(void);",
+ " void onstack_put(void);",
+ " void onstack_zap(void);",
"#endif",
"#ifndef XUSAFE",
- "int q_S_check(int, int);",
- "int q_R_check(int, int);",
- "uchar q_claim[MAXQ+1];",
- "char *q_name[MAXQ+1];",
- "char *p_name[MAXPROC+1];",
+ " int q_S_check(int, int);",
+ " int q_R_check(int, int);",
+ " uchar q_claim[MAXQ+1];",
+ " char *q_name[MAXQ+1];",
+ " char *p_name[MAXPROC+1];",
"#endif",
+ "",
+ "#ifndef NO_V_PROVISO",
+ " #define V_PROVISO",
+ "#endif",
+ "#if !defined(NO_RESIZE) && !defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(SPACE) && !defined(USE_TDH) && NCORE==1",
+ " #define AUTO_RESIZE",
+ "#endif",
+ "",
+ "typedef struct Trail Trail;",
+ "typedef struct H_el H_el;",
+ "",
+ "struct H_el {",
+ " H_el *nxt;",
+ " #ifdef FULLSTACK",
+ " unsigned int tagged;",
+ " #if defined(BITSTATE) && !defined(NOREDUCE) && !defined(SAFETY)",
+ " unsigned int proviso;", /* uses just 1 bit 0/1 */
+ " #endif",
+ " #endif",
+ " #if defined(CHECK) || (defined(COLLAPSE) && !defined(FULLSTACK))",
+ " ulong st_id;",
+ " #endif",
+ " #if !defined(SAFETY) || defined(REACH)",
+ " uint D;",
+ " #endif",
+ " #ifdef BCS",
+ " #ifndef CONSERVATIVE",
+ " #define CONSERVATIVE 1 /* good for up to 8 processes */",
+ " #endif",
+ " #ifdef CONSERVATIVE",
+ " #if CONSERVATIVE <= 0 || CONSERVATIVE>32",
+ " #error sensible values for CONSERVATIVE are 1..32 (256/8 = 32)",
+ " #endif",
+ " uchar ctx_pid[CONSERVATIVE];", /* pids setting lowest value */
+ " #endif",
+ " uchar ctx_low;", /* lowest nr of context switches seen so far */
+ " #endif",
+ " #if NCORE>1",
+ " /* could cost 1 extra word: 4 bytes if 32-bit and 8 bytes if 64-bit */",
+ " #ifdef V_PROVISO",
+ " uchar cpu_id; /* id of cpu that created the state */",
+ " #endif",
+ " #endif",
+ " #ifdef COLLAPSE",
+ " #if VECTORSZ<65536",
+ " ushort ln;", /* length of vector */
+ " #else",
+ " ulong ln;", /* length of vector */
+ " #endif",
+ " #endif",
+ " #if defined(AUTO_RESIZE) && !defined(BITSTATE)",
+ " ulong m_K1;",
+ " #endif",
+ " ulong state;",
+ "};",
+ "",
+ "#ifdef BFS_PAR",
+ "typedef struct BFS_Trail BFS_Trail;",
+ "struct BFS_Trail {",
+ " H_el *ostate;",
+ " int st;",
+ " int o_tt;",
+ " T_ID t_id;", /* could be uint, ushort, or uchar */
+ " uchar pr;",
+ " uchar o_pm;",
+ " uchar tau;",
+ "};",
+ " #if SYNC>0",
+ " #undef BFS_NOTRAIL", /* just in case it was used */
+ " #endif",
+ "#endif",
+ "",
+ "#ifdef RHASH",
+ " #ifndef PERMUTED",
+ " #define PERMUTED",
+ " #endif",
+ "#endif",
+ "",
+ "struct Trail {",
+ " int st; /* current state */",
+ " int o_tt;",
+ "#ifdef PERMUTED",
+ " uint seed;",
+ " uchar oII;",
+ "#endif",
+ " uchar pr; /* process id */",
+ " uchar tau; /* 8 bit-flags */",
+ " uchar o_pm; /* 8 more bit-flags */",
+ "",
+ " #if 0",
+ " Meaning of bit-flags on tau and o_pm:",
+ " tau&1 -> timeout enabled",
+ " tau&2 -> request to enable timeout 1 level up (in claim)",
+ " tau&4 -> current transition is a claim move",
+ " tau&8 -> current transition is an atomic move",
+ " tau&16 -> last move was truncated on stack",
+ " tau&32 -> current transition is a preselected move",
+ " tau&64 -> at least one next state is not on the stack",
+ " tau&128 -> current transition is a stutter move",
+
+ " o_pm&1 -> the current pid moved -- implements else",
+ " o_pm&2 -> this is an acceptance state",
+ " o_pm&4 -> this is a progress state",
+ " o_pm&8 -> fairness alg rule 1 undo mark",
+ " o_pm&16 -> fairness alg rule 3 undo mark",
+ " o_pm&32 -> fairness alg rule 2 undo mark",
+ " o_pm&64 -> the current proc applied rule2",
+ " o_pm&128 -> a fairness, dummy move - all procs blocked",
+ " #endif",
+ "",
+ " #ifdef NSUCC",
+ " uchar n_succ; /* nr of successor states */",
+ " #endif",
+ " #if defined(FULLSTACK) && defined(MA) && !defined(BFS)",
+ " uchar proviso;",
+ " #endif",
+ " #ifndef BFS",
+ " uchar o_n, o_ot; /* to save locals */",
+ " #endif",
+ " uchar o_m;",
+ " #ifdef EVENT_TRACE",
+ " #if nstates_event<256",
+ " uchar o_event;",
+ " #else",
+ " unsigned short o_event;",
+ " #endif",
+ " #endif",
+ " #ifndef BFS",
+ " short o_To;",
+ " #if defined(T_RAND) || defined(RANDOMIZE)",
+ " short oo_i;",
+ " #endif",
+ " #endif",
+ " #if defined(HAS_UNLESS) && !defined(BFS)",
+ " int e_state; /* if escape trans - state of origin */",
+ " #endif",
+ " #if (defined(FULLSTACK) && !defined(MA)) || defined(BFS) || (NCORE>1)",
+ " H_el *ostate; /* pointer to stored state */",
+ " #endif",
+ /* CNTRSTACK when !NOREDUCE && BITSTATE && SAFETY && WS<=4, uses LL[] */
+ " #if defined(CNTRSTACK) && !defined(BFS)",
+ " long j6, j7;",
+ " #endif",
+ " Trans *o_t;", /* transition fct, next state */
+
+ " #if !defined(BFS) && !defined(TRIX_ORIG)",
+ " char *p_bup;",
+ " char *q_bup;",
+ " #endif",
+
+ " #ifdef BCS",
+ " unsigned short sched_limit;",
+ " unsigned char bcs; /* phase 1 or 2, or forced 4 */",
+ " unsigned char b_pno; /* preferred pid */",
+ " #endif",
+
+ " #ifdef P_RAND", /* process scheduling randomization */
+ " unsigned char p_left; /* nr of procs left to explore */",
+ " short p_skip; /* to find starting point in list */",
+ " #endif",
+
+ " #ifdef HAS_SORTED",
+ " short ipt;", /* insertion slot in q */
+ " #endif",
+ " #ifdef HAS_PRIORITY",
+ " short o_priority;",
+ " #endif",
+ " union {",
+ " int oval;", /* single backup value of variable */
+ " int *ovals;", /* ptr to multiple values */
+ " } bup;",
+ "}; /* end of struct Trail */",
+ "",
+ "#ifdef BFS", /* breadth-first search */
+ " #define Q_PROVISO",
+ " #ifndef INLINE_REV",
+ " #define INLINE_REV",
+ " #endif",
+ "",
+ "typedef struct SV_Hold {",
+ " State *sv;",
+ " #ifndef BFS_PAR",
+ " int sz;",
+ " #endif",
+ " struct SV_Hold *nxt;",
+ "} SV_Hold;",
+ "#if !defined(BFS_PAR) || NRUNS>0",
+ " typedef struct EV_Hold {",
+ " #if !defined(BFS_PAR) || (!defined(NOCOMP) && !defined(HC) && NRUNS>0)",
+ " char *sv; /* Mask */",
+ " #endif",
+ " #if VECTORSZ<65536",
+ " ushort sz; /* vsize */",
+ " #else",
+ " ulong sz;",
+ " #endif",
+ " #ifdef BFS_PAR",
+ " uchar owner;",
+ " #endif",
+ " uchar nrpr;",
+ " uchar nrqs;",
+ " #if !defined(BFS_PAR) || (!defined(TRIX) && NRUNS>0)",
+ " char *po, *qo;",
+ " char *ps, *qs;",
+ " #endif",
+ " struct EV_Hold *nxt;",
+ " } EV_Hold;",
+ "#endif",
+ "typedef struct BFS_State {",
+ " #ifdef BFS_PAR",
+ " BFS_Trail *t_info;",
+ " State *osv;",
+ " #else",
+ " Trail *frame;",
+ " SV_Hold *onow;",
+ " #endif",
+ " #if !defined(BFS_PAR) || NRUNS>0",
+ " EV_Hold *omask;",
+ " #endif",
+ " #if defined(Q_PROVISO) && !defined(NOREDUCE)",
+ " H_el *lstate;",
+ " #endif",
+ " #if !defined(BFS_PAR) || SYNC>0",
+ " short boq;",
+ " #endif",
+ " #ifdef VERBOSE",
+ " ulong nr;",
+ " #endif",
+ " #ifndef BFS_PAR", /* new 6.2.4, 3 dec 2012 */
+ " struct BFS_State *nxt;",
+ " #endif",
+ "} BFS_State;",
+ "#endif\n",
0,
};
-static char *SvMap[] = {
+static const char *SvMap[] = {
"void",
"to_compile(void)",
- "{ char ctd[1024], carg[64];",
+ "{ char ctd[2048], carg[128];",
"#ifdef BITSTATE",
" strcpy(ctd, \"-DBITSTATE \");",
"#else",
" strcpy(ctd, \"\");",
"#endif",
+ "#ifdef BFS_PAR",
+ " strcat(ctd, \"-DBFS_PAR \");",
+ "#endif",
"#ifdef NOVSZ",
" strcat(ctd, \"-DNOVSZ \");",
"#endif",
+ "#ifdef RHASH",
+ " strcat(ctd, \"-DRHASH \");",
+ "#else",
+ " #ifdef PERMUTED",
+ " strcat(ctd, \"-DPERMUTED \");",
+ " #endif",
+ "#endif",
+ "#ifdef P_REVERSE",
+ " strcat(ctd, \"-DP_REVERSE \");",
+ "#endif",
+ "#ifdef T_REVERSE",
+ " strcat(ctd, \"-DT_REVERSE \");",
+ "#endif",
+ "#ifdef T_RAND",
+ " #if T_RAND>0",
+ " sprintf(carg, \"-DT_RAND=%%d \", T_RAND);",
+ " strcat(ctd, carg);",
+ " #else",
+ " strcat(ctd, \"-DT_RAND \");",
+ " #endif",
+ "#endif",
+ "#ifdef P_RAND",
+ " #if P_RAND>0",
+ " sprintf(carg, \"-DP_RAND=%%d \", P_RAND);",
+ " strcat(ctd, carg);",
+ " #else",
+ " strcat(ctd, \"-DP_RAND \");",
+ " #endif",
+ "#endif",
+ "#ifdef BCS",
+ " sprintf(carg, \"-DBCS=%%d \", BCS);",
+ " strcat(ctd, carg);",
+ "#endif",
+ "#ifdef BFS",
+ " strcat(ctd, \"-DBFS \");",
+ "#endif",
"#ifdef MEMLIM",
" sprintf(carg, \"-DMEMLIM=%%d \", MEMLIM);",
" strcat(ctd, carg);",
@@ -867,21 +1464,9 @@
"#ifdef VAR_RANGES",
" strcat(ctd, \"-DVAR_RANGES \");",
"#endif",
- "#ifdef HC0",
- " strcat(ctd, \"-DHC0 \");",
+ "#ifdef HC",
+ " strcat(ctd, \"-DHC \");",
"#endif",
- "#ifdef HC1",
- " strcat(ctd, \"-DHC1 \");",
- "#endif",
- "#ifdef HC2",
- " strcat(ctd, \"-DHC2 \");",
- "#endif",
- "#ifdef HC3",
- " strcat(ctd, \"-DHC3 \");",
- "#endif",
- "#ifdef HC4",
- " strcat(ctd, \"-DHC4 \");",
- "#endif",
"#ifdef CHECK",
" strcat(ctd, \"-DCHECK \");",
"#endif",
@@ -888,6 +1473,9 @@
"#ifdef CTL",
" strcat(ctd, \"-DCTL \");",
"#endif",
+ "#ifdef TRIX",
+ " strcat(ctd, \"-DTRIX \");",
+ "#endif",
"#ifdef NIBIS",
" strcat(ctd, \"-DNIBIS \");",
"#endif",
@@ -903,9 +1491,6 @@
"#ifdef PRINTF",
" strcat(ctd, \"-DPRINTF \");",
"#endif",
- "#ifdef OTIM",
- " strcat(ctd, \"-DOTIM \");",
- "#endif",
"#ifdef COLLAPSE",
" strcat(ctd, \"-DCOLLAPSE \");",
"#endif",
@@ -916,7 +1501,7 @@
"#ifdef SVDUMP",
" strcat(ctd, \"-DSVDUMP \");",
"#endif",
- "#ifdef VECTORSZ",
+ "#if defined(VECTORSZ) && !defined(TRIX)",
" if (VECTORSZ != 1024)",
" { sprintf(carg, \"-DVECTORSZ=%%d \", VECTORSZ);",
" strcat(ctd, carg);",
@@ -931,8 +1516,31 @@
"#ifdef SDUMP",
" strcat(ctd, \"-DSDUMP \");",
"#endif",
- "#ifdef COVEST",
- " strcat(ctd, \"-DCOVEST \");",
+ "#if NCORE>1",
+ " sprintf(carg, \"-DNCORE=%%d \", NCORE);",
+ " strcat(ctd, carg);",
+ "#endif",
+ "#ifdef VMAX",
+ " if (VMAX != 256)",
+ " { sprintf(carg, \"-DVMAX=%%d \", VMAX);",
+ " strcat(ctd, carg);",
+ " }",
+ "#endif",
+ "#ifdef PMAX",
+ " if (PMAX != 16)",
+ " { sprintf(carg, \"-DPMAX=%%d \", PMAX);",
+ " strcat(ctd, carg);",
+ " }",
+ "#endif",
+ "#ifdef QMAX",
+ " if (QMAX != 16)",
+ " { sprintf(carg, \"-DQMAX=%%d \", QMAX);",
+ " strcat(ctd, carg);",
+ " }",
+ "#endif",
+ "#ifdef SET_WQ_SIZE",
+ " sprintf(carg, \"-DSET_WQ_SIZE=%%d \", SET_WQ_SIZE);",
+ " strcat(ctd, carg);",
"#endif",
" printf(\"Compiled as: cc -o pan %%span.c\\n\", ctd);",
"}",
--- a/sys/src/cmd/spin/pangen4.c
+++ b/sys/src/cmd/spin/pangen4.c
@@ -1,13 +1,10 @@
/***** spin: pangen4.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include "spin.h"
#include "y.tab.h"
@@ -17,7 +14,7 @@
extern Symbol *Fname;
extern int lineno, m_loss, Pid, eventmapnr, multi_oval;
extern short nocast, has_provided, has_sorted;
-extern char *R13[], *R14[], *R15[];
+extern const char *R13[], *R14[], *R15[];
static void check_proc(Lextok *, int);
@@ -44,7 +41,7 @@
case FULL: case EMPTY: case 'R':
case NFULL: case NEMPTY: case ENABLED:
case '?': case PC_VAL: case '^':
- case C_EXPR:
+ case C_EXPR: case GET_P:
case NONPROGRESS:
putstmnt(tb, now, m);
break;
@@ -153,7 +150,14 @@
fprintf(tb, "p_restor(II);\n\t\t");
break;
+ case SET_P:
+ fprintf(tb, "((P0 *)pptr((trpt->o_priority >> 8)))");
+ fprintf(tb, "->_priority = trpt->o_priority & 255");
+ break;
+
case ASGN:
+ if (check_track(now) == STRUCT) { break; }
+
nocast=1; putstmnt(tb,now->lft,m);
nocast=0; fprintf(tb, " = trpt->bup.oval");
if (multi_oval > 0)
@@ -307,6 +311,8 @@
ntimes(tc, 0, 1, R15);
}
+extern void explain(int);
+
int
proper_enabler(Lextok *n)
{
@@ -317,15 +323,19 @@
case LEN: case 'R':
case NAME:
has_provided = 1;
- if (strcmp(n->sym->name, "_pid") == 0)
+ if (strcmp(n->sym->name, "_pid") == 0
+ || strcmp(n->sym->name, "_priority") == 0)
return 1;
return (!(n->sym->context));
- case CONST: case TIMEOUT:
+ case C_EXPR:
+ case CONST:
+ case TIMEOUT:
has_provided = 1;
return 1;
case ENABLED: case PC_VAL:
+ case GET_P: /* not SET_P */
return proper_enabler(n->lft);
case '!': case UMIN: case '~':
@@ -335,10 +345,14 @@
case '%': case LT: case GT: case '&': case '^':
case '|': case LE: case GE: case NE: case '?':
case EQ: case OR: case AND: case LSHIFT:
- case RSHIFT: case 'c':
+ case RSHIFT: case 'c': /* case ',': */
return proper_enabler(n->lft) && proper_enabler(n->rgt);
+
default:
break;
}
+ printf("spin: saw ");
+ explain(n->ntyp);
+ printf("\n");
return 0;
}
--- a/sys/src/cmd/spin/pangen4.h
+++ b/sys/src/cmd/spin/pangen4.h
@@ -1,24 +1,21 @@
/***** spin: pangen4.h *****/
-/* Copyright (c) 1997-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * The DFA code below was written by Anuj Puri and Gerard J. Holzmann in
+ * May 1997, and was inspired by earlier work on data compression using
+ * sharing tree data structures and graph-encoded sets by J-Ch. Gregoire
+ * (INRS Telecom, Quebec, Canada) and D.Zampunieris (Univ.Namur, Belgium)
+ * The splay routine code included here is based on the public domain
+ * version written by D. Sleator <sleator@cs.cmu.edu> in 1992.
+ */
-/* The DFA code below was written by Anuj Puri and Gerard J. Holzmann in */
-/* May 1997, and was inspired by earlier work on data compression using */
-/* sharing tree data structures and graph-encoded sets by J-Ch. Gregoire */
-/* (INRS Telecom, Quebec, Canada) and D.Zampunieris (Univ.Namur, Belgium) */
-
-/* The splay routine code included here is based on the public domain */
-/* version written by D. Sleator <sleator@cs.cmu.edu> in 1992. */
-
-static char *Dfa[] = {
+static const char *Dfa[] = {
"#ifdef MA",
+#if 0
"/*",
"#include <stdio.h>",
"#define uchar unsigned char",
@@ -26,6 +23,7 @@
"#define ulong unsigned long",
"#define ushort unsigned short",
"",
+#endif
"#define TWIDTH 256",
"#define HASH(y,n) (n)*(((long)y))",
"#define INRANGE(e,h) ((h>=e->From && h<=e->To)||(e->s==1 && e->S==h))",
@@ -466,7 +464,7 @@
" for (j = 0; j < TWIDTH; j++)",
" for (i = 0; i < dfa_depth+1; i++)",
" cnt += tree_stats(layers[i*TWIDTH+j]);",
- " printf(\"Minimized Automaton:\t%%6d nodes and %%6g edges\\n\",",
+ " printf(\"Minimized Automaton:\t%%6lu nodes and %%6g edges\\n\",",
" nr_states, cnt);",
"}",
"",
--- a/sys/src/cmd/spin/pangen5.c
+++ b/sys/src/cmd/spin/pangen5.c
@@ -1,13 +1,10 @@
/***** spin: pangen5.c *****/
-/* Copyright (c) 1999-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include "spin.h"
#include "y.tab.h"
@@ -140,6 +137,7 @@
|| lt->ntyp == C_CODE
|| lt->ntyp == C_EXPR
|| has_lab(el, 0) /* any label at all */
+ || lt->ntyp == SET_P /* to prevent multiple set_p merges */
|| lt->ntyp == DO
|| lt->ntyp == UNLESS
@@ -211,13 +209,18 @@
static int
build_step(FSM_trans *v)
{ FSM_state *f;
- Element *el = v->step;
+ Element *el;
#if 0
Lextok *lt = ZN;
#endif
- int st = v->to;
+ int st;
int r;
+ if (!v) return -1;
+
+ el = v->step;
+ st = v->to;
+
if (!el) return -1;
if (v->step->merge)
@@ -234,9 +237,7 @@
lt = v->step->n;
if (verbose&32)
{ if (++howdeep == 1)
- printf("spin: %s, line %3d, merge:\n",
- lt->fn->name,
- lt->ln);
+ printf("spin: %s:%d, merge:\n", lt->fn->name, lt->ln);
printf("\t[%d] <seqno %d>\t", howdeep, el->seqno);
comment(stdout, lt, 0);
printf(";\n");
@@ -257,7 +258,7 @@
}
static void
-FSM_MERGER(char *pname_unused) /* find candidates for safely merging steps */
+FSM_MERGER(/* char *pname */ void) /* find candidates for safely merging steps */
{ FSM_state *f, *g;
FSM_trans *t;
Lextok *lt;
@@ -281,7 +282,7 @@
continue;
g = fsm_tbl[t->to];
- if (!eligible(g->t))
+ if (!g || !eligible(g->t))
{
#define SINGLES
#ifdef SINGLES
@@ -288,7 +289,7 @@
t->step->merge_single = t->to;
#if 0
if ((verbose&32))
- { printf("spin: %s, line %3d, merge_single:\n\t<seqno %d>\t",
+ { printf("spin: %s:%d, merge_single:\n\t<seqno %d>\t",
t->step->n->fn->name,
t->step->n->ln,
t->step->seqno);
@@ -321,14 +322,17 @@
lt = t->step->n;
#if 0
4.1.3:
- an rv send operation inside an atomic, *loses* atomicity
- when executed
- and should therefore never be merged with a subsequent
+ an rv send operation ('s') inside an atomic, *loses* atomicity
+ when executed, and should therefore never be merged with a subsequent
statement within the atomic sequence
- the same is not true for non-rv send operations
+ the same is not true for non-rv send operations;
+ 6.2.2:
+ RUN statements can start a new process at a higher priority level
+ which interferes with statement merging, so it too is not a suitable
+ merge target
#endif
- if (lt->ntyp == 'c' /* potentially blocking stmnts */
+ if ((lt->ntyp == 'c' && !any_oper(lt->lft, RUN)) /* 2nd clause 6.2.2 */
|| lt->ntyp == 'r'
|| (lt->ntyp == 's' && u_sync == 0)) /* added !u_sync in 4.1.3 */
{ if (!canfill_in(t)) /* atomic, non-global, etc. */
@@ -346,9 +350,8 @@
#if 0
if ((verbose&32)
&& t->step->merge_start)
- { printf("spin: %s, line %3d, merge_START:\n\t<seqno %d>\t",
- lt->fn->name,
- lt->ln,
+ { printf("spin: %s:%d, merge_START:\n\t<seqno %d>\t",
+ lt->fn->name, lt->ln,
t->step->seqno);
comment(stdout, lt, 0);
printf(";\n");
@@ -532,6 +535,7 @@
if (now->sym->name[0] == '_'
&& (strcmp(now->sym->name, "_") == 0
|| strcmp(now->sym->name, "_pid") == 0
+ || strcmp(now->sym->name, "_priority") == 0
|| strcmp(now->sym->name, "_last") == 0))
return;
@@ -588,10 +592,17 @@
case C_EXPR:
break;
+ case ',': /* reached with SET_P and array initializers */
+ if (now->lft && now->lft->rgt)
+ { ana_stmnt(t, now->lft->rgt, RVAL);
+ }
+ break;
+
case '!':
case UMIN:
case '~':
case ENABLED:
+ case GET_P:
case PC_VAL:
case LEN:
case FULL:
@@ -603,6 +614,11 @@
ana_stmnt(t, now->lft, RVAL);
break;
+ case SET_P:
+ ana_stmnt(t, now->lft, RVAL); /* ',' */
+ ana_stmnt(t, now->lft->rgt, RVAL);
+ break;
+
case '/':
case '*':
case '-':
@@ -626,8 +642,11 @@
break;
case ASGN:
+ if (check_track(now) == STRUCT) { break; }
+
ana_stmnt(t, now->lft, LVAL);
- ana_stmnt(t, now->rgt, RVAL);
+ if (now->rgt->ntyp)
+ ana_stmnt(t, now->rgt, RVAL);
break;
case PRINT:
@@ -679,7 +698,8 @@
break;
default:
- printf("spin: bad node type %d line %d (ana_stmnt)\n", now->ntyp, now->ln);
+ printf("spin: %s:%d, bad node type %d (ana_stmnt)\n",
+ now->fn->name, now->ln, now->ntyp);
fatal("aborting", (char *) 0);
}
}
@@ -692,10 +712,7 @@
int counter = 1;
#endif
for (p = rdy; p; p = p->nxt)
- { if (p->tn == eventmapnr
- || p->tn == claimnr)
- continue;
-
+ {
ana_seq(p->s);
fsm_table();
@@ -711,7 +728,7 @@
{ FSM_ANA();
}
if (merger)
- { FSM_MERGER(p->n->name);
+ { FSM_MERGER(/* p->n->name */);
huntele(e, e->status, -1)->merge_in = 1; /* start-state */
#if 0
printf("\n");
@@ -726,8 +743,7 @@
{
if (!(e->status&DONE) && (verbose&32))
{ printf("unreachable code: ");
- printf("%s, line %3d: ",
- e->n->fn->name, e->n->ln);
+ printf("%s:%3d ", e->n->fn->name, e->n->ln);
comment(stdout, e->n, 0);
printf("\n");
}
@@ -735,7 +751,7 @@
}
if (export_ast)
{ AST_slice();
- exit(0);
+ alldone(0); /* changed in 5.3.0: was exit(0) */
}
}
@@ -831,9 +847,15 @@
{ if (e->n->ntyp == GOTO)
{ g = get_lab(e->n, 1);
g = huntele(g, e->status, -1);
+ if (!g)
+ { fatal("unexpected error 2", (char *) 0);
+ }
To = g->seqno;
} else if (e->nxt)
{ g = huntele(e->nxt, e->status, -1);
+ if (!g)
+ { fatal("unexpected error 3", (char *) 0);
+ }
To = g->seqno;
} else
To = 0;
--- a/sys/src/cmd/spin/pangen5.h
+++ b/sys/src/cmd/spin/pangen5.h
@@ -1,15 +1,12 @@
/***** spin: pangen5.h *****/
-/* Copyright (c) 1997-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
-static char *Xpt[] = {
+static const char *Xpt[] = {
"#if defined(MA) && (defined(W_XPT) || defined(R_XPT))",
"static Vertex **temptree;",
"static char wbuf[4096];",
@@ -80,7 +77,7 @@
" int i, j; uchar c;",
" static uchar xwarned = 0;",
"",
- " sprintf(nm, \"%%s.xpt\", Source);",
+ " sprintf(nm, \"%%s.xpt\", PanSource);",
" if ((fd = creat(nm, 0666)) <= 0)",
" if (!xwarned)",
" { xwarned = 1;",
@@ -136,7 +133,7 @@
" stacker[dfa_depth-1] = 0; r = dfa_store(stacker);",
" stacker[dfa_depth-1] = 4; j = dfa_member(dfa_depth-1);",
" if (r != 1 || j != 0)",
- " { printf(\"%%d: \", stackcnt);",
+ " { printf(\"%%lu: \", stackcnt);",
" for (i = 0; i < dfa_depth; i++)",
" printf(\"%%d,\", stacker[i]);",
" printf(\" -- not a stackstate <o:%%d,4:%%d>\\n\", r, j);",
@@ -372,7 +369,7 @@
" int i, j;",
"",
" wcnt = 0;",
- " sprintf(nm, \"%%s.xpt\", Source);",
+ " sprintf(nm, \"%%s.xpt\", PanSource);",
" if ((fd = open(nm, 0)) < 0) /* O_RDONLY */",
" Uerror(\"cannot open checkpoint file\");",
"",
@@ -416,7 +413,7 @@
" x_cleanup(d);",
" close(fd);",
"",
- " printf(\"pan: removed %%d stackstates\\n\", stackcnt);",
+ " printf(\"pan: removed %%lu stackstates\\n\", stackcnt);",
" nstates -= (double) stackcnt;",
"}",
"#endif",
--- a/sys/src/cmd/spin/pangen6.c
+++ b/sys/src/cmd/spin/pangen6.c
@@ -1,21 +1,11 @@
/***** spin: pangen6.c *****/
-/* Copyright (c) 2000-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
-/* Abstract syntax tree analysis / slicing (spin option -A) */
-/* AST_store stores the fsms's for each proctype */
-/* AST_track keeps track of variables used in properties */
-/* AST_slice starts the slicing algorithm */
-/* it first collects more info and then calls */
-/* AST_criteria to process the slice criteria */
-
#include "spin.h"
#include "y.tab.h"
@@ -90,7 +80,6 @@
static Slicer *rel_vars; /* all relevant variables */
static int AST_Changes;
static int AST_Round;
-static FSM_state no_state;
static RPN *rpn;
static int in_recv = 0;
@@ -145,7 +134,7 @@
{
if (!n || !n->sym) return;
- if (n->sym->nel != 1)
+ if (n->sym->nel > 1 || n->sym->isarray)
def_use(n->lft, code); /* process the index */
if (n->sym->type == STRUCT /* and possible deeper ones */
@@ -202,6 +191,8 @@
case '~':
case 'c':
case ENABLED:
+ case SET_P:
+ case GET_P:
case ASSERT:
case EVAL:
def_use(now->lft, USE|code);
@@ -503,7 +494,7 @@
if (strcmp(as->name, bs->name) != 0)
return 0;
- if (as->type == STRUCT && a->rgt && b->rgt)
+ if (as->type == STRUCT && a->rgt && b->rgt) /* we know that a and b are not null */
return AST_mutual(a->rgt->lft, b->rgt->lft, 0);
return 1;
@@ -545,14 +536,14 @@
case 'r':
/* guess sends where name may originate */
for (cl = chanlist; cl; cl = cl->nxt) /* all sends */
- { int a = AST_nrpar(cl->s);
- int b = AST_nrpar(t->step->n);
- if (a != b) /* matching nrs of params */
+ { int aa = AST_nrpar(cl->s);
+ int bb = AST_nrpar(t->step->n);
+ if (aa != bb) /* matching nrs of params */
continue;
- a = AST_ord(cl->s, cl->n);
- b = AST_ord(t->step->n, u->n);
- if (a != b) /* same position in parlist */
+ aa = AST_ord(cl->s, cl->n);
+ bb = AST_ord(t->step->n, u->n);
+ if (aa != bb) /* same position in parlist */
continue;
AST_add_alias(cl->n, 4); /* RCV assume possible match */
@@ -692,9 +683,7 @@
}
for (a = ast; a; a = a->nxt) /* all other stmnts */
- { if (strcmp(a->p->n->name, ":never:") != 0
- && strcmp(a->p->n->name, ":trace:") != 0
- && strcmp(a->p->n->name, ":notrace:") != 0)
+ { if (a->p->b != N_CLAIM && a->p->b != E_TRACE && a->p->b != N_TRACE)
for (f = a->fsm; f; f = f->nxt)
for (t = f->t; t; t = t->nxt)
{ if (!(t->relevant&1))
@@ -786,10 +775,8 @@
*/
for (a = ast; a; a = a->nxt)
- { if (strcmp(a->p->n->name, ":never:") == 0
- || strcmp(a->p->n->name, ":trace:") == 0
- || strcmp(a->p->n->name, ":notrace:") == 0
- || strcmp(a->p->n->name, ":init:") == 0)
+ { if (a->p->b == N_CLAIM || a->p->b == I_PROC
+ || a->p->b == E_TRACE || a->p->b == N_TRACE)
{ a->relevant |= 1; /* the proctype is relevant */
continue;
}
@@ -823,9 +810,9 @@
printf("spin: redundant in proctype %s (for given property):\n",
a->p->n->name);
}
- printf(" line %3d %s (state %d)",
- e->n?e->n->ln:-1,
+ printf(" %s:%d (state %d)",
e->n?e->n->fn->name:"-",
+ e->n?e->n->ln:-1,
e->seqno);
printf(" [");
comment(stdout, e->n, 0);
@@ -1016,7 +1003,8 @@
printf(" -- %d\n", code);
#endif
if (in_recv && (code&DEF) && (code&USE))
- { printf("spin: error: DEF and USE of same var in rcv stmnt: ");
+ { printf("spin: %s:%d, error: DEF and USE of same var in rcv stmnt: ",
+ n->fn->name, n->ln);
AST_var(n, n->sym, 1);
printf(" -- %d\n", code);
nr_errs++;
@@ -1065,6 +1053,8 @@
case '~':
case 'c':
case ENABLED:
+ case SET_P:
+ case GET_P:
case ASSERT:
AST_track(now->lft, USE|code);
break;
@@ -1075,8 +1065,8 @@
case NAME:
name_AST_track(now, code);
- if (now->sym->nel != 1)
- AST_track(now->lft, USE|code); /* index */
+ if (now->sym->nel > 1 || now->sym->isarray)
+ AST_track(now->lft, USE); /* index, was USE|code */
break;
case 'R':
@@ -1569,7 +1559,8 @@
{ t->relevant &= ~2; /* clear mark */
if (verbose&32)
{ printf("\t\tnomark ");
- comment(stdout, t->step->n, 0);
+ if (t->step && t->step->n)
+ comment(stdout, t->step->n, 0);
printf("\n");
} } }
@@ -1601,7 +1592,8 @@
t->relevant |= 2; /* lift */
if (verbose&32)
{ printf("\t\t\tliftmark ");
- comment(stdout, t->step->n, 0);
+ if (t->step && t->step->n)
+ comment(stdout, t->step->n, 0);
printf("\n");
}
AST_spread(a, t->to); /* and spread to all guards */
@@ -1621,10 +1613,9 @@
{ AST *a;
for (a = ast; a; a = a->nxt)
- if (strcmp(a->p->n->name, ":never:") != 0
- && strcmp(a->p->n->name, ":trace:") != 0
- && strcmp(a->p->n->name, ":notrace:") != 0)
- AST_ctrl(a);
+ { if (a->p->b != N_CLAIM && a->p->b != E_TRACE && a->p->b != N_TRACE)
+ { AST_ctrl(a);
+ } }
}
static void
@@ -1634,9 +1625,7 @@
FSM_trans *t;
for (a = ast; a; a = a->nxt)
- { if (strcmp(a->p->n->name, ":never:") != 0
- && strcmp(a->p->n->name, ":trace:") != 0
- && strcmp(a->p->n->name, ":notrace:") != 0)
+ { if (a->p->b != N_CLAIM && a->p->b != E_TRACE && a->p->b != N_TRACE)
for (f = a->fsm; f; f = f->nxt)
for (t = f->t; t; t = t->nxt)
{ if (t->step
@@ -1692,8 +1681,7 @@
int spurious = 0;
if (!slicer)
- { non_fatal("no slice criteria (or no claim) specified",
- (char *) 0);
+ { printf("spin: warning: no slice criteria found (no assertions and no claim)\n");
spurious = 1;
}
AST_dorelevant(); /* mark procs refered to in remote refs */
@@ -1730,9 +1718,7 @@
AST_store(ProcList *p, int start_state)
{ AST *n_ast;
- if (strcmp(p->n->name, ":never:") != 0
- && strcmp(p->n->name, ":trace:") != 0
- && strcmp(p->n->name, ":notrace:") != 0)
+ if (p->b != N_CLAIM && p->b != E_TRACE && p->b != N_TRACE)
{ n_ast = (AST *) emalloc(sizeof(AST));
n_ast->p = p;
n_ast->i_st = start_state;
@@ -1809,12 +1795,10 @@
int cnt;
for (a = ast; a; a = a->nxt)
- { if (strcmp(a->p->n->name, ":never:") == 0
- || strcmp(a->p->n->name, ":trace:") == 0
- || strcmp(a->p->n->name, ":notrace:") == 0
- || strcmp(a->p->n->name, ":init:") == 0)
- continue; /* have no params */
-
+ { if (a->p->b == N_CLAIM || a->p->b == I_PROC
+ || a->p->b == E_TRACE || a->p->b == N_TRACE)
+ { continue; /* has no params */
+ }
cnt = 0;
for (f = a->p->p; f; f = f->rgt) /* types */
for (t = f->lft; t; t = t->rgt) /* formals */
@@ -1845,9 +1829,8 @@
} }
for (a = ast; a; a = a->nxt)
- { if (strcmp(a->p->n->name, ":never:") != 0
- && strcmp(a->p->n->name, ":trace:") != 0
- && strcmp(a->p->n->name, ":notrace:") != 0) /* claim has no locals */
+ { if (a->p->b != N_CLAIM
+ && a->p->b != E_TRACE && a->p->b != N_TRACE) /* has no locals */
for (walk = all_names; walk; walk = walk->next)
{ sp = walk->entry;
if (sp
@@ -1995,7 +1978,7 @@
h = fsm_tbl[out];
i = f->from / BPW;
- j = f->from % BPW;
+ j = f->from % BPW; /* assert(j <= 32); else lshift undefined? */
g = h->mod;
if (verbose&32)
@@ -2023,28 +2006,30 @@
d. the dominator is reachable, and not equal to this node
#endif
for (t = f->p, i = 0; t; t = t->nxt)
- i += fsm_tbl[t->to]->seen;
- if (i <= 1) continue; /* a. */
-
+ { i += fsm_tbl[t->to]->seen;
+ }
+ if (i <= 1)
+ { continue; /* a. */
+ }
for (cnt = 1; cnt < a->nstates; cnt++) /* 0 is endstate */
{ if (cnt == f->from
|| !fsm_tbl[cnt]->seen)
- continue; /* c. */
-
+ { continue; /* c. */
+ }
i = cnt / BPW;
- j = cnt % BPW;
+ j = cnt % BPW; /* assert(j <= 32); */
if (!(f->dom[i]&(1<<j)))
- continue;
-
+ { continue;
+ }
for (t = fsm_tbl[cnt]->t, i = 0; t; t = t->nxt)
- i += fsm_tbl[t->to]->seen;
+ { i += fsm_tbl[t->to]->seen;
+ }
if (i <= 1)
- continue; /* b. */
-
+ { continue; /* b. */
+ }
if (f->mod) /* final check in 2nd phase */
- subgraph(a, f, cnt); /* possible entry-exit pair */
- }
- }
+ { subgraph(a, f, cnt); /* possible entry-exit pair */
+ } } }
}
static void
@@ -2178,27 +2163,26 @@
for (f = a->fsm; f; f = f->nxt)
{ if (!f->seen) continue;
- f->dom = (ulong *)
- emalloc(a->nwords * sizeof(ulong));
+ f->dom = (ulong *) emalloc(a->nwords * sizeof(ulong));
if (f->from == a->i_st)
{ i = a->i_st / BPW;
- j = a->i_st % BPW;
+ j = a->i_st % BPW; /* assert(j <= 32); */
f->dom[i] = (1<<j); /* (1) */
} else /* (2) */
{ for (i = 0; i < a->nwords; i++)
- f->dom[i] = (ulong) ~0; /* all 1's */
-
+ { f->dom[i] = (ulong) ~0; /* all 1's */
+ }
if (a->nstates % BPW)
for (i = (a->nstates % BPW); i < (int) BPW; i++)
- f->dom[a->nwords-1] &= ~(1<<i); /* clear tail */
-
+ { f->dom[a->nwords-1] &= ~(1<< ((ulong) i)); /* clear tail */
+ }
for (cnt = 0; cnt < a->nstates; cnt++)
- if (!fsm_tbl[cnt]->seen)
+ { if (!fsm_tbl[cnt]->seen)
{ i = cnt / BPW;
- j = cnt % BPW;
- f->dom[i] &= ~(1<<j);
- } } }
+ j = cnt % BPW; /* assert(j <= 32); */
+ f->dom[i] &= ~(1<< ((ulong) j));
+ } } } }
}
static int
@@ -2226,7 +2210,7 @@
}
i = f->from / BPW;
- j = f->from % BPW;
+ j = f->from % BPW; /* assert(j <= 32); */
ndom[i] |= (1<<j); /* (5a) */
for (i = 0; i < a->nwords; i++)
@@ -2261,6 +2245,7 @@
FSM_trans *t;
AST *a;
int oi;
+ static FSM_state no_state;
#if 0
find dominators
Aho, Sethi, & Ullman, Compilers - principles, techniques, and tools
--- /dev/null
+++ b/sys/src/cmd/spin/pangen6.h
@@ -1,0 +1,2878 @@
+/***** spin: pangen6.h *****/
+
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
+
+static const char *Code2e[] = {
+ "#if (NCORE>1 || defined(BFS_PAR)) && !defined(WIN32) && !defined(WIN64)",
+ " /* Test and Set assembly code */",
+ " #if defined(i386) || defined(__i386__) || defined(__x86_64__)",
+ " int",
+ " tas(volatile int *s) /* tested */",
+ " { int r;",
+ " __asm__ __volatile__(",
+ " \"xchgl %%0, %%1 \\n\\t\"",
+ " : \"=r\"(r), \"=m\"(*s)",
+ " : \"0\"(1), \"m\"(*s)",
+ " : \"memory\");",
+ " ",
+ " return r;",
+ " }",
+ " #elif defined(__arm__)",
+ " int",
+ " tas(volatile int *s) /* not tested */",
+ " { int r = 1;",
+ " __asm__ __volatile__(",
+ " \"swpb %%0, %%0, [%%3] \\n\"",
+ " : \"=r\"(r), \"=m\"(*s)",
+ " : \"0\"(r), \"r\"(s));",
+ "",
+ " return r;",
+ " }",
+ " #elif defined(sparc) || defined(__sparc__)",
+ " int",
+ " tas(volatile int *s) /* not tested */",
+ " { int r = 1;",
+ " __asm__ __volatile__(",
+ " \" ldstub [%%2], %%0 \\n\"",
+ " : \"=r\"(r), \"=m\"(*s)",
+ " : \"r\"(s));",
+ "",
+ " return r;",
+ " }",
+ " #elif defined(ia64) || defined(__ia64__)",
+ " /* Intel Itanium */",
+ " int",
+ " tas(volatile int *s) /* tested */",
+ " { long int r;",
+ " __asm__ __volatile__(",
+ " \" xchg4 %%0=%%1,%%2 \\n\"",
+ " : \"=r\"(r), \"+m\"(*s)",
+ " : \"r\"(1)",
+ " : \"memory\");",
+ " return (int) r;",
+ " }",
+ " #elif defined(__powerpc64__)",
+ " int",
+ " tas(volatile int *s) /* courtesy srirajpaul */",
+ " { int r;",
+ " #if 1",
+ " r = __sync_lock_test_and_set();",
+ " #else",
+ " /* xlc compiler only */",
+ " r = __fetch_and_or(s, 1);",
+ " __isync();",
+ " #endif",
+ " return r;",
+ " }",
+ " #else",
+ " #error missing definition of test and set operation for this platform",
+ " #endif",
+ "",
+ " #ifndef NO_CAS", /* linux, windows */
+ " #define cas(a,b,c) __sync_bool_compare_and_swap(a,b,c)",
+ " #else",
+ " int", /* workaround if the above is not available */
+ " cas(volatile uint32_t *a, uint32_t b, uint32_t c)",
+ " { static volatile int cas_lock;",
+ " while (tas(&cas_lock) != 0) { ; }",
+ " if (*a == b)",
+ " { *a = c;",
+ " cas_lock = 0;",
+ " return 1;",
+ " }",
+ " cas_lock = 0;",
+ " return 0;",
+ " }",
+ " #endif",
+ "#endif",
+ 0,
+};
+
+static const char *Code2c[] = { /* multi-core option - Spin 5.0 and later */
+ "#if NCORE>1",
+ "#if defined(WIN32) || defined(WIN64)",
+ " #ifndef _CONSOLE",
+ " #define _CONSOLE",
+ " #endif",
+ " #ifdef WIN64",
+ " #undef long",
+ " #endif",
+ " #include <windows.h>",
+ "/*",
+ " #ifdef WIN64",
+ " #define long long long",
+ " #endif",
+ "*/",
+ "#else",
+ " #include <sys/ipc.h>",
+ " #include <sys/sem.h>",
+ " #include <sys/shm.h>",
+ "#endif",
+ "",
+ "/* code common to cygwin/linux and win32/win64: */",
+ "",
+ "#ifdef VERBOSE",
+ " #define VVERBOSE (1)",
+ "#else",
+ " #define VVERBOSE (0)",
+ "#endif",
+ "",
+ "/* the following values must be larger than 256 and must fit in an int */",
+ "#define QUIT 1024 /* terminate now command */",
+ "#define QUERY 512 /* termination status query message */",
+ "#define QUERY_F 513 /* query failed, cannot quit */",
+ "",
+ "#define GN_FRAMES (int) (GWQ_SIZE / (double) sizeof(SM_frame))",
+ "#define LN_FRAMES (int) (LWQ_SIZE / (double) sizeof(SM_frame))",
+ "",
+ "#ifndef VMAX",
+ " #define VMAX VECTORSZ",
+ "#endif",
+ "#ifndef PMAX",
+ " #define PMAX 64",
+ "#endif",
+ "#ifndef QMAX",
+ " #define QMAX 64",
+ "#endif",
+ "",
+ "#if VECTORSZ>32000",
+ " #define OFFT int",
+ "#else",
+ " #define OFFT short",
+ "#endif",
+ "",
+ "#ifdef SET_SEG_SIZE",
+ " /* no longer useful -- being recomputed for local heap size anyway */",
+ " double SEG_SIZE = (((double) SET_SEG_SIZE) * 1048576.);",
+ "#else",
+ " double SEG_SIZE = (1048576.*1024.); /* 1GB default shared memory pool segments */",
+ "#endif",
+ "",
+ "double LWQ_SIZE = 0.; /* initialized in main */",
+ "",
+ "#ifdef SET_WQ_SIZE",
+ " #ifdef NGQ",
+ " #warning SET_WQ_SIZE applies to global queue -- ignored",
+ " double GWQ_SIZE = 0.;",
+ " #else",
+ " double GWQ_SIZE = (((double) SET_WQ_SIZE) * 1048576.);",
+ " /* must match the value in pan_proxy.c, if used */",
+ " #endif",
+ "#else",
+ " #ifdef NGQ",
+ " double GWQ_SIZE = 0.;",
+ " #else",
+ " double GWQ_SIZE = (128.*1048576.); /* 128 MB default queue sizes */",
+ " #endif",
+ "#endif",
+ "",
+ "/* Crash Detection Parameters */",
+ "#ifndef ONESECOND",
+ " #define ONESECOND (1<<25)", /* name is somewhat of a misnomer */
+ "#endif",
+ "#ifndef SHORT_T",
+ " #define SHORT_T (0.1)",
+ "#endif",
+ "#ifndef LONG_T",
+ " #define LONG_T (600)",
+ "#endif",
+ "",
+ "double OneSecond = (double) (ONESECOND); /* waiting for a free slot -- checks crash */",
+ "double TenSeconds = 10. * (ONESECOND); /* waiting for a lock -- check for a crash */",
+ "",
+ "/* Termination Detection Params -- waiting for new state input in Get_Full_Frame */",
+ "double Delay = ((double) SHORT_T) * (ONESECOND); /* termination detection trigger */",
+ "double OneHour = ((double) LONG_T) * (ONESECOND); /* timeout termination detection */",
+ "",
+ "typedef struct SM_frame SM_frame;",
+ "typedef struct SM_results SM_results;",
+ "typedef struct sh_Allocater sh_Allocater;",
+ "",
+ "struct SM_frame { /* about 6K per slot */",
+ " volatile int m_vsize; /* 0 means free slot */",
+ " volatile int m_boq; /* >500 is a control message */",
+ "#ifdef FULL_TRAIL",
+ " volatile struct Stack_Tree *m_stack; /* ptr to previous state */",
+ "#endif",
+ " volatile uchar m_tau;",
+ " volatile uchar m_o_pm;",
+ " volatile int nr_handoffs; /* to compute real_depth */",
+ " volatile char m_now [VMAX];",
+ "#if !defined(NOCOMP) && !defined(HC)",
+ " volatile char m_mask [(VMAX + 7)/8];",
+ "#endif",
+ " volatile OFFT m_p_offset[PMAX];",
+ " volatile OFFT m_q_offset[QMAX];",
+ " volatile uchar m_p_skip [PMAX];",
+ " volatile uchar m_q_skip [QMAX];",
+ "#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)",
+ " volatile uchar m_c_stack [StackSize];",
+ /* captures contents of c_stack[] for unmatched objects */
+ "#endif",
+ "};",
+ "",
+ "int proxy_pid; /* id of proxy if nonzero -- receive half */",
+ "int store_proxy_pid;",
+ "short remote_party;",
+ "int proxy_pid_snd; /* id of proxy if nonzero -- send half */",
+ "char o_cmdline[512]; /* to pass options to children */",
+ "",
+ "int iamin[CS_NR+NCORE]; /* non-shared */",
+ "",
+"#if defined(WIN32) || defined(WIN64)",
+ "int tas(volatile LONG *);",
+ "",
+ "HANDLE proxy_handle_snd; /* for Windows Create and Terminate */",
+ "",
+ "struct sh_Allocater { /* shared memory for states */",
+ " volatile char *dc_arena; /* to allocate states from */",
+ " volatile long pattern; /* to detect overruns */",
+ " volatile long dc_size; /* nr of bytes left */",
+ " volatile void *dc_start; /* where memory segment starts */",
+ " volatile void *dc_id; /* to attach, detach, remove shared memory segments */",
+ " volatile sh_Allocater *nxt; /* linked list of pools */",
+ "};",
+ "DWORD worker_pids[NCORE]; /* root mem of pids of all workers created */",
+ "HANDLE worker_handles[NCORE]; /* for windows Create and Terminate */",
+ "void * shmid [NR_QS]; /* return value from CreateFileMapping */",
+ "void * shmid_M; /* shared mem for state allocation in hashtable */",
+ "",
+ "#ifdef SEP_STATE",
+ " void *shmid_X;",
+ "#else",
+ " void *shmid_S; /* shared bitstate arena or hashtable */",
+ "#endif",
+"#else",
+ "int tas(volatile int *);",
+ "",
+ "struct sh_Allocater { /* shared memory for states */",
+ " volatile char *dc_arena; /* to allocate states from */",
+ " volatile long pattern; /* to detect overruns */",
+ " volatile long dc_size; /* nr of bytes left */",
+ " volatile char *dc_start; /* where memory segment starts */",
+ " volatile int dc_id; /* to attach, detach, remove shared memory segments */",
+ " volatile sh_Allocater *nxt; /* linked list of pools */",
+ "};",
+ "",
+ "int worker_pids[NCORE]; /* root mem of pids of all workers created */",
+ "int shmid [NR_QS]; /* return value from shmget */",
+ "int nibis = 0; /* set after shared mem has been released */",
+ "int shmid_M; /* shared mem for state allocation in hashtable */",
+ "#ifdef SEP_STATE",
+ " long shmid_X;",
+ "#else",
+ " int shmid_S; /* shared bitstate arena or hashtable */",
+ " volatile sh_Allocater *first_pool; /* of shared state memory */",
+ " volatile sh_Allocater *last_pool;",
+ "#endif", /* SEP_STATE */
+"#endif", /* WIN32 || WIN64 */
+ "",
+ "struct SM_results { /* for shuttling back final stats */",
+ " volatile int m_vsize; /* avoid conflicts with frames */",
+ " volatile int m_boq; /* these 2 fields are not written in record_info */",
+ " /* probably not all fields really need to be volatile */",
+ " volatile double m_memcnt;",
+ " volatile double m_nstates;",
+ " volatile double m_truncs;",
+ " volatile double m_truncs2;",
+ " volatile double m_nShadow;",
+ " volatile double m_nlinks;",
+ " volatile double m_ngrabs;",
+ " volatile double m_nlost;",
+ " volatile double m_hcmp;",
+ " volatile double m_frame_wait;",
+ " volatile int m_hmax;",
+ " volatile int m_svmax;",
+ " volatile int m_smax;",
+ " volatile int m_mreached;",
+ " volatile int m_errors;",
+ " volatile int m_VMAX;",
+ " volatile short m_PMAX;",
+ " volatile short m_QMAX;",
+ " volatile uchar m_R; /* reached info for all proctypes */",
+ "};",
+ "",
+ "int core_id = 0; /* internal process nr, to know which q to use */",
+ "unsigned long nstates_put = 0; /* statistics */",
+ "unsigned long nstates_get = 0;",
+ "int query_in_progress = 0; /* termination detection */",
+ "",
+ "double free_wait = 0.; /* waiting for a free frame */",
+ "double frame_wait = 0.; /* waiting for a full frame */",
+ "double lock_wait = 0.; /* waiting for access to cs */",
+ "double glock_wait[3]; /* waiting for access to global lock */",
+ "",
+ "char *sprefix = \"rst\";",
+ "uchar was_interrupted, issued_kill, writing_trail;",
+ "",
+ "static SM_frame cur_Root; /* current root, to be safe with error trails */",
+ "",
+ "SM_frame *m_workq [NR_QS]; /* per cpu work queues + global q */",
+ "char *shared_mem[NR_QS]; /* return value from shmat */",
+ "#ifdef SEP_HEAP",
+ "char *my_heap;",
+ "long my_size;",
+ "#endif",
+ "volatile sh_Allocater *dc_shared; /* assigned at initialization */",
+ "",
+ "static int vmax_seen, pmax_seen, qmax_seen;",
+ "static double gq_tries, gq_hasroom, gq_hasnoroom;",
+ "",
+ "volatile int *prfree;", /* [NCORE] */
+ "volatile int *prfull;", /* [NCORE] */
+ "volatile int *prcnt;", /* [NCORE] */
+ "volatile int *prmax;", /* [NCORE] */
+ "",
+ "volatile int *sh_lock; /* mutual exclusion locks - in shared memory */",
+ "volatile double *is_alive; /* to detect when processes crash */",
+ "volatile int *grfree, *grfull, *grcnt, *grmax; /* access to shared global q */",
+ "volatile double *gr_readmiss, *gr_writemiss;",
+ "static int lrfree; /* used for temporary recording of slot */",
+ "static int dfs_phase2;",
+ "",
+ "void mem_put(int); /* handoff state to other cpu */",
+ "void mem_put_acc(void); /* liveness mode */",
+ "void mem_get(void); /* get state from work queue */",
+ "void sudden_stop(char *);",
+ "",
+ "void",
+ "record_info(SM_results *r)",
+ "{ int i;",
+ " uchar *ptr;",
+ "",
+ "#ifdef SEP_STATE",
+ " if (0)",
+ " { cpu_printf(\"nstates %%g nshadow %%g -- memory %%-6.3f Mb\\n\",",
+ " nstates, nShadow, memcnt/(1048576.));",
+ " }",
+ " r->m_memcnt = 0;",
+ "#else",
+ " #ifdef BITSTATE",
+ " r->m_memcnt = 0; /* it's shared */",
+ " #endif",
+ " r->m_memcnt = memcnt;",
+ "#endif",
+ " if (a_cycles && core_id == 1)",
+ " { r->m_nstates = nstates;",
+ " r->m_nShadow = nstates;",
+ " } else",
+ " { r->m_nstates = nstates;",
+ " r->m_nShadow = nShadow;",
+ " }",
+ " r->m_truncs = truncs;",
+ " r->m_truncs2 = truncs2;",
+ " r->m_nlinks = nlinks;",
+ " r->m_ngrabs = ngrabs;",
+ " r->m_nlost = nlost;",
+ " r->m_hcmp = hcmp;",
+ " r->m_frame_wait = frame_wait;",
+ " r->m_hmax = hmax;",
+ " r->m_svmax = svmax;",
+ " r->m_smax = smax;",
+ " r->m_mreached = mreached;",
+ " r->m_errors = errors;",
+ " r->m_VMAX = vmax_seen;",
+ " r->m_PMAX = (short) pmax_seen;",
+ " r->m_QMAX = (short) qmax_seen;",
+ " ptr = (uchar *) &(r->m_R);",
+ " for (i = 0; i <= _NP_; i++) /* all proctypes */",
+ " { memcpy(ptr, reached[i], NrStates[i]*sizeof(uchar));",
+ " ptr += NrStates[i]*sizeof(uchar);",
+ " }",
+ " if (verbose>1)",
+ " { cpu_printf(\"Put Results nstates %%g (sz %%d)\\n\", nstates, ptr - &(r->m_R));",
+ " }",
+ "}",
+ "",
+ "void snapshot(void);",
+ "",
+ "void",
+ "retrieve_info(SM_results *r)",
+ "{ int i, j;",
+ " volatile uchar *ptr;",
+ "",
+ " snapshot(); /* for a final report */",
+ "",
+ " enter_critical(GLOBAL_LOCK);",
+ "#ifdef SEP_HEAP",
+ " if (verbose)",
+ " { printf(\"cpu%%d: local heap-left %%ld KB (%%d MB)\\n\",",
+ " core_id, (long) (my_size/1024), (int) (my_size/1048576));",
+ " }",
+ "#endif",
+ " if (verbose && core_id == 0)",
+ " { printf(\"qmax: \");",
+ " for (i = 0; i < NCORE; i++)",
+ " { printf(\"%%d \", prmax[i]);",
+ " }",
+ "#ifndef NGQ",
+ " printf(\"G: %%d\", *grmax);",
+ "#endif",
+ " printf(\"\\n\");",
+ " }",
+ " leave_critical(GLOBAL_LOCK);",
+ "",
+ " memcnt += r->m_memcnt;",
+ " nstates += r->m_nstates;",
+ " nShadow += r->m_nShadow;",
+ " truncs += r->m_truncs;",
+ " truncs2 += r->m_truncs2;",
+ " nlinks += r->m_nlinks;",
+ " ngrabs += r->m_ngrabs;",
+ " nlost += r->m_nlost;",
+ " hcmp += r->m_hcmp;",
+ " /* frame_wait += r->m_frame_wait; */",
+ " errors += r->m_errors;",
+ "",
+ " if (hmax < r->m_hmax) hmax = r->m_hmax;",
+ " if (svmax < r->m_svmax) svmax = r->m_svmax;",
+ " if (smax < r->m_smax) smax = r->m_smax;",
+ " if (mreached < r->m_mreached) mreached = r->m_mreached;",
+ "",
+ " if (vmax_seen < r->m_VMAX) vmax_seen = r->m_VMAX;",
+ " if (pmax_seen < (int) r->m_PMAX) pmax_seen = (int) r->m_PMAX;",
+ " if (qmax_seen < (int) r->m_QMAX) qmax_seen = (int) r->m_QMAX;",
+ "",
+ " ptr = &(r->m_R);",
+ " for (i = 0; i <= _NP_; i++) /* all proctypes */",
+ " { for (j = 0; j < NrStates[i]; j++)",
+ " { if (*(ptr + j) != 0)",
+ " { reached[i][j] = 1;",
+ " } }",
+ " ptr += NrStates[i]*sizeof(uchar);",
+ " }",
+ " if (verbose>1)",
+ " { cpu_printf(\"Got Results (%%d)\\n\", (int) (ptr - &(r->m_R)));",
+ " snapshot();",
+ " }",
+ "}",
+ "",
+ "#if !defined(WIN32) && !defined(WIN64)",
+ "static void",
+ "rm_shared_segments(void)",
+ "{ int m;",
+ " volatile sh_Allocater *nxt_pool;",
+ " /*",
+ " * mark all shared memory segments for removal ",
+ " * the actual removes wont happen intil last process dies or detaches",
+ " * the shmctl calls can return -1 if not all procs have detached yet",
+ " */",
+ " for (m = 0; m < NR_QS; m++) /* +1 for global q */",
+ " { if (shmid[m] != -1)",
+ " { (void) shmctl(shmid[m], IPC_RMID, NULL);",
+ " } }",
+ "#ifdef SEP_STATE",
+ " if (shmid_M != -1)",
+ " { (void) shmctl(shmid_M, IPC_RMID, NULL);",
+ " }",
+ "#else",
+ " if (shmid_S != -1)",
+ " { (void) shmctl(shmid_S, IPC_RMID, NULL);",
+ " }",
+ " for (last_pool = first_pool; last_pool != NULL; last_pool = nxt_pool)",
+ " { shmid_M = (int) (last_pool->dc_id);",
+ " nxt_pool = last_pool->nxt; /* as a pre-caution only */",
+ " if (shmid_M != -1)",
+ " { (void) shmctl(shmid_M, IPC_RMID, NULL);",
+ " } }",
+ "#endif",
+ "}",
+ "#endif",
+ "",
+ "void",
+ "sudden_stop(char *s)",
+ "{ char b[64];",
+ " int i;",
+ "",
+ " printf(\"cpu%%d: stop - %%s\\n\", core_id, s);",
+ "#if !defined(WIN32) && !defined(WIN64)",
+ " if (proxy_pid != 0)",
+ " { rm_shared_segments();",
+ " }",
+ "#endif",
+ " if (search_terminated != NULL)",
+ " { if (*search_terminated != 0)",
+ " { if (verbose)",
+ " { printf(\"cpu%%d: termination initiated (%%d)\\n\",",
+ " core_id, (int) *search_terminated);",
+ " }",
+ " } else",
+ " { if (verbose)",
+ " { printf(\"cpu%%d: initiated termination\\n\", core_id);",
+ " }",
+ " *search_terminated |= 8; /* sudden_stop */",
+ " }",
+ " if (core_id == 0)",
+ " { if (((*search_terminated) & 4) /* uerror in one of the cpus */",
+ " && !((*search_terminated) & (8|32|128|256))) /* abnormal stop */",
+ " { if (errors == 0) errors++; /* we know there is at least 1 */",
+ " }",
+ " wrapup(); /* incomplete stats, but at least something */",
+ " }",
+ " return;",
+ " } /* else: should rarely happen, take more drastic measures */",
+ "",
+ " if (core_id == 0) /* local root process */",
+ " { for (i = 1; i < NCORE; i++) /* not for 0 of course */",
+ " { int ignore;",
+ "#if defined(WIN32) || defined(WIN64)",
+ " DWORD dwExitCode = 0;",
+ " GetExitCodeProcess(worker_handles[i], &dwExitCode);",
+ " if (dwExitCode == STILL_ACTIVE)",
+ " { TerminateProcess(worker_handles[i], 0);",
+ " }",
+ " printf(\"cpu0: terminate %%d %%d\\n\",",
+ " (int) worker_pids[i], (dwExitCode == STILL_ACTIVE));",
+ "#else",
+ " sprintf(b, \"kill -%%d %%d\", (int) SIGKILL, (int) worker_pids[i]);",
+ " ignore = system(b); /* if this is a proxy: receive half */",
+ " printf(\"cpu0: %%s\\n\", b);",
+ "#endif",
+ " }",
+ " issued_kill++;",
+ " } else",
+ " { /* on WIN32/WIN64 -- these merely kills the root process... */",
+ " if (was_interrupted == 0)", /* 2=SIGINT to root to trigger stop */
+ " { int ignore;",
+ " sprintf(b, \"kill -%%d %%d\", (int) SIGINT, (int) worker_pids[0]);",
+ " ignore = system(b); /* warn the root process */",
+ " printf(\"cpu%%d: %%s\\n\", core_id, b);",
+ " issued_kill++;",
+ " } }",
+ "}",
+ "",
+ "#define iam_alive() is_alive[core_id]++", /* for crash detection */
+ "",
+ "extern int crash_test(double);",
+ "extern void crash_reset(void);",
+ "",
+ "int",
+ "someone_crashed(int wait_type)",
+ "{ static double last_value = 0.0;",
+ " static int count = 0;",
+ "",
+ " if (search_terminated == NULL",
+ " || *search_terminated != 0)",
+ " {",
+ " if (!(*search_terminated & (8|32|128|256)))",
+ " { if (count++ < 100*NCORE)",
+ " { return 0;",
+ " } }",
+ " return 1;",
+ " }",
+ " /* check left neighbor only */",
+ " if (last_value == is_alive[(core_id + NCORE - 1) %% NCORE])",
+ " { if (count++ >= 100) /* to avoid unnecessary checks */",
+ " { return 1;",
+ " }",
+ " return 0;",
+ " }",
+ " last_value = is_alive[(core_id + NCORE - 1) %% NCORE];",
+ " count = 0;",
+ " crash_reset();",
+ " return 0;",
+ "}",
+ "",
+ "void",
+ "sleep_report(void)",
+ "{",
+ " enter_critical(GLOBAL_LOCK);",
+ " if (verbose)",
+ " {",
+ "#ifdef NGQ",
+ " printf(\"cpu%%d: locks: global %%g\\tother %%g\\t\",",
+ " core_id, glock_wait[0], lock_wait - glock_wait[0]);",
+ "#else",
+ " printf(\"cpu%%d: locks: GL %%g, RQ %%g, WQ %%g, HT %%g\\t\",",
+ " core_id, glock_wait[0], glock_wait[1], glock_wait[2],",
+ " lock_wait - glock_wait[0] - glock_wait[1] - glock_wait[2]);",
+ "#endif",
+ " printf(\"waits: states %%g slots %%g\\n\", frame_wait, free_wait);",
+ "#ifndef NGQ",
+ " printf(\"cpu%%d: gq [tries %%g, room %%g, noroom %%g]\\n\", core_id, gq_tries, gq_hasroom, gq_hasnoroom);",
+ " if (core_id == 0 && (*gr_readmiss >= 1.0 || *gr_readmiss >= 1.0 || *grcnt != 0))",
+ " printf(\"cpu0: gq [readmiss: %%g, writemiss: %%g cnt %%d]\\n\", *gr_readmiss, *gr_writemiss, *grcnt);",
+ "#endif",
+ " }",
+ " if (free_wait > 1000000.)",
+ " #ifndef NGQ",
+ " if (!a_cycles)",
+ " { printf(\"hint: this search may be faster with a larger work-queue\\n\");",
+ " printf(\" (-DSET_WQ_SIZE=N with N>%%g), and/or with -DUSE_DISK\\n\",",
+ " GWQ_SIZE/sizeof(SM_frame));",
+ " printf(\" or with a larger value for -zN (N>%%ld)\\n\", z_handoff);",
+ " #else",
+ " { printf(\"hint: this search may be faster if compiled without -DNGQ, with -DUSE_DISK, \");",
+ " printf(\"or with a larger -zN (N>%%d)\\n\", z_handoff);",
+ " #endif",
+ " }",
+ " leave_critical(GLOBAL_LOCK);",
+ "}",
+ "",
+ "#ifndef MAX_DSK_FILE",
+ " #define MAX_DSK_FILE 1000000 /* default is max 1M states per file */",
+ "#endif",
+ "",
+ "void",
+ "multi_usage(FILE *fd)",
+ "{ static int warned = 0;",
+ " if (warned > 0) { return; } else { warned++; }",
+ " fprintf(fd, \"\\n\");",
+ " fprintf(fd, \"Defining multi-core mode:\\n\\n\");",
+ " fprintf(fd, \" -DDUAL_CORE --> same as -DNCORE=2\\n\");",
+ " fprintf(fd, \" -DQUAD_CORE --> same as -DNCORE=4\\n\");",
+ " fprintf(fd, \" -DNCORE=N --> enables multi_core verification if N>1\\n\");",
+ " fprintf(fd, \"\\n\");",
+ " fprintf(fd, \"Additional directives supported in multi-core mode:\\n\\n\");",
+ " fprintf(fd, \" -DSEP_STATE --> forces separate statespaces instead of a single shared state space\\n\");",
+ " fprintf(fd, \" -DNUSE_DISK --> use disk for storing states when a work queue overflows\\n\");",
+ " fprintf(fd, \" -DMAX_DSK_FILE --> max nr of states per diskfile (%%d)\\n\", MAX_DSK_FILE);",
+ " fprintf(fd, \" -DFULL_TRAIL --> support full error trails (increases memory use)\\n\");",
+ " fprintf(fd, \"\\n\");",
+ " fprintf(fd, \"More advanced use (should rarely need changing):\\n\\n\");",
+ " fprintf(fd, \" To change the nr of states that can be stored in the global queue\\n\");",
+ " fprintf(fd, \" (lower numbers allow for more states to be stored, prefer multiples of 8):\\n\");",
+ " fprintf(fd, \" -DVMAX=N --> upperbound on statevector for handoffs (N=%%d)\\n\", VMAX);",
+ " fprintf(fd, \" -DPMAX=N --> upperbound on nr of procs (default: N=%%d)\\n\", PMAX);",
+ " fprintf(fd, \" -DQMAX=N --> upperbound on nr of channels (default: N=%%d)\\n\", QMAX);",
+ " fprintf(fd, \"\\n\");",
+#if 0
+ "#if !defined(WIN32) && !defined(WIN64)",
+ " fprintf(fd, \" To change the size of spin's individual shared memory segments for cygwin/linux:\\n\");",
+ " fprintf(fd, \" -DSET_SEG_SIZE=N --> default %%g (Mbytes)\\n\", SEG_SIZE/(1048576.));",
+ " fprintf(fd, \"\\n\");",
+ "#endif",
+#endif
+ " fprintf(fd, \" To set the total amount of memory reserved for the global workqueue:\\n\");",
+ " fprintf(fd, \" -DSET_WQ_SIZE=N --> default: N=128 (defined in MBytes)\\n\\n\");",
+#if 0
+ " fprintf(fd, \" To omit the global workqueue completely (bad idea):\\n\");",
+ " fprintf(fd, \" -DNGQ\\n\\n\");",
+#endif
+ " fprintf(fd, \" To force the use of a single global heap, instead of separate heaps:\\n\");",
+ " fprintf(fd, \" -DGLOB_HEAP\\n\");",
+ " fprintf(fd, \"\\n\");",
+ " fprintf(fd, \" To define a fct to initialize data before spawning processes (use quotes):\\n\");",
+ " fprintf(fd, \" \\\"-DC_INIT=fct()\\\"\\n\");",
+ " fprintf(fd, \"\\n\");",
+ " fprintf(fd, \" Timer settings for termination and crash detection:\\n\");",
+ " fprintf(fd, \" -DSHORT_T=N --> timeout for termination detection trigger (N=%%g)\\n\", (double) SHORT_T);",
+ " fprintf(fd, \" -DLONG_T=N --> timeout for giving up on termination detection (N=%%g)\\n\", (double) LONG_T);",
+ " fprintf(fd, \" -DONESECOND --> (1<<29) --> timeout waiting for a free slot -- to check for crash\\n\");",
+ " fprintf(fd, \" -DT_ALERT --> collect stats on crash alert timeouts\\n\\n\");",
+ " fprintf(fd, \"Help with Linux/Windows/Cygwin configuration for multi-core:\\n\");",
+ " fprintf(fd, \" http://spinroot.com/spin/multicore/V5_Readme.html\\n\");",
+ " fprintf(fd, \"\\n\");",
+ "}",
+ "#if NCORE>1 && defined(FULL_TRAIL)",
+ "typedef struct Stack_Tree {",
+ " uchar pr; /* process that made transition */",
+ " T_ID t_id; /* id of transition */",
+ " volatile struct Stack_Tree *prv; /* backward link towards root */",
+ "} Stack_Tree;",
+ "",
+ "H_el *grab_shared(int);",
+ "volatile Stack_Tree **stack_last; /* in shared memory */",
+ "char *stack_cache = NULL; /* local */",
+ "int nr_cached = 0; /* local */",
+ "",
+ "#ifndef CACHE_NR",
+ " #define CACHE_NR 1024",
+ "#endif",
+ "",
+ "volatile Stack_Tree *",
+ "stack_prefetch(void)",
+ "{ volatile Stack_Tree *st;",
+ "",
+ " if (nr_cached == 0)",
+ " { stack_cache = (char *) grab_shared(CACHE_NR * sizeof(Stack_Tree));",
+ " nr_cached = CACHE_NR;",
+ " }",
+ " st = (volatile Stack_Tree *) stack_cache;",
+ " stack_cache += sizeof(Stack_Tree);",
+ " nr_cached--;",
+ " return st;",
+ "}",
+ "",
+ "void",
+ "Push_Stack_Tree(short II, T_ID t_id)",
+ "{ volatile Stack_Tree *st;",
+ "",
+ " st = (volatile Stack_Tree *) stack_prefetch();",
+ " st->pr = II;",
+ " st->t_id = t_id;",
+ " st->prv = (Stack_Tree *) stack_last[core_id];",
+ " stack_last[core_id] = st;",
+ "}",
+ "",
+ "void",
+ "Pop_Stack_Tree(void)",
+ "{ volatile Stack_Tree *cf = stack_last[core_id];",
+ "",
+ " if (cf)",
+ " { stack_last[core_id] = cf->prv;",
+ " } else if (nr_handoffs * z_handoff + depth > 0)",
+ " { printf(\"cpu%%d: error pop_stack_tree (depth %%ld)\\n\",",
+ " core_id, depth);",
+ " }",
+ "}",
+ "#endif", /* NCORE>1 && FULL_TRAIL */
+ "",
+ "void",
+ "e_critical(int which)",
+ "{ double cnt_start;",
+ "",
+ " if (readtrail || iamin[which] > 0)",
+ " { if (!readtrail && verbose)",
+ " { printf(\"cpu%%d: Double Lock on %%d (now %%d)\\n\",",
+ " core_id, which, iamin[which]+1);",
+ " fflush(stdout);",
+ " }",
+ " iamin[which]++; /* local variable */",
+ " return;",
+ " }",
+ "",
+ " cnt_start = lock_wait;",
+ "",
+ " while (sh_lock != NULL) /* as long as we have shared memory */",
+ " { int r = tas(&sh_lock[which]);",
+ " if (r == 0)",
+ " { iamin[which] = 1;",
+ " return; /* locked */",
+ " }",
+ "",
+ " lock_wait++;",
+ "#ifndef NGQ",
+ " if (which < 3) { glock_wait[which]++; }",
+ "#else",
+ " if (which == 0) { glock_wait[which]++; }",
+ "#endif",
+ " iam_alive();",
+ "",
+ " if (lock_wait - cnt_start > TenSeconds)",
+ " { printf(\"cpu%%d: lock timeout on %%d\\n\", core_id, which);",
+ " cnt_start = lock_wait;",
+ " if (someone_crashed(1))",
+ " { sudden_stop(\"lock timeout\");",
+ " pan_exit(1);",
+ " } } }",
+ "}",
+ "",
+ "void",
+ "x_critical(int which)",
+ "{",
+ " if (iamin[which] != 1)",
+ " { if (iamin[which] > 1)",
+ " { iamin[which]--; /* this is thread-local - no races on this one */",
+ " if (!readtrail && verbose)",
+ " { printf(\"cpu%%d: Partial Unlock on %%d (%%d more needed)\\n\",",
+ " core_id, which, iamin[which]);",
+ " fflush(stdout);",
+ " }",
+ " return;",
+ " } else /* iamin[which] <= 0 */",
+ " { if (!readtrail)",
+ " { printf(\"cpu%%d: Invalid Unlock iamin[%%d] = %%d\\n\",",
+ " core_id, which, iamin[which]);",
+ " fflush(stdout);",
+ " }",
+ " return;",
+ " } }",
+ "",
+ " if (sh_lock != NULL)",
+ " { iamin[which] = 0;",
+ "#if defined(__powerpc64__)",
+ " #if 1",
+ " __sync_synchronize(); /* srirajpaul */",
+ " #else",
+ " __lwsync(); /* xlc compiler only */",
+ " #endif",
+ "#endif",
+ " sh_lock[which] = 0; /* unlock */",
+ " }",
+ "}",
+ "",
+ "void",
+ "#if defined(WIN32) || defined(WIN64)",
+ "start_proxy(char *s, DWORD r_pid)",
+ "#else",
+ "start_proxy(char *s, int r_pid)",
+ "#endif",
+ "{ char Q_arg[16], Z_arg[16], Y_arg[16];",
+ " char *args[32], *ptr;",
+ " int argcnt = 0;",
+ "",
+ " sprintf(Q_arg, \"-Q%%d\", getpid());",
+ " sprintf(Y_arg, \"-Y%%d\", r_pid);",
+ " sprintf(Z_arg, \"-Z%%d\", proxy_pid /* core_id */);",
+ "",
+ " args[argcnt++] = \"proxy\";",
+ " args[argcnt++] = s; /* -r or -s */",
+ " args[argcnt++] = Q_arg;",
+ " args[argcnt++] = Z_arg;",
+ " args[argcnt++] = Y_arg;",
+ "",
+ " if (strlen(o_cmdline) > 0)",
+ " { ptr = o_cmdline; /* assume args separated by spaces */",
+ " do { args[argcnt++] = ptr++;",
+ " if ((ptr = strchr(ptr, ' ')) != NULL)",
+ " { while (*ptr == ' ')",
+ " { *ptr++ = '\\0';",
+ " }",
+ " } else",
+ " { break;",
+ " }",
+ " } while (argcnt < 31);",
+ " }",
+ " args[argcnt] = NULL;",
+ "#if defined(WIN32) || defined(WIN64)",
+ " execvp(\"pan_proxy\", args); /* no return */",
+ "#else",
+ " execvp(\"./pan_proxy\", args); /* no return */",
+ "#endif",
+ " Uerror(\"pan_proxy exec failed\");",
+ "}",
+ "/*** end of common code fragment ***/",
+ "",
+ "#if !defined(WIN32) && !defined(WIN64)",
+ "void",
+ "init_shm(void) /* initialize shared work-queues - linux/cygwin */",
+ "{ key_t key[NR_QS];",
+ " int n, m;",
+ " int must_exit = 0;",
+ "",
+ " if (core_id == 0 && verbose)",
+ " { printf(\"cpu0: step 3: allocate shared workqueues %%g MB\\n\",",
+ " ((double) NCORE * LWQ_SIZE + GWQ_SIZE) / (1048576.) );",
+ " }",
+ " for (m = 0; m < NR_QS; m++) /* last q is the global q */",
+ " { double qsize = (m == NCORE) ? GWQ_SIZE : LWQ_SIZE;",
+ " key[m] = ftok(PanSource, m+1);", /* m must be nonzero, 1..NCORE */
+ " if (key[m] == -1)",
+ " { perror(\"ftok shared queues\"); must_exit = 1; break;",
+ " }",
+ "",
+ " if (core_id == 0) /* root creates */",
+ " { /* check for stale copy */",
+ " shmid[m] = shmget(key[m], (size_t) qsize, 0600);",
+ " if (shmid[m] != -1) /* yes there is one; remove it */",
+ " { printf(\"cpu0: removing stale q%%d, status: %%d\\n\",",
+ " m, shmctl(shmid[m], IPC_RMID, NULL));",
+ " }",
+ " shmid[m] = shmget(key[m], (size_t) qsize, 0600|IPC_CREAT|IPC_EXCL);",
+ " memcnt += qsize;",
+ " } else /* workers attach */",
+ " { shmid[m] = shmget(key[m], (size_t) qsize, 0600);",
+ " /* never called, since we create shm *before* we fork */",
+ " }",
+ " if (shmid[m] == -1)",
+ " { perror(\"shmget shared queues\"); must_exit = 1; break;",
+ " }",
+ "",
+ " shared_mem[m] = (char *) shmat(shmid[m], (void *) 0, 0); /* attach */",
+ " if (shared_mem[m] == (char *) -1)",
+ " { fprintf(stderr, \"error: cannot attach shared wq %%d (%%d Mb)\\n\",",
+ " m+1, (int) (qsize/(1048576.)));",
+ " perror(\"shmat shared queues\"); must_exit = 1; break;",
+ " }",
+ "",
+ " m_workq[m] = (SM_frame *) shared_mem[m];",
+ " if (core_id == 0)",
+ " { int nframes = (m == NCORE) ? GN_FRAMES : LN_FRAMES;",
+ " for (n = 0; n < nframes; n++)",
+ " { m_workq[m][n].m_vsize = 0;",
+ " m_workq[m][n].m_boq = 0;",
+ " } } }",
+ "",
+ " if (must_exit)",
+ " { rm_shared_segments();",
+ " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
+ " pan_exit(1); /* calls cleanup_shm */",
+ " }",
+ "}",
+ "",
+ "static uchar *",
+ "prep_shmid_S(size_t n) /* either sets SS or H_tab, linux/cygwin */",
+ "{ char *rval;",
+ "#ifndef SEP_STATE",
+ " key_t key;",
+ "",
+ " if (verbose && core_id == 0)",
+ " {",
+ " #ifdef BITSTATE",
+ " printf(\"cpu0: step 1: allocate shared bitstate %%g Mb\\n\",",
+ " (double) n / (1048576.));",
+ " #else",
+ " printf(\"cpu0: step 1: allocate shared hastable %%g Mb\\n\",",
+ " (double) n / (1048576.));",
+ " #endif",
+ " }",
+ " #ifdef MEMLIM", /* memlim has a value */
+ " if (memcnt + (double) n > memlim)",
+ " { printf(\"cpu0: S %%8g + %%d Kb exceeds memory limit of %%8g Mb\\n\",",
+ " memcnt/1024., (int) (n/1024), memlim/(1048576.));",
+ " printf(\"cpu0: insufficient memory -- aborting\\n\");",
+ " exit(1);",
+ " }",
+ " #endif",
+ "",
+ " key = ftok(PanSource, NCORE+2); /* different from queues */",
+ " if (key == -1)",
+ " { perror(\"ftok shared bitstate or hashtable\");",
+ " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
+ " pan_exit(1);",
+ " }",
+ "",
+ " if (core_id == 0) /* root */",
+ " { shmid_S = shmget(key, n, 0600);",
+ " if (shmid_S != -1)",
+ " { printf(\"cpu0: removing stale segment, status: %%d\\n\",",
+ " (int) shmctl(shmid_S, IPC_RMID, NULL));",
+ " }",
+ " shmid_S = shmget(key, n, 0600 | IPC_CREAT | IPC_EXCL);",
+ " memcnt += (double) n;",
+ " } else /* worker */",
+ " { shmid_S = shmget(key, n, 0600);",
+ " }",
+ " if (shmid_S == -1)",
+ " { perror(\"shmget shared bitstate or hashtable too large?\");",
+ " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
+ " pan_exit(1);",
+ " }",
+ "",
+ " rval = (char *) shmat(shmid_S, (void *) 0, 0); /* attach */",
+ " if ((char *) rval == (char *) -1)",
+ " { perror(\"shmat shared bitstate or hashtable\");",
+ " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
+ " pan_exit(1);",
+ " }",
+ "#else",
+ " rval = (char *) emalloc(n);",
+ "#endif",
+ " return (uchar *) rval;",
+ "}",
+ "",
+ "#define TRY_AGAIN 1",
+ "#define NOT_AGAIN 0",
+ "",
+ "static char shm_prep_result;",
+ "",
+ "static uchar *",
+ "prep_state_mem(size_t n) /* sets memory arena for states linux/cygwin */",
+ "{ char *rval;",
+ " key_t key;",
+ " static int cnt = 3; /* start larger than earlier ftok calls */",
+ "",
+ " shm_prep_result = NOT_AGAIN; /* default */",
+ " if (verbose && core_id == 0)",
+ " { printf(\"cpu0: step 2+: pre-allocate memory arena %%d of %%6.2g Mb\\n\",",
+ " cnt-3, (double) n / (1048576.));",
+ " }",
+ " #ifdef MEMLIM",
+ " if (memcnt + (double) n > memlim)",
+ " { printf(\"cpu0: error: M %%.0f + %%.0f Kb exceeds memory limit of %%.0f Mb\\n\",",
+ " memcnt/1024.0, (double) n/1024.0, memlim/(1048576.));",
+ " return NULL;",
+ " }",
+ " #endif",
+ "",
+ " key = ftok(PanSource, NCORE+cnt); cnt++;", /* starts at NCORE+3 */
+ " if (key == -1)",
+ " { perror(\"ftok T\");",
+ " printf(\"pan: check './pan --' for usage details\\n\");",
+ " pan_exit(1);",
+ " }",
+ "",
+ " if (core_id == 0)",
+ " { shmid_M = shmget(key, n, 0600);",
+ " if (shmid_M != -1)",
+ " { printf(\"cpu0: removing stale memory segment %%d, status: %%d\\n\",",
+ " cnt-3, shmctl(shmid_M, IPC_RMID, NULL));",
+ " }",
+ " shmid_M = shmget(key, n, 0600 | IPC_CREAT | IPC_EXCL);",
+ " /* memcnt += (double) n; -- only amount actually used is counted */",
+ " } else",
+ " { shmid_M = shmget(key, n, 0600);",
+ " ",
+ " }",
+ " if (shmid_M == -1)",
+ " { if (verbose)",
+ " { printf(\"error: failed to get pool of shared memory %%d of %%.0f Mb\\n\",",
+ " cnt-3, ((double)n)/(1048576.));",
+ " perror(\"state mem\");",
+ " printf(\"pan: check './pan --' for usage details\\n\");",
+ " }",
+ " shm_prep_result = TRY_AGAIN;",
+ " return NULL;",
+ " }",
+ " rval = (char *) shmat(shmid_M, (void *) 0, 0); /* attach */",
+ "",
+ " if ((char *) rval == (char *) -1)",
+ " { printf(\"cpu%%d error: failed to attach pool of shared memory %%d of %%.0f Mb\\n\",",
+ " core_id, cnt-3, ((double)n)/(1048576.));",
+ " perror(\"state mem\");",
+ " return NULL;",
+ " }",
+ " return (uchar *) rval;",
+ "}",
+ "",
+ "void",
+ "init_HT(unsigned long n) /* cygwin/linux version */",
+ "{ volatile char *x;",
+ " double get_mem;",
+ "#ifndef SEP_STATE",
+ " volatile char *dc_mem_start;",
+ " double need_mem, got_mem = 0.;",
+ "#endif",
+ "",
+"#ifdef SEP_STATE",
+ " #ifndef MEMLIM",
+ " if (verbose)",
+ " { printf(\"cpu0: steps 0,1: no -DMEMLIM set\\n\");", /* cannot happen */
+ " }",
+ " #else",
+ " if (verbose)",
+ " { printf(\"cpu0: steps 0,1: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb)\\n\",",
+ " MEMLIM, ((double)n/(1048576.)), (((double) NCORE * LWQ_SIZE) + GWQ_SIZE) /(1048576.) );",
+ " }",
+ " #endif",
+ " get_mem = NCORE * sizeof(double) + (1 + CS_NR) * sizeof(void *) + 4*sizeof(void *) + 2*sizeof(double);",
+ " /* NCORE * is_alive + search_terminated + CS_NR * sh_lock + 6 gr vars */",
+ " get_mem += 4 * NCORE * sizeof(void *); /* prfree, prfull, prcnt, prmax */",
+ " #ifdef FULL_TRAIL",
+ " get_mem += (NCORE) * sizeof(Stack_Tree *); /* NCORE * stack_last */",
+ " #endif",
+ " x = (volatile char *) prep_state_mem((size_t) get_mem); /* work queues and basic structs */",
+ " shmid_X = (long) x;",
+ " if (x == NULL)", /* do not repeat for smaller sizes */
+ " { printf(\"cpu0: could not allocate shared memory, see ./pan --\\n\");",
+ " exit(1);",
+ " }",
+ " search_terminated = (volatile unsigned int *) x; /* comes first */",
+ " x += sizeof(void *); /* maintain alignment */",
+ "",
+ " is_alive = (volatile double *) x;",
+ " x += NCORE * sizeof(double);",
+ "",
+ " sh_lock = (volatile int *) x;",
+ " x += CS_NR * sizeof(void *);", /* allow 1 word per entry */
+ "",
+ " grfree = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " grfull = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " grcnt = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " grmax = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " prfree = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " prfull = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " prcnt = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " prmax = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " gr_readmiss = (volatile double *) x;",
+ " x += sizeof(double);",
+ " gr_writemiss = (volatile double *) x;",
+ " x += sizeof(double);",
+ "",
+ " #ifdef FULL_TRAIL",
+ " stack_last = (volatile Stack_Tree **) x;",
+ " x += NCORE * sizeof(Stack_Tree *);",
+ " #endif",
+ "",
+ " #ifndef BITSTATE",
+ " H_tab = (H_el **) emalloc(n);",
+ " #endif",
+"#else",
+ " #ifndef MEMLIM",
+ " #warning MEMLIM not set", /* cannot happen */
+ " #define MEMLIM (2048)",
+ " #endif",
+ "",
+ " if (core_id == 0 && verbose)",
+ " { printf(\"cpu0: step 0: -DMEMLIM=%%d Mb minus hashtable+workqs (%%g + %%g Mb) leaves %%g Mb\\n\",",
+ " MEMLIM, ((double)n/(1048576.)), (NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.),",
+ " (memlim - memcnt - (double) n - (NCORE * LWQ_SIZE + GWQ_SIZE))/(1048576.));",
+ " }",
+ " #ifndef BITSTATE",
+ " H_tab = (H_el **) prep_shmid_S((size_t) n); /* hash_table */",
+ " #endif",
+ " need_mem = memlim - memcnt - ((double) NCORE * LWQ_SIZE) - GWQ_SIZE;",
+ " if (need_mem <= 0.)",
+ " { Uerror(\"internal error -- shared state memory\");",
+ " }",
+ "",
+ " if (core_id == 0 && verbose)",
+ " { printf(\"cpu0: step 2: pre-allocate shared state memory %%g Mb\\n\",",
+ " need_mem/(1048576.));",
+ " }",
+ "#ifdef SEP_HEAP",
+ " SEG_SIZE = need_mem / NCORE;",
+ " if (verbose && core_id == 0)",
+ " { printf(\"cpu0: setting segsize to %%6g MB\\n\",",
+ " SEG_SIZE/(1048576.));",
+ " }",
+ " #if defined(CYGWIN) || defined(__CYGWIN__)",
+ " if (SEG_SIZE > 512.*1024.*1024.)",
+ " { printf(\"warning: reducing SEG_SIZE of %%g MB to 512MB (exceeds max for Cygwin)\\n\",",
+ " SEG_SIZE/(1024.*1024.));",
+ " SEG_SIZE = 512.*1024.*1024.;",
+ " }",
+ " #endif",
+ "#endif",
+ " mem_reserved = need_mem;",
+ " while (need_mem > 1024.)",
+ " { get_mem = need_mem;",
+ "shm_more:",
+ " if (get_mem > (double) SEG_SIZE)",
+ " { get_mem = (double) SEG_SIZE;",
+ " }",
+ " if (get_mem <= 0.0) break;",
+ "",
+ " /* for allocating states: */",
+ " x = dc_mem_start = (volatile char *) prep_state_mem((size_t) get_mem);",
+ " if (x == NULL)",
+ " { if (shm_prep_result == NOT_AGAIN",
+ " || first_pool != NULL",
+ " || SEG_SIZE < (16. * 1048576.))",
+ " { break;",
+ " }",
+ " SEG_SIZE /= 2.;",
+ " if (verbose)",
+ " { printf(\"pan: lowered segsize to %%f\\n\", SEG_SIZE);",
+ " }",
+ " if (SEG_SIZE >= 1024.)",
+ " { goto shm_more;", /* always terminates */
+ " }",
+ " break;",
+ " }",
+ "",
+ " need_mem -= get_mem;",
+ " got_mem += get_mem;",
+ " if (first_pool == NULL)",
+ " { search_terminated = (volatile unsigned int *) x; /* comes first */",
+ " x += sizeof(void *); /* maintain alignment */",
+ "",
+ " is_alive = (volatile double *) x;",
+ " x += NCORE * sizeof(double);",
+ "",
+ " sh_lock = (volatile int *) x;",
+ " x += CS_NR * sizeof(void *);", /* allow 1 word per entry */
+ "",
+ " grfree = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " grfull = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " grcnt = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " grmax = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " prfree = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " prfull = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " prcnt = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " prmax = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " gr_readmiss = (volatile double *) x;",
+ " x += sizeof(double);",
+ " gr_writemiss = (volatile double *) x;",
+ " x += sizeof(double);",
+ " #ifdef FULL_TRAIL",
+ " stack_last = (volatile Stack_Tree **) x;",
+ " x += NCORE * sizeof(Stack_Tree *);",
+ " #endif",
+ " if (((long)x)&(sizeof(void *)-1)) /* 64-bit word alignment */",
+ " { x += sizeof(void *)-(((long)x)&(sizeof(void *)-1));",
+ " }",
+ "",
+ " #ifdef COLLAPSE",
+ " ncomps = (unsigned long *) x;",
+ " x += (256+2) * sizeof(unsigned long);",
+ " #endif",
+ " }",
+ "",
+ " dc_shared = (sh_Allocater *) x; /* must be in shared memory */",
+ " x += sizeof(sh_Allocater);",
+ "",
+ " if (core_id == 0) /* root only */",
+ " { dc_shared->dc_id = shmid_M;",
+ " dc_shared->dc_start = dc_mem_start;",
+ " dc_shared->dc_arena = x;",
+ " dc_shared->pattern = 1234567; /* protection */",
+ " dc_shared->dc_size = (long) get_mem - (long) (x - dc_mem_start);",
+ " dc_shared->nxt = (long) 0;",
+ "",
+ " if (last_pool == NULL)",
+ " { first_pool = last_pool = dc_shared;",
+ " } else",
+ " { last_pool->nxt = dc_shared;",
+ " last_pool = dc_shared;",
+ " }",
+ " } else if (first_pool == NULL)",
+ " { first_pool = dc_shared;",
+ " } }",
+ "",
+ " if (need_mem > 1024.)",
+ " { printf(\"cpu0: could allocate only %%g Mb of shared memory (wanted %%g more)\\n\",",
+ " got_mem/(1048576.), need_mem/(1048576.));",
+ " }",
+ "",
+ " if (!first_pool)",
+ " { printf(\"cpu0: insufficient memory -- aborting.\\n\");",
+ " exit(1);",
+ " }",
+ " /* we are still single-threaded at this point, with core_id 0 */",
+ " dc_shared = first_pool;",
+ "",
+"#endif", /* !SEP_STATE */
+ "}",
+ "",
+ "void",
+ "cleanup_shm(int val)",
+ "{ volatile sh_Allocater *nxt_pool;",
+ " unsigned long cnt = 0;",
+ " int m;",
+ "",
+ " if (nibis != 0)",
+ " { printf(\"cpu%%d: Redundant call to cleanup_shm(%%d)\\n\", core_id, val);",
+ " return;",
+ " } else",
+ " { nibis = 1;",
+ " }",
+ " if (search_terminated != NULL)",
+ " { *search_terminated |= 16; /* cleanup_shm */",
+ " }",
+ "",
+ " for (m = 0; m < NR_QS; m++)",
+ " { if (shmdt((void *) shared_mem[m]) > 0)",
+ " { perror(\"shmdt detaching from shared queues\");",
+ " } }",
+ "",
+ "#ifdef SEP_STATE",
+ " if (shmdt((void *) shmid_X) != 0)",
+ " { perror(\"shmdt detaching from shared state memory\");",
+ " }",
+ "#else",
+ " #ifdef BITSTATE",
+ " if (SS > 0 && shmdt((void *) SS) != 0)",
+ " { if (verbose)",
+ " { perror(\"shmdt detaching from shared bitstate arena\");",
+ " } }",
+ " #else",
+ " if (core_id == 0)",
+ " { /* before detaching: */",
+ " for (nxt_pool = dc_shared; nxt_pool != NULL; nxt_pool = nxt_pool->nxt)",
+ " { cnt += nxt_pool->dc_size;",
+ " }",
+ " if (verbose)",
+ " { printf(\"cpu0: done, %%ld Mb of shared state memory left\\n\",",
+ " cnt / (long)(1048576));",
+ " } }",
+ "",
+ " if (shmdt((void *) H_tab) != 0)",
+ " { perror(\"shmdt detaching from shared hashtable\");",
+ " }",
+ "",
+ " for (last_pool = first_pool; last_pool != NULL; last_pool = nxt_pool)",
+ " { nxt_pool = last_pool->nxt;",
+ " if (shmdt((void *) last_pool->dc_start) != 0)",
+ " { perror(\"shmdt detaching from shared state memory\");",
+ " } }",
+ " first_pool = last_pool = NULL; /* precaution */",
+ " #endif",
+ "#endif",
+ " /* detached from shared memory - so cannot use cpu_printf */",
+ " if (verbose)",
+ " { printf(\"cpu%%d: done -- got %%ld states from queue\\n\",",
+ " core_id, nstates_get);",
+ " }",
+ "}",
+ "",
+ "extern void give_up(int);",
+ "extern void Read_Queue(int);",
+ "",
+ "void",
+ "mem_get(void)",
+ "{ SM_frame *f;",
+ " int is_parent;",
+ "",
+ "#if defined(MA) && !defined(SEP_STATE)",
+ " #error MA without SEP_STATE is not supported with multi-core",
+ "#endif",
+ "#ifdef BFS",
+ " #error instead of -DNCORE -DBFS use -DBFS_PAR",
+ "#endif",
+ "#ifdef SC",
+ " #error SC is not supported with multi-core",
+ "#endif",
+ " init_shm(); /* we are single threaded when this starts */",
+ "",
+ " if (core_id == 0 && verbose)",
+ " { printf(\"cpu0: step 4: calling fork()\\n\");",
+ " }",
+ " fflush(stdout);",
+ "",
+ "/* if NCORE > 1 the child or the parent should fork N-1 more times",
+ " * the parent is the only process with core_id == 0 and is_parent > 0",
+ " * the workers have is_parent = 0 and core_id = 1..NCORE-1",
+ " */",
+ " if (core_id == 0)",
+ " { worker_pids[0] = getpid(); /* for completeness */",
+ " while (++core_id < NCORE) /* first worker sees core_id = 1 */",
+ " { is_parent = fork();",
+ " if (is_parent == -1)",
+ " { Uerror(\"fork failed\");",
+ " }",
+ " if (is_parent == 0) /* this is a worker process */",
+ " { if (proxy_pid == core_id) /* always non-zero */",
+ " { start_proxy(\"-r\", 0); /* no return */",
+ " }",
+ " goto adapt; /* root process continues spawning */",
+ " }",
+ " worker_pids[core_id] = is_parent;",
+ " }",
+ " /* note that core_id is now NCORE */",
+ " if (proxy_pid > 0 && proxy_pid < NCORE)", /* add send-half of proxy */
+ " { proxy_pid_snd = fork();",
+ " if (proxy_pid_snd == -1)",
+ " { Uerror(\"proxy fork failed\");",
+ " }",
+ " if (proxy_pid_snd == 0)",
+ " { start_proxy(\"-s\", worker_pids[proxy_pid]); /* no return */",
+ " } } /* else continue */",
+
+ " if (is_parent > 0)",
+ " { core_id = 0; /* reset core_id for root process */",
+ " }",
+ " } else /* worker */",
+ " { static char db0[16]; /* good for up to 10^6 cores */",
+ " static char db1[16];",
+ "adapt: tprefix = db0; sprefix = db1;",
+ " sprintf(tprefix, \"cpu%%d_trail\", core_id);",
+ " sprintf(sprefix, \"cpu%%d_rst\", core_id);",
+ " memcnt = 0; /* count only additionally allocated memory */",
+ " }",
+ " signal(SIGINT, give_up);",
+ "",
+ " if (proxy_pid == 0) /* not in a cluster setup, pan_proxy must attach */",
+ " { rm_shared_segments(); /* mark all shared segments for removal on exit */",
+ " }", /* doing it early means less chance of being unable to do this */
+ " if (verbose)",
+ " { cpu_printf(\"starting core_id %%d -- pid %%d\\n\", core_id, getpid());",
+ " }",
+
+ "#if defined(SEP_HEAP) && !defined(SEP_STATE)", /* set my_heap and adjust dc_shared */
+ " { int i;",
+ " volatile sh_Allocater *ptr;",
+ " ptr = first_pool;",
+ " for (i = 0; i < NCORE && ptr != NULL; i++)",
+ " { if (i == core_id)",
+ " { my_heap = (char *) ptr->dc_arena;",
+ " my_size = (long) ptr->dc_size;",
+ " if (verbose)",
+ " cpu_printf(\"local heap %%ld MB\\n\", my_size/(1048576));",
+ " break;",
+ " }",
+ " ptr = ptr->nxt; /* local */",
+ " }",
+ " if (my_heap == NULL)",
+ " { printf(\"cpu%%d: no local heap\\n\", core_id);",
+ " pan_exit(1);",
+ " } /* else */",
+ " #if defined(CYGWIN) || defined(__CYGWIN__)",
+ " ptr = first_pool;",
+ " for (i = 0; i < NCORE && ptr != NULL; i++)",
+ " { ptr = ptr->nxt; /* local */",
+ " }",
+ " dc_shared = ptr; /* any remainder */",
+ " #else",
+ " dc_shared = NULL; /* used all mem for local heaps */",
+ " #endif",
+ " }",
+ "#endif",
+
+ " if (core_id == 0 && !remote_party)",
+ " { new_state(); /* cpu0 explores root */",
+ " if (verbose)",
+ " cpu_printf(\"done with 1st dfs, nstates %%g (put %%d states), read q\\n\",",
+ " nstates, nstates_put);",
+ " dfs_phase2 = 1;",
+ " }",
+ " Read_Queue(core_id); /* all cores */",
+ "",
+ " if (verbose)",
+ " { cpu_printf(\"put %%6d states into queue -- got %%6d\\n\",",
+ " nstates_put, nstates_get);",
+ " }",
+ " if (proxy_pid != 0)",
+ " { rm_shared_segments();",
+ " }",
+ " done = 1;",
+ " wrapup();",
+ " exit(0);",
+ "}",
+ "",
+ "#else",
+ "int unpack_state(SM_frame *, int);",
+ "#endif",
+ "",
+ "H_el *",
+ "grab_shared(int n)",
+ "{",
+ "#ifndef SEP_STATE",
+ " char *rval = (char *) 0;",
+ "",
+ " if (n == 0)",
+ " { printf(\"cpu%%d: grab shared zero\\n\", core_id); fflush(stdout);",
+ " return (H_el *) rval;",
+ " } else if (n&(sizeof(void *)-1))",
+ " { n += sizeof(void *)-(n&(sizeof(void *)-1)); /* alignment */",
+ " }",
+ "",
+ "#ifdef SEP_HEAP",
+ " /* no locking */",
+ " if (my_heap != NULL && my_size > n)",
+ " { rval = my_heap;",
+ " my_heap += n;",
+ " my_size -= n;",
+ " goto done;",
+ " }",
+ "#endif",
+ "",
+ " if (!dc_shared)",
+ " { sudden_stop(\"pan: out of memory\");",
+ " }",
+ "",
+ " /* another lock is always already in effect when this is called */",
+ " /* but not always the same lock -- i.e., on different parts of the hashtable */",
+ " enter_critical(GLOBAL_LOCK); /* this must be independently mutex */",
+ "#if defined(SEP_HEAP) && !defined(WIN32) && !defined(WIN64)",
+ " { static int noted = 0;",
+ " if (!noted)",
+ " { noted = 1;",
+ " printf(\"cpu%%d: global heap has %%ld bytes left, needed %%d\\n\",",
+ " core_id, dc_shared?dc_shared->dc_size:0, n);",
+ " } }",
+ "#endif",
+ "#if 0", /* for debugging */
+ " if (dc_shared->pattern != 1234567)",
+ " { leave_critical(GLOBAL_LOCK);",
+ " Uerror(\"overrun -- memory corruption\");",
+ " }",
+ "#endif",
+ " if (dc_shared->dc_size < n)",
+ " { if (verbose)",
+ " { printf(\"Next Pool %%g Mb + %%d\\n\", memcnt/(1048576.), n);",
+ " }",
+ " if (dc_shared->nxt == NULL",
+ " || dc_shared->nxt->dc_arena == NULL",
+ " || dc_shared->nxt->dc_size < n)",
+ " { printf(\"cpu%%d: memcnt %%g Mb + wanted %%d bytes more\\n\",",
+ " core_id, memcnt / (1048576.), n);",
+ " leave_critical(GLOBAL_LOCK);",
+ " sudden_stop(\"out of memory -- aborting\");",
+ " wrapup(); /* exits */",
+ " } else",
+ " { dc_shared = (sh_Allocater *) dc_shared->nxt;",
+ " } }",
+ "",
+ " rval = (char *) dc_shared->dc_arena;",
+ " dc_shared->dc_arena += n;",
+ " dc_shared->dc_size -= (long) n;",
+ "#if 0",
+ " if (VVERBOSE)",
+ " printf(\"cpu%%d grab shared (%%d bytes) -- %%ld left\\n\",",
+ " core_id, n, dc_shared->dc_size);",
+ "#endif",
+ " leave_critical(GLOBAL_LOCK);",
+ "done:",
+ " memset(rval, 0, n);",
+ " memcnt += (double) n;",
+ "",
+ " return (H_el *) rval;",
+ "#else",
+ " return (H_el *) emalloc(n);",
+ "#endif",
+ "}",
+ "",
+ "SM_frame *",
+ "Get_Full_Frame(int n)",
+ "{ SM_frame *f;",
+ " double cnt_start = frame_wait;",
+ "",
+ " f = &m_workq[n][prfull[n]];",
+ " while (f->m_vsize == 0) /* await full slot LOCK : full frame */",
+ " { iam_alive();",
+ "#ifndef NGQ",
+ " #ifndef SAFETY",
+ " if (!a_cycles || core_id != 0)",
+ " #endif",
+ " if (*grcnt > 0) /* accessed outside lock, but safe even if wrong */",
+ " { enter_critical(GQ_RD); /* gq - read access */",
+ " if (*grcnt > 0) /* could have changed */",
+ " { f = &m_workq[NCORE][*grfull]; /* global q */",
+ " if (f->m_vsize == 0)",
+ " { /* writer is still filling the slot */",
+ " *gr_writemiss++;",
+ " f = &m_workq[n][prfull[n]]; /* reset */",
+ " } else",
+ " { *grfull = (*grfull+1) %% (GN_FRAMES);",
+ " enter_critical(GQ_WR);",
+ " *grcnt = *grcnt - 1;",
+ " leave_critical(GQ_WR);",
+ " leave_critical(GQ_RD);",
+ " return f;",
+ " } }",
+ " leave_critical(GQ_RD);",
+ " }",
+ "#endif",
+ " if (frame_wait++ - cnt_start > Delay)",
+ " { if (0)", /* too frequent to enable this one */
+ " { cpu_printf(\"timeout on q%%d -- %%u -- query %%d\\n\",",
+ " n, f, query_in_progress);",
+ " }",
+ " return (SM_frame *) 0; /* timeout */",
+ " } }",
+ " iam_alive();",
+ " if (VVERBOSE) cpu_printf(\"got frame from q%%d\\n\", n);",
+ " prfull[n] = (prfull[n] + 1) %% (LN_FRAMES);",
+ " enter_critical(QLOCK(n));",
+ " prcnt[n]--; /* lock out increments */",
+ " leave_critical(QLOCK(n));",
+ " return f;",
+ "}",
+ "",
+ "SM_frame *",
+ "Get_Free_Frame(int n)",
+ "{ SM_frame *f;",
+ " double cnt_start = free_wait;",
+ "",
+ " if (VVERBOSE) { cpu_printf(\"get free frame from q%%d\\n\", n); }",
+ "",
+ " if (n == NCORE) /* global q */",
+ " { f = &(m_workq[n][lrfree]);",
+ " } else",
+ " { f = &(m_workq[n][prfree[n]]);",
+ " }",
+ " while (f->m_vsize != 0) /* await free slot LOCK : free slot */",
+ " { iam_alive();",
+ " if (free_wait++ - cnt_start > OneSecond)",
+ " { if (verbose)",
+ " { cpu_printf(\"timeout waiting for free slot q%%d\\n\", n);",
+ " }",
+ " cnt_start = free_wait;",
+ " if (someone_crashed(1))",
+ " { printf(\"cpu%%d: search terminated\\n\", core_id);",
+ " sudden_stop(\"get free frame\");",
+ " pan_exit(1);",
+ " } } }",
+ " if (n != NCORE)",
+ " { prfree[n] = (prfree[n] + 1) %% (LN_FRAMES);",
+ " enter_critical(QLOCK(n));",
+ " prcnt[n]++; /* lock out decrements */",
+ " if (prmax[n] < prcnt[n])",
+ " { prmax[n] = prcnt[n];",
+ " }",
+ " leave_critical(QLOCK(n));",
+ " }",
+ " return f;",
+ "}",
+ "",
+ "#ifndef NGQ",
+ "int",
+ "GlobalQ_HasRoom(void)",
+ "{ int rval = 0;",
+ "",
+ " gq_tries++;",
+ " if (*grcnt < GN_FRAMES) /* there seems to be room */",
+ " { enter_critical(GQ_WR); /* gq write access */",
+ " if (*grcnt < GN_FRAMES)",
+ " { if (m_workq[NCORE][*grfree].m_vsize != 0)",
+ " { /* can happen if reader is slow emptying slot */",
+ " *gr_readmiss++;",
+ " goto out; /* dont wait: release lock and return */",
+ " }",
+ " lrfree = *grfree; /* Get_Free_Frame use lrfree in this mode */",
+ " *grfree = (*grfree + 1) %% GN_FRAMES;", /* next process looks at next slot */
+ " *grcnt = *grcnt + 1; /* count nr of slots filled -- no additional lock needed */",
+ " if (*grmax < *grcnt) *grmax = *grcnt;",
+ " leave_critical(GQ_WR); /* for short lock duration */",
+ " gq_hasroom++;",
+ " mem_put(NCORE); /* copy state into reserved slot */",
+ " rval = 1; /* successfull handoff */",
+ " } else",
+ " { gq_hasnoroom++;",
+ "out: leave_critical(GQ_WR);", /* should be rare */
+ " } }",
+ " return rval;",
+ "}",
+ "#endif",
+ "",
+ "int",
+ "unpack_state(SM_frame *f, int from_q)",
+ "{ int i, j;",
+ " static H_el D_State;",
+ "",
+ " if (f->m_vsize > 0)",
+ " { boq = f->m_boq;",
+ " if (boq > 256)",
+ " { cpu_printf(\"saw control %%d, expected state\\n\", boq);",
+ " return 0;",
+ " }",
+ " vsize = f->m_vsize;",
+ "correct:",
+ " memcpy((uchar *) &now, (uchar *) f->m_now, vsize);",
+ " #if !defined(NOCOMP) && !defined(HC)",
+ " for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)",
+ " { Mask[i] = (f->m_mask[i/8] & (1<<j)) ? 1 : 0;",
+ " }",
+ " #endif",
+ " if (now._nr_pr > 0)",
+ " { memcpy((uchar *) proc_offset, (uchar *) f->m_p_offset, now._nr_pr * sizeof(OFFT));",
+ " memcpy((uchar *) proc_skip, (uchar *) f->m_p_skip, now._nr_pr * sizeof(uchar));",
+ " }",
+ " if (now._nr_qs > 0)",
+ " { memcpy((uchar *) q_offset, (uchar *) f->m_q_offset, now._nr_qs * sizeof(OFFT));",
+ " memcpy((uchar *) q_skip, (uchar *) f->m_q_skip, now._nr_qs * sizeof(uchar));",
+ " }",
+ "#ifndef NOVSZ",
+ " if (vsize != now._vsz)",
+ " { cpu_printf(\"vsize %%d != now._vsz %%d (type %%d) %%d\\n\",",
+ " vsize, now._vsz, f->m_boq, f->m_vsize);",
+ " vsize = now._vsz;",
+ " goto correct; /* rare event: a race */",
+ " }",
+ "#endif",
+ " hmax = max(hmax, vsize);",
+ "",
+ " if (f != &cur_Root)",
+ " { memcpy((uchar *) &cur_Root, (uchar *) f, sizeof(SM_frame));",
+ " }",
+ "",
+ " if (((now._a_t) & 1) == 1) /* i.e., when starting nested DFS */",
+ " { A_depth = depthfound = 0;",
+ " memcpy((uchar *)&A_Root, (uchar *)&now, vsize);",
+ " }",
+ " nr_handoffs = f->nr_handoffs;",
+ " } else",
+ " { cpu_printf(\"pan: state empty\\n\");",
+ " }",
+ "",
+ " depth = 0;",
+ " trpt = &trail[1];",
+ " trpt->tau = f->m_tau;",
+ " trpt->o_pm = f->m_o_pm;",
+ "",
+ " (trpt-1)->ostate = &D_State; /* stub */",
+ " trpt->ostate = &D_State;",
+ "",
+ "#ifdef FULL_TRAIL",
+ " if (upto > 0)",
+ " { stack_last[core_id] = (Stack_Tree *) f->m_stack;",
+ " }",
+ " #if defined(VERBOSE)",
+ " if (stack_last[core_id])",
+ " { cpu_printf(\"%%d: UNPACK -- SET m_stack %%u (%%d,%%d)\\n\",",
+ " depth, stack_last[core_id], stack_last[core_id]->pr,",
+ " stack_last[core_id]->t_id);",
+ " }",
+ " #endif",
+ "#endif",
+ "",
+ " if (!trpt->o_t)",
+ " { static Trans D_Trans;",
+ " trpt->o_t = &D_Trans;",
+ " }",
+ "",
+ " #ifdef VERI",
+ " if ((trpt->tau & 4) != 4)",
+ " { trpt->tau |= 4; /* the claim moves first */",
+ " cpu_printf(\"warning: trpt was not up to date\\n\");",
+ " }",
+ " #endif",
+ "",
+ " for (i = 0; i < (int) now._nr_pr; i++)",
+ " { P0 *ptr = (P0 *) pptr(i);",
+ " #ifndef NP",
+ " if (accpstate[ptr->_t][ptr->_p])",
+ " { trpt->o_pm |= 2;",
+ " }",
+ " #else",
+ " if (progstate[ptr->_t][ptr->_p])",
+ " { trpt->o_pm |= 4;",
+ " }",
+ " #endif",
+ " }",
+ "",
+ " #ifdef EVENT_TRACE",
+ " #ifndef NP",
+ " if (accpstate[EVENT_TRACE][now._event])",
+ " { trpt->o_pm |= 2;",
+ " }",
+ " #else",
+ " if (progstate[EVENT_TRACE][now._event])",
+ " { trpt->o_pm |= 4;",
+ " }",
+ " #endif",
+ " #endif",
+ "",
+ " #if defined(C_States) && (HAS_TRACK==1)",
+ " /* restore state of tracked C objects */",
+ " c_revert((uchar *) &(now.c_state[0]));",
+ " #if (HAS_STACK==1)",
+ " c_unstack((uchar *) f->m_c_stack); /* unmatched tracked data */",
+ " #endif",
+ " #endif",
+ " return 1;",
+ "}",
+ "",
+ "void",
+ "write_root(void) /* for trail file */",
+ "{ int fd;",
+ "",
+ " if (iterative == 0 && Nr_Trails > 1)",
+ " sprintf(fnm, \"%%s%%d.%%s\", TrailFile, Nr_Trails-1, sprefix);",
+ " else",
+ " sprintf(fnm, \"%%s.%%s\", TrailFile, sprefix);",
+ "",
+ " if (cur_Root.m_vsize == 0)",
+ " { (void) unlink(fnm); /* remove possible old copy */",
+ " return; /* its the default initial state */",
+ " }",
+ "",
+ " if ((fd = creat(fnm, TMODE)) < 0)",
+ " { char *q;",
+ " if ((q = strchr(TrailFile, \'.\')))",
+ " { *q = \'\\0\'; /* strip .pml */",
+ " if (iterative == 0 && Nr_Trails-1 > 0)",
+ " sprintf(fnm, \"%%s%%d.%%s\", TrailFile, Nr_Trails-1, sprefix);",
+ " else",
+ " sprintf(fnm, \"%%s.%%s\", TrailFile, sprefix);",
+ " *q = \'.\';",
+ " fd = creat(fnm, TMODE);",
+ " }",
+ " if (fd < 0)",
+ " { cpu_printf(\"pan: cannot create %%s\\n\", fnm);",
+ " perror(\"cause\");",
+ " return;",
+ " } }",
+ "",
+ " if (write(fd, &cur_Root, sizeof(SM_frame)) != sizeof(SM_frame))",
+ " { cpu_printf(\"pan: error writing %%s\\n\", fnm);",
+ " } else",
+ " { cpu_printf(\"pan: wrote %%s\\n\", fnm);",
+ " }",
+ " close(fd);",
+ "}",
+ "",
+ "void",
+ "set_root(void)",
+ "{ int fd;",
+ " char *q;",
+ " char MyFile[512];", /* enough to hold a reasonable pathname */
+ " char MySuffix[16];",
+ " char *ssuffix = \"rst\";",
+ " int try_core = 1;",
+ "",
+ " strcpy(MyFile, TrailFile);",
+ "try_again:",
+ " if (whichtrail > 0)",
+ " { sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, ssuffix);",
+ " fd = open(fnm, O_RDONLY, 0);",
+ " if (fd < 0 && (q = strchr(MyFile, \'.\')))",
+ " { *q = \'\\0\'; /* strip .pml */",
+ " sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, ssuffix);",
+ " *q = \'.\';",
+ " fd = open(fnm, O_RDONLY, 0);",
+ " }",
+ " } else",
+ " { sprintf(fnm, \"%%s.%%s\", MyFile, ssuffix);",
+ " fd = open(fnm, O_RDONLY, 0);",
+ " if (fd < 0 && (q = strchr(MyFile, \'.\')))",
+ " { *q = \'\\0\'; /* strip .pml */",
+ " sprintf(fnm, \"%%s.%%s\", MyFile, ssuffix);",
+ " *q = \'.\';",
+ " fd = open(fnm, O_RDONLY, 0);",
+ " } }",
+ "",
+ " if (fd < 0)",
+ " { if (try_core < NCORE)",
+ " { ssuffix = MySuffix;",
+ " sprintf(ssuffix, \"cpu%%d_rst\", try_core++);",
+ " goto try_again;",
+ " }",
+ " cpu_printf(\"no file '%%s.rst' or '%%s' (not an error)\\n\", MyFile, fnm);",
+ " } else",
+ " { if (read(fd, &cur_Root, sizeof(SM_frame)) != sizeof(SM_frame))",
+ " { cpu_printf(\"read error %%s\\n\", fnm);",
+ " close(fd);",
+ " pan_exit(1);",
+ " }",
+ " close(fd);",
+ " (void) unpack_state(&cur_Root, -2);",
+ "#ifdef SEP_STATE",
+ " cpu_printf(\"partial trail -- last few steps only\\n\");",
+ "#endif",
+ " cpu_printf(\"restored root from '%%s'\\n\", fnm);",
+ " printf(\"=====State:=====\\n\");",
+ " { int i, j; P0 *z;",
+ " for (i = 0; i < now._nr_pr; i++)",
+ " { z = (P0 *)pptr(i);",
+ " printf(\"proc %%2d (%%s) \", i, procname[z->_t]);",
+
+ " for (j = 0; src_all[j].src; j++)",
+ " if (src_all[j].tp == (int) z->_t)",
+ " { printf(\" %%s:%%d \",",
+ " PanSource, src_all[j].src[z->_p]);",
+ " break;",
+ " }",
+ " printf(\"(state %%d)\\n\", z->_p);",
+ " c_locals(i, z->_t);",
+ " }",
+ " c_globals();",
+ " }",
+ " printf(\"================\\n\");",
+ " }",
+ "}",
+ "",
+ "#ifdef USE_DISK",
+ "unsigned long dsk_written, dsk_drained;",
+ "void mem_drain(void);",
+ "#endif",
+ "",
+ "void",
+ "m_clear_frame(SM_frame *f)", /* clear room for stats */
+ "{ int i, clr_sz = sizeof(SM_results);",
+ "",
+ " for (i = 0; i <= _NP_; i++) /* all proctypes */",
+ " { clr_sz += NrStates[i]*sizeof(uchar);",
+ " }",
+ " memset(f, 0, clr_sz);",
+ " /* caution if sizeof(SM_results) > sizeof(SM_frame) */",
+ "}",
+ "",
+ "#define TargetQ_Full(n) (m_workq[n][prfree[n]].m_vsize != 0)", /* no free slot */
+ "#define TargetQ_NotFull(n) (m_workq[n][prfree[n]].m_vsize == 0)", /* avoiding prcnt */
+ "",
+ "int",
+ "AllQueuesEmpty(void)",
+ "{ int q;",
+ "#ifndef NGQ",
+ " if (*grcnt != 0)",
+ " { return 0;",
+ " }",
+ "#endif",
+ " for (q = 0; q < NCORE; q++)",
+ " { if (prcnt[q] != 0)", /* not locked, ok if race */
+ " { return 0;",
+ " } }",
+ " return 1;",
+ "}",
+ "",
+ "void",
+ "Read_Queue(int q)",
+ "{ SM_frame *f, *of;",
+ " int remember, target_q;",
+ " SM_results *r;",
+ " double patience = 0.0;",
+ "",
+ " target_q = (q + 1) %% NCORE;",
+ "",
+ " for (;;)",
+ " { f = Get_Full_Frame(q);",
+ " if (!f) /* 1 second timeout -- and trigger for Query */",
+ " { if (someone_crashed(2))",
+ " { printf(\"cpu%%d: search terminated [code %%d]\\n\",",
+ " core_id, search_terminated?*search_terminated:-1);",
+ " sudden_stop(\"\");",
+ " pan_exit(1);",
+ " }",
+ "#ifdef TESTING",
+ " /* to profile with cc -pg and gprof pan.exe -- set handoff depth beyond maxdepth */",
+ " exit(0);",
+ "#endif",
+ " remember = *grfree;",
+ " if (core_id == 0 /* root can initiate termination */",
+ " && remote_party == 0 /* and only the original root */",
+ " && query_in_progress == 0 /* unless its already in progress */",
+ " && AllQueuesEmpty())",
+ " { f = Get_Free_Frame(target_q);",
+ " query_in_progress = 1; /* only root process can do this */",
+ " if (!f) { Uerror(\"Fatal1: no free slot\"); }",
+ " f->m_boq = QUERY; /* initiate Query */",
+ " if (verbose)",
+ " { cpu_printf(\"snd QUERY to q%%d (%%d) into slot %%d\\n\",",
+ " target_q, nstates_get + 1, prfree[target_q]-1);",
+ " }",
+ " f->m_vsize = remember + 1;",
+ " /* number will not change unless we receive more states */",
+ " } else if (patience++ > OneHour) /* one hour watchdog timer */",
+ " { cpu_printf(\"timeout -- giving up\\n\");",
+ " sudden_stop(\"queue timeout\");",
+ " pan_exit(1);",
+ " }",
+ " if (0) cpu_printf(\"timed out -- try again\\n\");",
+ " continue; ",
+ " }",
+ " patience = 0.0; /* reset watchdog */",
+ "",
+ " if (f->m_boq == QUERY)",
+ " { if (verbose)",
+ " { cpu_printf(\"got QUERY on q%%d (%%d <> %%d) from slot %%d\\n\",",
+ " q, f->m_vsize, nstates_put + 1, prfull[q]-1);",
+ " snapshot();",
+ " }",
+ " remember = f->m_vsize;",
+ " f->m_vsize = 0; /* release slot */",
+ "",
+ " if (core_id == 0 && remote_party == 0) /* original root cpu0 */",
+ " { if (query_in_progress == 1 /* didn't send more states in the interim */",
+ " && *grfree + 1 == remember) /* no action on global queue meanwhile */",
+ " { if (verbose) cpu_printf(\"Termination detected\\n\");",
+ " if (TargetQ_Full(target_q))",
+ " { if (verbose)",
+ " cpu_printf(\"warning: target q is full\\n\");",
+ " }",
+ " f = Get_Free_Frame(target_q);",
+ " if (!f) { Uerror(\"Fatal2: no free slot\"); }",
+ " m_clear_frame(f);",
+ " f->m_boq = QUIT; /* send final Quit, collect stats */",
+ " f->m_vsize = 111; /* anything non-zero will do */",
+ " if (verbose)",
+ " cpu_printf(\"put QUIT on q%%d\\n\", target_q);",
+ " } else",
+ " { if (verbose) cpu_printf(\"Stale Query\\n\");",
+ "#ifdef USE_DISK",
+ " mem_drain();",
+ "#endif",
+ " }",
+ " query_in_progress = 0;",
+ " } else",
+ " { if (TargetQ_Full(target_q))",
+ " { if (verbose)",
+ " cpu_printf(\"warning: forward query - target q full\\n\");",
+ " }",
+ " f = Get_Free_Frame(target_q);",
+ " if (verbose)",
+ " cpu_printf(\"snd QUERY response to q%%d (%%d <> %%d) in slot %%d\\n\",",
+ " target_q, remember, *grfree + 1, prfree[target_q]-1);",
+ " if (!f) { Uerror(\"Fatal4: no free slot\"); }",
+ "",
+ " if (*grfree + 1 == remember) /* no action on global queue */",
+ " { f->m_boq = QUERY; /* forward query, to root */",
+ " f->m_vsize = remember;",
+ " } else",
+ " { f->m_boq = QUERY_F; /* no match -- busy */",
+ " f->m_vsize = 112; /* anything non-zero */",
+ "#ifdef USE_DISK",
+ " if (dsk_written != dsk_drained)",
+ " { mem_drain();",
+ " }",
+ "#endif",
+ " } }",
+ " continue;",
+ " }",
+ "",
+ " if (f->m_boq == QUERY_F)",
+ " { if (verbose)",
+ " { cpu_printf(\"got QUERY_F on q%%d from slot %%d\\n\", q, prfull[q]-1);",
+ " }",
+ " f->m_vsize = 0; /* release slot */",
+ "",
+ " if (core_id == 0 && remote_party == 0) /* original root cpu0 */",
+ " { if (verbose) cpu_printf(\"No Match on Query\\n\");",
+ " query_in_progress = 0;",
+ " } else",
+ " { if (TargetQ_Full(target_q))",
+ " { if (verbose) cpu_printf(\"warning: forwarding query_f, target queue full\\n\");",
+ " }",
+ " f = Get_Free_Frame(target_q);",
+ " if (verbose) cpu_printf(\"forward QUERY_F to q%%d into slot %%d\\n\",",
+ " target_q, prfree[target_q]-1);",
+ " if (!f) { Uerror(\"Fatal5: no free slot\"); }",
+ " f->m_boq = QUERY_F; /* cannot terminate yet */",
+ " f->m_vsize = 113; /* anything non-zero */",
+ " }",
+ "#ifdef USE_DISK",
+ " if (dsk_written != dsk_drained)",
+ " { mem_drain();",
+ " }",
+ "#endif",
+ " continue;",
+ " }",
+ "",
+ " if (f->m_boq == QUIT)",
+ " { if (0) cpu_printf(\"done -- local memcnt %%g Mb\\n\", memcnt/(1048576.));",
+ " retrieve_info((SM_results *) f); /* collect and combine stats */",
+ " if (verbose)",
+ " { cpu_printf(\"received Quit\\n\");",
+ " snapshot();",
+ " }",
+ " f->m_vsize = 0; /* release incoming slot */",
+ " if (core_id != 0)",
+ " { f = Get_Free_Frame(target_q); /* new outgoing slot */",
+ " if (!f) { Uerror(\"Fatal6: no free slot\"); }",
+ " m_clear_frame(f); /* start with zeroed stats */",
+ " record_info((SM_results *) f);",
+ " f->m_boq = QUIT; /* forward combined results */",
+ " f->m_vsize = 114; /* anything non-zero */",
+ " if (verbose>1)",
+ " cpu_printf(\"fwd Results to q%%d\\n\", target_q);",
+ " }",
+ " break; /* successful termination */",
+ " }",
+ "",
+ " /* else: 0<= boq <= 255, means STATE transfer */",
+ " if (unpack_state(f, q) != 0)",
+ " { nstates_get++;",
+ " f->m_vsize = 0; /* release slot */",
+ " if (VVERBOSE) cpu_printf(\"Got state\\n\");",
+ "",
+ " if (search_terminated != NULL",
+ " && *search_terminated == 0)",
+ " { new_state(); /* explore successors */",
+ " memset((uchar *) &cur_Root, 0, sizeof(SM_frame)); /* avoid confusion */",
+ " } else",
+ " { pan_exit(0);",
+ " }",
+ " } else",
+ " { pan_exit(0);",
+ " } }",
+ " if (verbose) cpu_printf(\"done got %%d put %%d\\n\", nstates_get, nstates_put);",
+ " sleep_report();",
+ "}",
+ "",
+ "void",
+ "give_up(int unused_x)",
+ "{",
+ " if (search_terminated != NULL)",
+ " { *search_terminated |= 32; /* give_up */",
+ " }",
+ " if (!writing_trail)",
+ " { was_interrupted = 1;",
+ " snapshot();",
+ " cpu_printf(\"Give Up\\n\");",
+ " sleep_report();",
+ " pan_exit(1);",
+ " } else /* we are already terminating */",
+ " { cpu_printf(\"SIGINT\\n\");",
+ " }",
+ "}",
+ "",
+ "void",
+ "check_overkill(void)",
+ "{",
+ " vmax_seen = (vmax_seen + 7)/ 8;",
+ " vmax_seen *= 8; /* round up to a multiple of 8 */",
+ "",
+ " if (core_id == 0",
+ " && !remote_party",
+ " && nstates_put > 0",
+ " && VMAX - vmax_seen > 8)",
+ " {",
+ "#ifdef BITSTATE",
+ " printf(\"cpu0: max VMAX value seen in this run: \");",
+ "#else",
+ " printf(\"cpu0: recommend recompiling with \");",
+ "#endif",
+ " printf(\"-DVMAX=%%d\\n\", vmax_seen);",
+ " }",
+ "}",
+ "",
+ "void",
+ "mem_put(int q) /* handoff state to other cpu, workq q */",
+ "{ SM_frame *f;",
+ " int i, j;",
+ "",
+ " if (vsize > VMAX)",
+ " { vsize = (vsize + 7)/8; vsize *= 8; /* round up */",
+ " printf(\"pan: recompile with -DVMAX=N with N >= %%d\\n\", (int) vsize);",
+ " Uerror(\"aborting\");",
+ " }",
+ " if (now._nr_pr > PMAX)",
+ " { printf(\"pan: recompile with -DPMAX=N with N >= %%d\\n\", now._nr_pr);",
+ " Uerror(\"aborting\");",
+ " }",
+ " if (now._nr_qs > QMAX)",
+ " { printf(\"pan: recompile with -DQMAX=N with N >= %%d\\n\", now._nr_qs);",
+ " Uerror(\"aborting\");",
+ " }",
+ " if (vsize > vmax_seen) vmax_seen = vsize;",
+ " if (now._nr_pr > pmax_seen) pmax_seen = now._nr_pr;",
+ " if (now._nr_qs > qmax_seen) qmax_seen = now._nr_qs;",
+ "",
+ " f = Get_Free_Frame(q); /* not called in likely deadlock states */",
+ " if (!f) { Uerror(\"Fatal3: no free slot\"); }",
+ "",
+ " if (VVERBOSE) cpu_printf(\"putting state into q%%d\\n\", q);",
+ "",
+ " memcpy((uchar *) f->m_now, (uchar *) &now, vsize);",
+ "#if !defined(NOCOMP) && !defined(HC)",
+ " memset((uchar *) f->m_mask, 0, (VMAX+7)/8 * sizeof(char));",
+ " for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)",
+ " { if (Mask[i])",
+ " { f->m_mask[i/8] |= (1<<j);",
+ " } }",
+ "#endif",
+ " if (now._nr_pr > 0)",
+ " { memcpy((uchar *) f->m_p_offset, (uchar *) proc_offset, now._nr_pr * sizeof(OFFT));",
+ " memcpy((uchar *) f->m_p_skip, (uchar *) proc_skip, now._nr_pr * sizeof(uchar));",
+ " }",
+ " if (now._nr_qs > 0)",
+ " { memcpy((uchar *) f->m_q_offset, (uchar *) q_offset, now._nr_qs * sizeof(OFFT));",
+ " memcpy((uchar *) f->m_q_skip, (uchar *) q_skip, now._nr_qs * sizeof(uchar));",
+ " }",
+ "#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)",
+ " c_stack((uchar *) f->m_c_stack); /* save unmatched tracked data */",
+ "#endif",
+ "#ifdef FULL_TRAIL",
+ " f->m_stack = stack_last[core_id];",
+ "#endif",
+ " f->nr_handoffs = nr_handoffs+1;",
+ " f->m_tau = trpt->tau;",
+ " f->m_o_pm = trpt->o_pm;",
+ " f->m_boq = boq;",
+ " f->m_vsize = vsize; /* must come last - now the other cpu can see it */",
+ "",
+ " if (query_in_progress == 1)",
+ " query_in_progress = 2; /* make sure we know, if a query makes the rounds */",
+ " nstates_put++;",
+ "}",
+ "",
+ "#ifdef USE_DISK",
+ "int Dsk_W_Nr, Dsk_R_Nr;",
+ "int dsk_file = -1, dsk_read = -1;",
+ "unsigned long dsk_written, dsk_drained;",
+ "char dsk_name[512];",
+ "",
+ "#ifndef BFS_DISK",
+ "#if defined(WIN32) || defined(WIN64)",
+ " #define RFLAGS (O_RDONLY|O_BINARY)",
+ " #define WFLAGS (O_CREAT|O_WRONLY|O_TRUNC|O_BINARY)",
+ "#else",
+ " #define RFLAGS (O_RDONLY)",
+ " #define WFLAGS (O_CREAT|O_WRONLY|O_TRUNC)",
+ "#endif",
+ "#endif",
+ "",
+ "void",
+ "dsk_stats(void)",
+ "{ int i;",
+ "",
+ " if (dsk_written > 0)",
+ " { cpu_printf(\"dsk_written %%d states in %%d files\\ncpu%%d: dsk_drained %%6d states\\n\",",
+ " dsk_written, Dsk_W_Nr, core_id, dsk_drained);",
+ " close(dsk_read);",
+ " close(dsk_file);",
+ " for (i = 0; i < Dsk_W_Nr; i++)",
+ " { sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", i, core_id);",
+ " unlink(dsk_name);",
+ " } }",
+ "}",
+ "",
+ "void",
+ "mem_drain(void)",
+ "{ SM_frame *f, g;",
+ " int q = (core_id + 1) %% NCORE; /* target q */",
+ " int sz;",
+ "",
+ " if (dsk_read < 0",
+ " || dsk_written <= dsk_drained)",
+ " { return;",
+ " }",
+ "",
+ " while (dsk_written > dsk_drained",
+ " && TargetQ_NotFull(q))",
+ " { f = Get_Free_Frame(q);",
+ " if (!f) { Uerror(\"Fatal: unhandled condition\"); }",
+ "",
+ " if ((dsk_drained+1)%%MAX_DSK_FILE == 0) /* 100K states max per file */",
+ " { (void) close(dsk_read); /* close current read handle */",
+ " sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_R_Nr++, core_id);",
+ " (void) unlink(dsk_name); /* remove current file */",
+ " sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_R_Nr, core_id);",
+ " cpu_printf(\"reading %%s\\n\", dsk_name);",
+ " dsk_read = open(dsk_name, RFLAGS); /* open next file */",
+ " if (dsk_read < 0)",
+ " { Uerror(\"could not open dsk file\");",
+ " } }",
+ " if (read(dsk_read, &g, sizeof(SM_frame)) != sizeof(SM_frame))",
+ " { Uerror(\"bad dsk file read\");",
+ " }",
+ " sz = g.m_vsize;",
+ " g.m_vsize = 0;",
+ " memcpy(f, &g, sizeof(SM_frame));",
+ " f->m_vsize = sz; /* last */",
+ "",
+ " dsk_drained++;",
+ " }",
+ "}",
+ "",
+ "void",
+ "mem_file(void)",
+ "{ SM_frame f;",
+ " int i, j, q = (core_id + 1) %% NCORE; /* target q */",
+ "",
+ " if (vsize > VMAX)",
+ " { printf(\"pan: recompile with -DVMAX=N with N >= %%d\\n\", vsize);",
+ " Uerror(\"aborting\");",
+ " }",
+ " if (now._nr_pr > PMAX)",
+ " { printf(\"pan: recompile with -DPMAX=N with N >= %%d\\n\", now._nr_pr);",
+ " Uerror(\"aborting\");",
+ " }",
+ " if (now._nr_qs > QMAX)",
+ " { printf(\"pan: recompile with -DQMAX=N with N >= %%d\\n\", now._nr_qs);",
+ " Uerror(\"aborting\");",
+ " }",
+ "",
+ " if (VVERBOSE) cpu_printf(\"filing state for q%%d\\n\", q);",
+ "",
+ " memcpy((uchar *) f.m_now, (uchar *) &now, vsize);",
+ "#if !defined(NOCOMP) && !defined(HC)",
+ " memset((uchar *) f.m_mask, 0, (VMAX+7)/8 * sizeof(char));",
+ " for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)",
+ " { if (Mask[i])",
+ " { f.m_mask[i/8] |= (1<<j);",
+ " } }",
+ "#endif",
+ " if (now._nr_pr > 0)",
+ " { memcpy((uchar *)f.m_p_offset, (uchar *)proc_offset, now._nr_pr*sizeof(OFFT));",
+ " memcpy((uchar *)f.m_p_skip, (uchar *)proc_skip, now._nr_pr*sizeof(uchar));",
+ " }",
+ " if (now._nr_qs > 0)",
+ " { memcpy((uchar *) f.m_q_offset, (uchar *) q_offset, now._nr_qs*sizeof(OFFT));",
+ " memcpy((uchar *) f.m_q_skip, (uchar *) q_skip, now._nr_qs*sizeof(uchar));",
+ " }",
+ "#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)",
+ " c_stack((uchar *) f.m_c_stack); /* save unmatched tracked data */",
+ "#endif",
+ "#ifdef FULL_TRAIL",
+ " f.m_stack = stack_last[core_id];",
+ "#endif",
+ " f.nr_handoffs = nr_handoffs+1;",
+ " f.m_tau = trpt->tau;",
+ " f.m_o_pm = trpt->o_pm;",
+ " f.m_boq = boq;",
+ " f.m_vsize = vsize;",
+ "",
+ " if (query_in_progress == 1)",
+ " { query_in_progress = 2;",
+ " }",
+ " if (dsk_file < 0)",
+ " { sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_W_Nr, core_id);",
+ " dsk_file = open(dsk_name, WFLAGS, 0644);",
+ " dsk_read = open(dsk_name, RFLAGS);",
+ " if (dsk_file < 0 || dsk_read < 0)",
+ " { cpu_printf(\"File: <%%s>\\n\", dsk_name);",
+ " Uerror(\"cannot open diskfile\");",
+ " }",
+ " Dsk_W_Nr++; /* nr of next file to open */",
+ " cpu_printf(\"created temporary diskfile %%s\\n\", dsk_name);",
+ " } else if ((dsk_written+1)%%MAX_DSK_FILE == 0)",
+ " { close(dsk_file); /* close write handle */",
+ " sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_W_Nr++, core_id);",
+ " dsk_file = open(dsk_name, WFLAGS, 0644);",
+ " if (dsk_file < 0)",
+ " { cpu_printf(\"File: <%%s>\\n\", dsk_name);",
+ " Uerror(\"aborting: cannot open new diskfile\");",
+ " }",
+ " cpu_printf(\"created temporary diskfile %%s\\n\", dsk_name);",
+ " }",
+ " if (write(dsk_file, &f, sizeof(SM_frame)) != sizeof(SM_frame))",
+ " { Uerror(\"aborting -- disk write failed (disk full?)\");",
+ " }",
+ " nstates_put++;",
+ " dsk_written++;",
+ "}",
+ "#endif",
+ "",
+ "int",
+ "mem_hand_off(void)",
+ "{",
+ " if (search_terminated == NULL",
+ " || *search_terminated != 0) /* not a full crash check */",
+ " { pan_exit(0);",
+ " }",
+ " iam_alive(); /* on every transition of Down */",
+ "#ifdef USE_DISK",
+ " mem_drain(); /* maybe call this also on every Up */",
+ "#endif",
+ " if (depth > z_handoff /* above handoff limit */",
+ "#ifndef SAFETY",
+ " && !a_cycles /* not in liveness mode */",
+ "#endif",
+ "#if SYNC",
+ " && boq == -1 /* not mid-rv */",
+ "#endif",
+ "#ifdef VERI",
+ " && (trpt->tau&4) /* claim moves first */",
+ " && !((trpt-1)->tau&128) /* not a stutter move */",
+ "#endif",
+ " && !(trpt->tau&8)) /* not an atomic move */",
+ " { int q = (core_id + 1) %% NCORE; /* circular handoff */",
+ " #ifdef GENEROUS",
+ " if (prcnt[q] < LN_FRAMES)", /* not the best strategy */
+ " #else",
+ " if (TargetQ_NotFull(q)",
+ " && (dfs_phase2 == 0 || prcnt[core_id] > 0))", /* not locked, ok if race */
+ " #endif",
+ " { mem_put(q);", /* only 1 writer: lock-free */
+ " return 1;",
+ " }",
+ " { int rval;",
+ " #ifndef NGQ",
+ " rval = GlobalQ_HasRoom();",
+ " #else",
+ " rval = 0;",
+ " #endif",
+ " #ifdef USE_DISK",
+ " if (rval == 0)",
+ " { void mem_file(void);",
+ " mem_file();",
+ " rval = 1;",
+ " }",
+ " #endif",
+ " return rval;",
+ " }",
+ " }",
+ " return 0; /* i.e., no handoff */",
+ "}",
+ "",
+ "void",
+ "mem_put_acc(void) /* liveness mode */",
+ "{ int q = (core_id + 1) %% NCORE;",
+ "",
+ " if (search_terminated == NULL",
+ " || *search_terminated != 0)",
+ " { pan_exit(0);",
+ " }",
+ "#ifdef USE_DISK",
+ " mem_drain();",
+ "#endif",
+ " /* some tortured use of preprocessing: */",
+ "#if !defined(NGQ) || defined(USE_DISK)",
+ " if (TargetQ_Full(q))",
+ " {",
+ "#endif",
+ "#ifndef NGQ",
+ " if (GlobalQ_HasRoom())",
+ " { return;",
+ " }",
+ "#endif",
+ "#ifdef USE_DISK",
+ " mem_file();",
+ " } else",
+ "#else",
+ " #if !defined(NGQ) || defined(USE_DISK)",
+ " }",
+ " #endif",
+ "#endif",
+ " { mem_put(q);",
+ " }",
+ "}",
+ "",
+ "#if defined(WIN32) || defined(WIN64)", /* visual studio */
+ "void",
+ "init_shm(void) /* initialize shared work-queues */",
+ "{ char key[512];",
+ " int n, m;",
+ " int must_exit = 0;",
+ "",
+ " if (core_id == 0 && verbose)",
+ " { printf(\"cpu0: step 3: allocate shared work-queues %%g Mb\\n\",",
+ " ((double) NCORE * LWQ_SIZE + GWQ_SIZE) / (1048576.));",
+ " }",
+ " for (m = 0; m < NR_QS; m++) /* last q is global 1 */",
+ " { double qsize = (m == NCORE) ? GWQ_SIZE : LWQ_SIZE;",
+ " sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, m);",
+ " if (core_id == 0)", /* root process creates shared memory segments */
+ " { shmid[m] = CreateFileMapping(",
+ " INVALID_HANDLE_VALUE, /* use paging file */",
+ " NULL, /* default security */",
+ " PAGE_READWRITE, /* access permissions */",
+ " 0, /* high-order 4 bytes */",
+ " qsize, /* low-order bytes, size in bytes */",
+ " key); /* name */",
+ " } else /* worker nodes just open these segments */",
+ " { shmid[m] = OpenFileMapping(",
+ " FILE_MAP_ALL_ACCESS, /* read/write access */",
+ " FALSE, /* children do not inherit handle */",
+ " key);",
+ " }",
+ " if (shmid[m] == NULL)",
+ " { fprintf(stderr, \"cpu%%d: could not create or open shared queues\\n\",",
+ " core_id);",
+ " must_exit = 1;",
+ " break;",
+ " }",
+ " /* attach: */",
+ " shared_mem[m] = (char *) MapViewOfFile(shmid[m], FILE_MAP_ALL_ACCESS, 0, 0, 0);",
+ " if (shared_mem[m] == NULL)",
+ " { fprintf(stderr, \"cpu%%d: cannot attach shared q%%d (%%d Mb)\\n\",",
+ " core_id, m+1, (int) (qsize/(1048576.)));",
+ " must_exit = 1;",
+ " break;",
+ " }",
+ "",
+ " memcnt += qsize;",
+ "",
+ " m_workq[m] = (SM_frame *) shared_mem[m];",
+ " if (core_id == 0)",
+ " { int nframes = (m == NCORE) ? GN_FRAMES : LN_FRAMES;",
+ " for (n = 0; n < nframes; n++)",
+ " { m_workq[m][n].m_vsize = 0;",
+ " m_workq[m][n].m_boq = 0;",
+ " } } }",
+ "",
+ " if (must_exit)",
+ " { fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
+ " pan_exit(1); /* calls cleanup_shm */",
+ " }",
+ "}",
+ "",
+ "static uchar *",
+ "prep_shmid_S(size_t n) /* either sets SS or H_tab, WIN32/WIN64 */",
+ "{ char *rval;",
+ "#ifndef SEP_STATE",
+ " char key[512];",
+ "",
+ " if (verbose && core_id == 0)",
+ " {",
+ " #ifdef BITSTATE",
+ " printf(\"cpu0: step 1: allocate shared bitstate %%g Mb\\n\",",
+ " (double) n / (1048576.));",
+ " #else",
+ " printf(\"cpu0: step 1: allocate shared hastable %%g Mb\\n\",",
+ " (double) n / (1048576.));",
+ " #endif",
+ " }",
+ " #ifdef MEMLIM",
+ " if (memcnt + (double) n > memlim)",
+ " { printf(\"cpu%%d: S %%8g + %%d Kb exceeds memory limit of %%8g Mb\\n\",",
+ " core_id, memcnt/1024., n/1024, memlim/(1048576.));",
+ " printf(\"cpu%%d: insufficient memory -- aborting\\n\", core_id);",
+ " exit(1);",
+ " }",
+ " #endif",
+ "",
+ " /* make key different from queues: */",
+ " sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, NCORE+2); /* different from qs */",
+ "",
+ " if (core_id == 0) /* root */",
+ " { shmid_S = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,",
+ "#ifdef WIN64",
+ " PAGE_READWRITE, (n>>32), (n & 0xffffffff), key);",
+ "#else",
+ " PAGE_READWRITE, 0, n, key);",
+ "#endif",
+ " memcnt += (double) n;",
+ " } else /* worker */",
+ " { shmid_S = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, key);",
+ " }",
+
+ " if (shmid_S == NULL)",
+ " {",
+ " #ifdef BITSTATE",
+ " fprintf(stderr, \"cpu%%d: cannot %%s shared bitstate\",",
+ " core_id, core_id?\"open\":\"create\");",
+ " #else",
+ " fprintf(stderr, \"cpu%%d: cannot %%s shared hashtable\",",
+ " core_id, core_id?\"open\":\"create\");",
+ " #endif",
+ " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
+ " pan_exit(1);",
+ " }",
+ "",
+ " rval = (char *) MapViewOfFile(shmid_S, FILE_MAP_ALL_ACCESS, 0, 0, 0); /* attach */",
+ " if ((char *) rval == NULL)",
+ " { fprintf(stderr, \"cpu%%d: cannot attach shared bitstate or hashtable\\n\", core_id);",
+ " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
+ " pan_exit(1);",
+ " }",
+ "#else",
+ " rval = (char *) emalloc(n);",
+ "#endif",
+ " return (uchar *) rval;",
+ "}",
+ "",
+ "static uchar *",
+ "prep_state_mem(size_t n) /* WIN32/WIN64 sets memory arena for states */",
+ "{ char *rval;",
+ " char key[512];",
+ " static int cnt = 3; /* start larger than earlier ftok calls */",
+ "",
+ " if (verbose && core_id == 0)",
+ " { printf(\"cpu0: step 2+: pre-allocate memory arena %%d of %%g Mb\\n\",",
+ " cnt-3, (double) n / (1048576.));",
+ " }",
+ " #ifdef MEMLIM",
+ " if (memcnt + (double) n > memlim)",
+ " { printf(\"cpu%%d: error: M %%.0f + %%.0f exceeds memory limit of %%.0f Kb\\n\",",
+ " core_id, memcnt/1024.0, (double) n/1024.0, memlim/1024.0);",
+ " return NULL;",
+ " }",
+ " #endif",
+ "",
+ " sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, NCORE+cnt); cnt++;",
+ "",
+ " if (core_id == 0)",
+ " { shmid_M = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,",
+ "#ifdef WIN64",
+ " PAGE_READWRITE, (n>>32), (n & 0xffffffff), key);",
+ "#else",
+ " PAGE_READWRITE, 0, n, key);",
+ "#endif",
+ " } else",
+ " { shmid_M = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, key);",
+ " }",
+ " if (shmid_M == NULL)",
+ " { printf(\"cpu%%d: failed to get pool of shared memory nr %%d of size %%d\\n\",",
+ " core_id, cnt-3, n);",
+ " printf(\"pan: check './pan --' for usage details\\n\");",
+ " return NULL;",
+ " }",
+ " rval = (char *) MapViewOfFile(shmid_M, FILE_MAP_ALL_ACCESS, 0, 0, 0); /* attach */",
+ "",
+ " if (rval == NULL)",
+ " { printf(\"cpu%%d: failed to attach pool of shared memory nr %%d of size %%d\\n\",",
+ " core_id, cnt-3, n);",
+ " return NULL;",
+ " }",
+ " return (uchar *) rval;",
+ "}",
+ "",
+ "void",
+ "init_HT(unsigned long n) /* WIN32/WIN64 version */",
+ "{ volatile char *x;",
+ " double get_mem;",
+ "#ifndef SEP_STATE",
+ " char *dc_mem_start;",
+ "#endif",
+ " if (verbose) printf(\"cpu%%d: initialization for Windows\\n\", core_id);",
+ "",
+"#ifdef SEP_STATE",
+ " #ifndef MEMLIM",
+ " if (verbose)",
+ " { printf(\"cpu0: steps 0,1: no -DMEMLIM set\\n\");",
+ " }",
+ " #else",
+ " if (verbose)",
+ " printf(\"cpu0: steps 0,1: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb)\\n\",",
+ " MEMLIM, ((double)n/(1048576.)), ((double) NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.));",
+ "#endif",
+ " get_mem = NCORE * sizeof(double) + (1 + CS_NR) * sizeof(void *)+ 4*sizeof(void *) + 2*sizeof(double);",
+ " /* NCORE * is_alive + search_terminated + CS_NR * sh_lock + 6 gr vars */",
+ " get_mem += 4 * NCORE * sizeof(void *);", /* prfree, prfull, prcnt, prmax */
+ " #ifdef FULL_TRAIL",
+ " get_mem += (NCORE) * sizeof(Stack_Tree *);",
+ " /* NCORE * stack_last */",
+ " #endif",
+ " x = (volatile char *) prep_state_mem((size_t) get_mem);",
+ " shmid_X = (void *) x;",
+ " if (x == NULL)",
+ " { printf(\"cpu0: could not allocate shared memory, see ./pan --\\n\");",
+ " exit(1);",
+ " }",
+ " search_terminated = (volatile unsigned int *) x; /* comes first */",
+ " x += sizeof(void *); /* maintain alignment */",
+ "",
+ " is_alive = (volatile double *) x;",
+ " x += NCORE * sizeof(double);",
+ "",
+ " sh_lock = (volatile int *) x;",
+ " x += CS_NR * sizeof(void *); /* allow 1 word per entry */",
+ "",
+ " grfree = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " grfull = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " grcnt = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " grmax = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " prfree = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " prfull = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " prcnt = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " prmax = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " gr_readmiss = (volatile double *) x;",
+ " x += sizeof(double);",
+ " gr_writemiss = (volatile double *) x;",
+ " x += sizeof(double);",
+ "",
+ " #ifdef FULL_TRAIL",
+ " stack_last = (volatile Stack_Tree **) x;",
+ " x += NCORE * sizeof(Stack_Tree *);",
+ " #endif",
+ "",
+ " #ifndef BITSTATE",
+ " H_tab = (H_el **) emalloc(n);",
+ " #endif",
+"#else",
+ " #ifndef MEMLIM",
+ " #warning MEMLIM not set", /* cannot happen */
+ " #define MEMLIM (2048)",
+ " #endif",
+ "",
+ " if (core_id == 0 && verbose)",
+ " printf(\"cpu0: step 0: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb) = %%g Mb for state storage\\n\",",
+ " MEMLIM, ((double)n/(1048576.)), ((double) NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.),",
+ " (memlim - memcnt - (double) n - ((double) NCORE * LWQ_SIZE + GWQ_SIZE))/(1048576.));",
+ " #ifndef BITSTATE",
+ " H_tab = (H_el **) prep_shmid_S((size_t) n); /* hash_table */",
+ " #endif",
+ " get_mem = memlim - memcnt - ((double) NCORE) * LWQ_SIZE - GWQ_SIZE;",
+ " if (get_mem <= 0)",
+ " { Uerror(\"internal error -- shared state memory\");",
+ " }",
+ "",
+ " if (core_id == 0 && verbose)",
+ " { printf(\"cpu0: step 2: shared state memory %%g Mb\\n\",",
+ " get_mem/(1048576.));",
+ " }",
+ " x = dc_mem_start = (char *) prep_state_mem((size_t) get_mem); /* for states */",
+ " if (x == NULL)",
+ " { printf(\"cpu%%d: insufficient memory -- aborting\\n\", core_id);",
+ " exit(1);",
+ " }",
+ "",
+ " search_terminated = (volatile unsigned int *) x; /* comes first */",
+ " x += sizeof(void *); /* maintain alignment */",
+ "",
+ " is_alive = (volatile double *) x;",
+ " x += NCORE * sizeof(double);",
+ "",
+ " sh_lock = (volatile int *) x;",
+ " x += CS_NR * sizeof(int);",
+ "",
+ " grfree = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " grfull = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " grcnt = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " grmax = (volatile int *) x;",
+ " x += sizeof(void *);",
+ " prfree = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " prfull = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " prcnt = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " prmax = (volatile int *) x;",
+ " x += NCORE * sizeof(void *);",
+ " gr_readmiss = (volatile double *) x;",
+ " x += sizeof(double);",
+ " gr_writemiss = (volatile double *) x;",
+ " x += sizeof(double);",
+ "",
+ " #ifdef FULL_TRAIL",
+ " stack_last = (volatile Stack_Tree **) x;",
+ " x += NCORE * sizeof(Stack_Tree *);",
+ " #endif",
+ " if (((long)x)&(sizeof(void *)-1)) /* word alignment */",
+ " { x += sizeof(void *)-(((long)x)&(sizeof(void *)-1)); /* 64-bit align */",
+ " }",
+ "",
+ " #ifdef COLLAPSE",
+ " ncomps = (unsigned long *) x;",
+ " x += (256+2) * sizeof(unsigned long);",
+ " #endif",
+ "",
+ " dc_shared = (sh_Allocater *) x; /* in shared memory */",
+ " x += sizeof(sh_Allocater);",
+ "",
+ " if (core_id == 0) /* root only */",
+ " { dc_shared->dc_id = shmid_M;",
+ " dc_shared->dc_start = (void *) dc_mem_start;",
+ " dc_shared->dc_arena = x;",
+ " dc_shared->pattern = 1234567;",
+ " dc_shared->dc_size = (long) get_mem - (long) (x - dc_mem_start);",
+ " dc_shared->nxt = NULL;",
+ " }",
+"#endif",
+ "}",
+ "",
+ "#if defined(WIN32) || defined(WIN64) || defined(__i386__) || defined(__x86_64__)",
+ "extern BOOLEAN InterlockedBitTestAndSet(LONG volatile* Base, LONG Bit);",
+ "int",
+ "tas(volatile LONG *s)", /* atomic test and set */
+ "{ return InterlockedBitTestAndSet(s, 1);",
+ "}",
+ "#else",
+ " #error missing definition of test and set operation for this platform",
+ "#endif",
+ "",
+ "void",
+ "cleanup_shm(int val)",
+ "{ int m;",
+ " static int nibis = 0;",
+ "",
+ " if (nibis != 0)",
+ " { printf(\"cpu%%d: Redundant call to cleanup_shm(%%d)\\n\", core_id, val);",
+ " return;",
+ " } else",
+ " { nibis = 1;",
+ " }",
+ " if (search_terminated != NULL)",
+ " { *search_terminated |= 16; /* cleanup_shm */",
+ " }",
+ "",
+ " for (m = 0; m < NR_QS; m++)",
+ " { if (shmid[m] != NULL)",
+ " { UnmapViewOfFile((char *) shared_mem[m]);",
+ " CloseHandle(shmid[m]);",
+ " } }",
+ "#ifdef SEP_STATE",
+ " UnmapViewOfFile((void *) shmid_X);",
+ " CloseHandle((void *) shmid_M);",
+ "#else",
+ " #ifdef BITSTATE",
+ " if (shmid_S != NULL)",
+ " { UnmapViewOfFile(SS);",
+ " CloseHandle(shmid_S);",
+ " }",
+ " #else",
+ " if (core_id == 0 && verbose)",
+ " { printf(\"cpu0: done, %%ld Mb of shared state memory left\\n\",",
+ " dc_shared->dc_size / (long)(1048576));",
+ " }",
+ " if (shmid_S != NULL)",
+ " { UnmapViewOfFile(H_tab);",
+ " CloseHandle(shmid_S);",
+ " }",
+ " shmid_M = (void *) (dc_shared->dc_id);",
+ " UnmapViewOfFile((char *) dc_shared->dc_start);",
+ " CloseHandle(shmid_M);",
+ " #endif",
+ "#endif",
+ " /* detached from shared memory - so cannot use cpu_printf */",
+ " if (verbose)",
+ " { printf(\"cpu%%d: done -- got %%d states from queue\\n\",",
+ " core_id, nstates_get);",
+ " }",
+ "}",
+ "",
+ "void",
+ "mem_get(void)",
+ "{ SM_frame *f;",
+ " int is_parent;",
+ "",
+ "#if defined(MA) && !defined(SEP_STATE)",
+ " #error MA requires SEP_STATE in multi-core mode",
+ "#endif",
+ "#ifdef BFS",
+ " #error instead of -DNCORE -DBFS use -DBFS_PAR",
+ "#endif",
+ "#ifdef SC",
+ " #error SC is not supported in multi-core mode",
+ "#endif",
+ " init_shm(); /* we are single threaded when this starts */",
+ " signal(SIGINT, give_up); /* windows control-c interrupt */",
+ "",
+ " if (core_id == 0 && verbose)",
+ " { printf(\"cpu0: step 4: creating additional workers (proxy %%d)\\n\",",
+ " proxy_pid);",
+ " }",
+ "#if 0",
+ " if NCORE > 1 the child or the parent should fork N-1 more times",
+ " the parent is the only process with core_id == 0 and is_parent > 0",
+ " the others (workers) have is_parent = 0 and core_id = 1..NCORE-1",
+ "#endif",
+ " if (core_id == 0) /* root starts up the workers */",
+ " { worker_pids[0] = (DWORD) getpid(); /* for completeness */",
+ " while (++core_id < NCORE) /* first worker sees core_id = 1 */",
+ " { char cmdline[64];",
+ " STARTUPINFO si = { sizeof(si) };",
+ " PROCESS_INFORMATION pi;",
+ "",
+ " if (proxy_pid == core_id) /* always non-zero */",
+ " { sprintf(cmdline, \"pan_proxy.exe -r %%s-Q%%d -Z%%d\",",
+ " o_cmdline, getpid(), core_id);",
+ " } else",
+ " { sprintf(cmdline, \"pan.exe %%s-Q%%d -Z%%d\",",
+ " o_cmdline, getpid(), core_id);",
+ " }",
+ " if (verbose) printf(\"cpu%%d: spawn %%s\\n\", core_id, cmdline);",
+ "",
+ " is_parent = CreateProcess(0, cmdline, 0, 0, FALSE, 0, 0, 0, &si, &pi);",
+ " if (is_parent == 0)",
+ " { Uerror(\"fork failed\");",
+ " }",
+ " worker_pids[core_id] = pi.dwProcessId;",
+ " worker_handles[core_id] = pi.hProcess;",
+ " if (verbose)",
+ " { cpu_printf(\"created core %%d, pid %%d\\n\",",
+ " core_id, pi.dwProcessId);",
+ " }",
+ " if (proxy_pid == core_id) /* we just created the receive half */",
+ " { /* add proxy send, store pid in proxy_pid_snd */",
+ " sprintf(cmdline, \"pan_proxy.exe -s %%s-Q%%d -Z%%d -Y%%d\",",
+ " o_cmdline, getpid(), core_id, worker_pids[proxy_pid]);",
+ " if (verbose) printf(\"cpu%%d: spawn %%s\\n\", core_id, cmdline);",
+ " is_parent = CreateProcess(0, cmdline, 0,0, FALSE, 0,0,0, &si, &pi);",
+ " if (is_parent == 0)",
+ " { Uerror(\"fork failed\");",
+ " }",
+ " proxy_pid_snd = pi.dwProcessId;",
+ " proxy_handle_snd = pi.hProcess;",
+ " if (verbose)",
+ " { cpu_printf(\"created core %%d, pid %%d (send proxy)\\n\",",
+ " core_id, pi.dwProcessId);",
+ " } } }",
+ " core_id = 0; /* reset core_id for root process */",
+ " } else /* worker */",
+ " { static char db0[16]; /* good for up to 10^6 cores */",
+ " static char db1[16];",
+ " tprefix = db0; sprefix = db1;",
+ " sprintf(tprefix, \"cpu%%d_trail\", core_id); /* avoid conflicts on file access */",
+ " sprintf(sprefix, \"cpu%%d_rst\", core_id);",
+ " memcnt = 0; /* count only additionally allocated memory */",
+ " }",
+ " if (verbose)",
+ " { cpu_printf(\"starting core_id %%d -- pid %%d\\n\", core_id, getpid());",
+ " }",
+ " if (core_id == 0 && !remote_party)",
+ " { new_state(); /* root starts the search */",
+ " if (verbose)",
+ " cpu_printf(\"done with 1st dfs, nstates %%g (put %%d states), start reading q\\n\",",
+ " nstates, nstates_put);",
+ " dfs_phase2 = 1;",
+ " }",
+ " Read_Queue(core_id); /* all cores */",
+ "",
+ " if (verbose)",
+ " { cpu_printf(\"put %%6d states into queue -- got %%6d\\n\",",
+ " nstates_put, nstates_get);",
+ " }",
+ " done = 1;",
+ " wrapup();",
+ " exit(0);",
+ "}",
+ "#endif", /* WIN32 || WIN64 */
+ "",
+ "#ifdef BITSTATE",
+ "void",
+ "init_SS(unsigned long n)",
+ "{",
+ " SS = (uchar *) prep_shmid_S((size_t) n);",
+ " init_HT(0L);", /* locks and shared memory for Stack_Tree allocations */
+ "}",
+ "#endif", /* BITSTATE */
+ "",
+ "#endif", /* NCORE>1 */
+ 0,
+};
--- /dev/null
+++ b/sys/src/cmd/spin/pangen7.c
@@ -1,0 +1,923 @@
+/***** spin: pangen7.c *****/
+
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include "spin.h"
+#include "y.tab.h"
+#include <assert.h>
+#ifndef PC
+#include <unistd.h>
+#endif
+
+extern ProcList *rdy;
+extern Element *Al_El;
+extern int nclaims, verbose, Strict;
+extern short has_accept;
+
+typedef struct Succ_List Succ_List;
+typedef struct SQueue SQueue;
+typedef struct OneState OneState;
+typedef struct State_Stack State_Stack;
+typedef struct Guard Guard;
+
+struct Succ_List {
+ SQueue *s;
+ Succ_List *nxt;
+};
+
+struct OneState {
+ int *combo; /* the combination of claim states */
+ Succ_List *succ; /* list of ptrs to immediate successor states */
+};
+
+struct SQueue {
+ OneState state;
+ SQueue *nxt;
+};
+
+struct State_Stack {
+ int *n;
+ State_Stack *nxt;
+};
+
+struct Guard {
+ Lextok *t;
+ Guard *nxt;
+};
+
+static SQueue *sq, *sd, *render; /* states move from sq to sd to render to holding */
+static SQueue *holding, *lasthold;
+static State_Stack *dsts;
+
+static int nst; /* max nr of states in claims */
+static int *Ist; /* initial states */
+static int *Nacc; /* number of accept states in claim */
+static int *Nst; /* next states */
+static int **reached; /* n claims x states */
+static int unfolding; /* to make sure all accept states are reached */
+static int is_accept; /* remember if the current state is accepting in any claim */
+static int not_printing; /* set during explore_product */
+
+static Element ****matrix; /* n x two-dimensional arrays state x state */
+static Element **Selfs; /* self-loop states at end of claims */
+
+static void get_seq(int, Sequence *);
+static void set_el(int n, Element *e);
+static void gen_product(void);
+static void print_state_nm(char *, int *, char *);
+static SQueue *find_state(int *);
+static SQueue *retrieve_state(int *);
+
+static int
+same_state(int *a, int *b)
+{ int i;
+
+ for (i = 0; i < nclaims; i++)
+ { if (a[i] != b[i])
+ { return 0;
+ } }
+ return 1;
+}
+
+static int
+in_stack(SQueue *s, SQueue *in)
+{ SQueue *q;
+
+ for (q = in; q; q = q->nxt)
+ { if (same_state(q->state.combo, s->state.combo))
+ { return 1;
+ } }
+ return 0;
+}
+
+static void
+to_render(SQueue *s)
+{ SQueue *a, *q, *last; /* find in sd/sq and move to render, if not already there */
+ int n;
+
+ for (n = 0; n < nclaims; n++)
+ { reached[n][ s->state.combo[n] ] |= 2;
+ }
+
+ for (q = render; q; q = q->nxt)
+ { if (same_state(q->state.combo, s->state.combo))
+ { return;
+ } }
+ for (q = holding; q; q = q->nxt)
+ { if (same_state(q->state.combo, s->state.combo))
+ { return;
+ } }
+
+ a = sd;
+more:
+ for (q = a, last = 0; q; last = q, q = q->nxt)
+ { if (same_state(q->state.combo, s->state.combo))
+ { if (!last)
+ { if (a == sd)
+ { sd = q->nxt;
+ } else if (a == sq)
+ { sq = q->nxt;
+ } else
+ { holding = q->nxt;
+ }
+ } else
+ { last->nxt = q->nxt;
+ }
+ q->nxt = render;
+ render = q;
+ return;
+ } }
+ if (verbose)
+ { print_state_nm("looking for: ", s->state.combo, "\n");
+ }
+ (void) find_state(s->state.combo); /* creates it in sq */
+ if (a != sq)
+ { a = sq;
+ goto more;
+ }
+ fatal("cannot happen, to_render", 0);
+}
+
+static void
+wrap_text(char *pre, Lextok *t, char *post)
+{
+ printf(pre, (char *) 0);
+ comment(stdout, t, 0);
+ printf(post, (char *) 0);
+}
+
+static State_Stack *
+push_dsts(int *n)
+{ State_Stack *s;
+ int i;
+
+ for (s = dsts; s; s = s->nxt)
+ { if (same_state(s->n, n))
+ { if (verbose&64)
+ { printf("\n");
+ for (s = dsts; s; s = s->nxt)
+ { print_state_nm("\t", s->n, "\n");
+ }
+ print_state_nm("\t", n, "\n");
+ }
+ return s;
+ } }
+
+ s = (State_Stack *) emalloc(sizeof(State_Stack));
+ s->n = (int *) emalloc(nclaims * sizeof(int));
+ for (i = 0; i < nclaims; i++)
+ s->n[i] = n[i];
+ s->nxt = dsts;
+ dsts = s;
+ return 0;
+}
+
+static void
+pop_dsts(void)
+{
+ assert(dsts != NULL);
+ dsts = dsts->nxt;
+}
+
+static void
+complete_transition(Succ_List *sl, Guard *g)
+{ Guard *w;
+ int cnt = 0;
+
+ printf(" :: ");
+ for (w = g; w; w = w->nxt)
+ { if (w->t->ntyp == CONST
+ && w->t->val == 1)
+ { continue;
+ } else if (w->t->ntyp == 'c'
+ && w->t->lft->ntyp == CONST
+ && w->t->lft->val == 1)
+ { continue; /* 'true' */
+ }
+
+ if (cnt > 0)
+ { printf(" && ");
+ }
+ wrap_text("", w->t, "");
+ cnt++;
+ }
+ if (cnt == 0)
+ { printf("true");
+ }
+ print_state_nm(" -> goto ", sl->s->state.combo, "");
+
+ if (is_accept > 0)
+ { printf("_U%d\n", (unfolding+1)%nclaims);
+ } else
+ { printf("_U%d\n", unfolding);
+ }
+}
+
+static void
+state_body(OneState *s, Guard *guard)
+{ Succ_List *sl;
+ State_Stack *y;
+ Guard *g;
+ int i, once;
+
+ for (sl = s->succ; sl; sl = sl->nxt)
+ { once = 0;
+
+ for (i = 0; i < nclaims; i++)
+ { Element *e;
+ e = matrix[i][s->combo[i]][sl->s->state.combo[i]];
+
+ /* if one of the claims has a DO or IF move
+ then pull its target state forward, once
+ */
+
+ if (!e
+ || e->n->ntyp == NON_ATOMIC
+ || e->n->ntyp == DO
+ || e->n->ntyp == IF)
+ { s = &(sl->s->state);
+ y = push_dsts(s->combo);
+ if (!y)
+ { if (once++ == 0)
+ { assert(s->succ != NULL);
+ state_body(s, guard);
+ }
+ pop_dsts();
+ } else if (!y->nxt) /* self-loop transition */
+ { if (!not_printing) printf(" /* self-loop */\n");
+ } else
+ { /* non_fatal("loop in state body", 0); ** maybe ok */
+ }
+ continue;
+ } else
+ { g = (Guard *) emalloc(sizeof(Guard));
+ g->t = e->n;
+ g->nxt = guard;
+ guard = g;
+ } }
+
+ if (guard && !once)
+ { if (!not_printing) complete_transition(sl, guard);
+ to_render(sl->s);
+ } }
+}
+
+static struct X {
+ char *s; int n;
+} spl[] = {
+ {"end", 3 },
+ {"accept", 6 },
+ {0, 0 },
+};
+
+static int slcnt;
+extern Label *labtab;
+
+static ProcList *
+locate_claim(int n)
+{ ProcList *p;
+ int i;
+
+ for (p = rdy, i = 0; p; p = p->nxt, i++) /* find claim name */
+ { if (i == n)
+ { break;
+ } }
+ assert(p && p->b == N_CLAIM);
+
+ return p;
+}
+
+static void
+elim_lab(Element *e)
+{ Label *l, *lst;
+
+ for (l = labtab, lst = NULL; l; lst = l, l = l->nxt)
+ { if (l->e == e)
+ { if (lst)
+ { lst->nxt = l->nxt;
+ } else
+ { labtab = l->nxt;
+ }
+ break;
+ } }
+}
+
+static int
+claim_has_accept(ProcList *p)
+{ Label *l;
+
+ for (l = labtab; l; l = l->nxt)
+ { if (strcmp(l->c->name, p->n->name) == 0
+ && strncmp(l->s->name, "accept", 6) == 0)
+ { return 1;
+ } }
+ return 0;
+}
+
+static void
+prune_accept(void)
+{ int n;
+
+ for (n = 0; n < nclaims; n++)
+ { if ((reached[n][Selfs[n]->seqno] & 2) == 0)
+ { if (verbose)
+ { printf("claim %d: selfloop not reachable\n", n);
+ }
+ elim_lab(Selfs[n]);
+ Nacc[n] = claim_has_accept(locate_claim(n));
+ } }
+}
+
+static void
+mk_accepting(int n, Element *e)
+{ ProcList *p;
+ Label *l;
+ int i;
+
+ assert(!Selfs[n]);
+ Selfs[n] = e;
+
+ l = (Label *) emalloc(sizeof(Label));
+ l->s = (Symbol *) emalloc(sizeof(Symbol));
+ l->s->name = "accept00";
+ l->c = (Symbol *) emalloc(sizeof(Symbol));
+ l->uiid = 0; /* this is not in an inline */
+
+ for (p = rdy, i = 0; p; p = p->nxt, i++) /* find claim name */
+ { if (i == n)
+ { l->c->name = p->n->name;
+ break;
+ } }
+ assert(p && p->b == N_CLAIM);
+ Nacc[n] = 1;
+ has_accept = 1;
+
+ l->e = e;
+ l->nxt = labtab;
+ labtab = l;
+}
+
+static void
+check_special(int *nrs)
+{ ProcList *p;
+ Label *l;
+ int i, j, nmatches;
+ int any_accepts = 0;
+
+ for (i = 0; i < nclaims; i++)
+ { any_accepts += Nacc[i];
+ }
+
+ is_accept = 0;
+ for (j = 0; spl[j].n; j++) /* 2 special label prefixes */
+ { nmatches = 0;
+ for (p = rdy, i = 0; p; p = p->nxt, i++) /* check each claim */
+ { if (p->b != N_CLAIM)
+ { continue;
+ }
+ /* claim i in state nrs[i], type p->tn, name p->n->name
+ * either the state has an accept label, or the claim has none,
+ * so that all its states should be considered accepting
+ * --- but only if other claims do have accept states!
+ */
+ if (Strict == 0 && j == 1 && Nacc[i] == 0 && any_accepts > 0)
+ { if ((verbose&32) && i == unfolding)
+ { printf(" /* claim %d pseudo-accept */\n", i);
+ }
+ goto is_accepting;
+ }
+ for (l = labtab; l; l = l->nxt) /* check its labels */
+ { if (strcmp(l->c->name, p->n->name) == 0 /* right claim */
+ && l->e->seqno == nrs[i] /* right state */
+ && strncmp(l->s->name, spl[j].s, spl[j].n) == 0)
+ { if (j == 1) /* accept state */
+ { char buf[32];
+is_accepting: if (strchr(p->n->name, ':'))
+ { sprintf(buf, "N%d", i);
+ } else
+ { assert(strlen(p->n->name) < sizeof(buf));
+ strcpy(buf, p->n->name);
+ }
+ if (unfolding == 0 && i == 0)
+ { if (!not_printing)
+ printf("%s_%s_%d:\n", /* true accept */
+ spl[j].s, buf, slcnt++);
+ } else if (verbose&32)
+ { if (!not_printing)
+ printf("%s_%s%d:\n",
+ buf, spl[j].s, slcnt++);
+ }
+ if (i == unfolding)
+ { is_accept++; /* move to next unfolding */
+ }
+ } else
+ { nmatches++;
+ }
+ break;
+ } } }
+ if (j == 0 && nmatches == nclaims) /* end-state */
+ { if (!not_printing)
+ { printf("%s%d:\n", spl[j].s, slcnt++);
+ } } }
+}
+
+static int
+render_state(SQueue *q)
+{
+ if (!q || !q->state.succ)
+ { if (verbose&64)
+ { printf(" no exit\n");
+ }
+ return 0;
+ }
+
+ check_special(q->state.combo); /* accept or end-state labels */
+
+ dsts = (State_Stack *) 0;
+ push_dsts(q->state.combo); /* to detect loops */
+
+ if (!not_printing)
+ { print_state_nm("", q->state.combo, ""); /* the name */
+ printf("_U%d:\n\tdo\n", unfolding);
+ }
+
+ state_body(&(q->state), (Guard *) 0);
+
+ if (!not_printing)
+ { printf("\tod;\n");
+ }
+ pop_dsts();
+ return 1;
+}
+
+static void
+explore_product(void)
+{ SQueue *q;
+
+ /* all states are in the sd queue */
+
+ q = retrieve_state(Ist); /* retrieve from the sd q */
+ q->nxt = render; /* put in render q */
+ render = q;
+ do {
+ q = render;
+ render = render->nxt;
+ q->nxt = 0; /* remove from render q */
+
+ if (verbose&64)
+ { print_state_nm("explore: ", q->state.combo, "\n");
+ }
+
+ not_printing = 1;
+ render_state(q); /* may add new states */
+ not_printing = 0;
+
+ if (lasthold)
+ { lasthold->nxt = q;
+ lasthold = q;
+ } else
+ { holding = lasthold = q;
+ }
+ } while (render);
+ assert(!dsts);
+
+}
+
+static void
+print_product(void)
+{ SQueue *q;
+ int cnt;
+
+ if (unfolding == 0)
+ { printf("never Product {\n"); /* name expected by iSpin */
+ q = find_state(Ist); /* should find it in the holding q */
+ assert(q != NULL);
+ q->nxt = holding; /* put it at the front */
+ holding = q;
+ }
+ render = holding;
+ holding = lasthold = 0;
+
+ printf("/* ============= U%d ============= */\n", unfolding);
+ cnt = 0;
+ do {
+ q = render;
+ render = render->nxt;
+ q->nxt = 0;
+ if (verbose&64)
+ { print_state_nm("print: ", q->state.combo, "\n");
+ }
+ cnt += render_state(q);
+
+ if (lasthold)
+ { lasthold->nxt = q;
+ lasthold = q;
+ } else
+ { holding = lasthold = q;
+ }
+ } while (render);
+ assert(!dsts);
+
+ if (cnt == 0)
+ { printf(" 0;\n");
+ }
+
+ if (unfolding == nclaims-1)
+ { printf("}\n");
+ }
+}
+
+static void
+prune_dead(void)
+{ Succ_List *sl, *last;
+ SQueue *q;
+ int cnt;
+
+ do { cnt = 0;
+ for (q = sd; q; q = q->nxt)
+ { /* if successor is deadend, remove it
+ * unless it's a move to the end-state of the claim
+ */
+ last = (Succ_List *) 0;
+ for (sl = q->state.succ; sl; last = sl, sl = sl->nxt)
+ { if (!sl->s->state.succ) /* no successor */
+ { if (!last)
+ { q->state.succ = sl->nxt;
+ } else
+ { last->nxt = sl->nxt;
+ }
+ cnt++;
+ } } }
+ } while (cnt > 0);
+}
+
+static void
+print_raw(void)
+{ int i, j, n;
+
+ printf("#if 0\n");
+ for (n = 0; n < nclaims; n++)
+ { printf("C%d:\n", n);
+ for (i = 0; i < nst; i++)
+ { if (reached[n][i])
+ for (j = 0; j < nst; j++)
+ { if (matrix[n][i][j])
+ { if (reached[n][i] & 2) printf("+");
+ if (i == Ist[n]) printf("*");
+ printf("\t%d", i);
+ wrap_text(" -[", matrix[n][i][j]->n, "]->\t");
+ printf("%d\n", j);
+ } } } }
+ printf("#endif\n\n");
+ fflush(stdout);
+}
+
+void
+sync_product(void)
+{ ProcList *p;
+ Element *e;
+ int n, i;
+
+ if (nclaims <= 1) return;
+
+ (void) unlink("pan.pre");
+
+ Ist = (int *) emalloc(sizeof(int) * nclaims);
+ Nacc = (int *) emalloc(sizeof(int) * nclaims);
+ Nst = (int *) emalloc(sizeof(int) * nclaims);
+ reached = (int **) emalloc(sizeof(int *) * nclaims);
+ Selfs = (Element **) emalloc(sizeof(Element *) * nclaims);
+ matrix = (Element ****) emalloc(sizeof(Element ***) * nclaims); /* claims */
+
+ for (p = rdy, i = 0; p; p = p->nxt, i++)
+ { if (p->b == N_CLAIM)
+ { nst = max(p->s->maxel, nst);
+ Nacc[i] = claim_has_accept(p);
+ } }
+
+ for (n = 0; n < nclaims; n++)
+ { reached[n] = (int *) emalloc(sizeof(int) * nst);
+ matrix[n] = (Element ***) emalloc(sizeof(Element **) * nst); /* rows */
+ for (i = 0; i < nst; i++) /* cols */
+ { matrix[n][i] = (Element **) emalloc(sizeof(Element *) * nst);
+ } }
+
+ for (e = Al_El; e; e = e->Nxt)
+ { e->status &= ~DONE;
+ }
+
+ for (p = rdy, n=0; p; p = p->nxt, n++)
+ { if (p->b == N_CLAIM)
+ { /* fill in matrix[n] */
+ e = p->s->frst;
+ Ist[n] = huntele(e, e->status, -1)->seqno;
+
+ reached[n][Ist[n]] = 1|2;
+ get_seq(n, p->s);
+ } }
+
+ if (verbose) /* show only the input automata */
+ { print_raw();
+ }
+
+ gen_product(); /* create product automaton */
+}
+
+static int
+nxt_trans(int n, int cs, int frst)
+{ int j;
+
+ for (j = frst; j < nst; j++)
+ { if (reached[n][cs]
+ && matrix[n][cs][j])
+ { return j;
+ } }
+ return -1;
+}
+
+static void
+print_state_nm(char *p, int *s, char *a)
+{ int i;
+ printf("%sP", p);
+ for (i = 0; i < nclaims; i++)
+ { printf("_%d", s[i]);
+ }
+ printf("%s", a);
+}
+
+static void
+create_transition(OneState *s, SQueue *it)
+{ int n, from, upto;
+ int *F = s->combo;
+ int *T = it->state.combo;
+ Succ_List *sl;
+ Lextok *t;
+
+ if (verbose&64)
+ { print_state_nm("", F, " ");
+ print_state_nm("-> ", T, "\t");
+ }
+
+ /* check if any of the claims is blocked */
+ /* which makes the state a dead-end */
+ for (n = 0; n < nclaims; n++)
+ { from = F[n];
+ upto = T[n];
+ t = matrix[n][from][upto]->n;
+ if (verbose&64)
+ { wrap_text("", t, " ");
+ }
+ if (t->ntyp == 'c'
+ && t->lft->ntyp == CONST)
+ { if (t->lft->val == 0) /* i.e., false */
+ { goto done;
+ } } }
+
+ sl = (Succ_List *) emalloc(sizeof(Succ_List));
+ sl->s = it;
+ sl->nxt = s->succ;
+ s->succ = sl;
+done:
+ if (verbose&64)
+ { printf("\n");
+ }
+}
+
+static SQueue *
+find_state(int *cs)
+{ SQueue *nq, *a = sq;
+ int i;
+
+again: /* check in nq, sq, and then in the render q */
+ for (nq = a; nq; nq = nq->nxt)
+ { if (same_state(nq->state.combo, cs))
+ { return nq; /* found */
+ } }
+ if (a == sq && sd)
+ { a = sd;
+ goto again; /* check the other stack too */
+ } else if (a == sd && render)
+ { a = render;
+ goto again;
+ }
+
+ nq = (SQueue *) emalloc(sizeof(SQueue));
+ nq->state.combo = (int *) emalloc(nclaims * sizeof(int));
+ for (i = 0; i < nclaims; i++)
+ { nq->state.combo[i] = cs[i];
+ }
+ nq->nxt = sq; /* add to sq stack */
+ sq = nq;
+
+ return nq;
+}
+
+static SQueue *
+retrieve_state(int *s)
+{ SQueue *nq, *last = NULL;
+
+ for (nq = sd; nq; last = nq, nq = nq->nxt)
+ { if (same_state(nq->state.combo, s))
+ { if (last)
+ { last->nxt = nq->nxt;
+ } else
+ { sd = nq->nxt; /* 6.4.0: was sd = nq */
+ }
+ return nq; /* found */
+ } }
+
+ fatal("cannot happen: retrieve_state", 0);
+ return (SQueue *) 0;
+}
+
+static void
+all_successors(int n, OneState *cur)
+{ int i, j = 0;
+
+ if (n >= nclaims)
+ { create_transition(cur, find_state(Nst));
+ } else
+ { i = cur->combo[n];
+ for (;;)
+ { j = nxt_trans(n, i, j);
+ if (j < 0) break;
+ Nst[n] = j;
+ all_successors(n+1, cur);
+ j++;
+ } }
+}
+
+static void
+gen_product(void)
+{ OneState *cur_st;
+ SQueue *q;
+
+ find_state(Ist); /* create initial state */
+
+ while (sq)
+ { if (in_stack(sq, sd))
+ { sq = sq->nxt;
+ continue;
+ }
+ cur_st = &(sq->state);
+
+ q = sq;
+ sq = sq->nxt; /* delete from sq stack */
+ q->nxt = sd; /* and move to done stack */
+ sd = q;
+
+ all_successors(0, cur_st);
+ }
+ /* all states are in the sd queue now */
+ prune_dead();
+ explore_product(); /* check if added accept-self-loops are reachable */
+ prune_accept();
+
+ if (verbose)
+ { print_raw();
+ }
+
+ /* PM: merge states with identical successor lists */
+
+ /* all outgoing transitions from accept-states
+ from claim n in copy n connect to states in copy (n+1)%nclaims
+ only accept states from claim 0 in copy 0 are true accept states
+ in the product
+
+ PM: what about claims that have no accept states (e.g., restrictions)
+ */
+
+ for (unfolding = 0; unfolding < nclaims; unfolding++)
+ { print_product();
+ }
+}
+
+static void
+t_record(int n, Element *e, Element *g)
+{ int from = e->seqno, upto = g?g->seqno:0;
+
+ assert(from >= 0 && from < nst);
+ assert(upto >= 0 && upto < nst);
+
+ matrix[n][from][upto] = e;
+ reached[n][upto] |= 1;
+}
+
+static void
+get_sub(int n, Element *e)
+{
+ if (e->n->ntyp == D_STEP
+ || e->n->ntyp == ATOMIC)
+ { fatal("atomic or d_step in never claim product", 0);
+ }
+ /* NON_ATOMIC */
+ e->n->sl->this->last->nxt = e->nxt;
+ get_seq(n, e->n->sl->this);
+
+ t_record(n, e, e->n->sl->this->frst);
+
+}
+
+static void
+set_el(int n, Element *e)
+{ Element *g;
+
+ if (e->n->ntyp == '@') /* change to self-loop */
+ { e->n->ntyp = CONST;
+ e->n->val = 1; /* true */
+ e->nxt = e;
+ g = e;
+ mk_accepting(n, e);
+ } else
+
+ if (e->n->ntyp == GOTO)
+ { g = get_lab(e->n, 1);
+ g = huntele(g, e->status, -1);
+ } else if (e->nxt)
+ { g = huntele(e->nxt, e->status, -1);
+ } else
+ { g = NULL;
+ }
+
+ t_record(n, e, g);
+}
+
+static void
+get_seq(int n, Sequence *s)
+{ SeqList *h;
+ Element *e;
+
+ e = huntele(s->frst, s->frst->status, -1);
+ for ( ; e; e = e->nxt)
+ { if (e->status & DONE)
+ { goto checklast;
+ }
+ e->status |= DONE;
+
+ if (e->n->ntyp == UNLESS)
+ { fatal("unless stmnt in never claim product", 0);
+ }
+
+ if (e->sub) /* IF or DO */
+ { Lextok *x = NULL;
+ Lextok *y = NULL;
+ Lextok *haselse = NULL;
+
+ for (h = e->sub; h; h = h->nxt)
+ { Lextok *t = h->this->frst->n;
+ if (t->ntyp == ELSE)
+ { if (verbose&64) printf("else at line %d\n", t->ln);
+ haselse = t;
+ continue;
+ }
+ if (t->ntyp != 'c')
+ { fatal("product, 'else' combined with non-condition", 0);
+ }
+
+ if (t->lft->ntyp == CONST /* true */
+ && t->lft->val == 1
+ && y == NULL)
+ { y = nn(ZN, CONST, ZN, ZN);
+ y->val = 0;
+ } else
+ { if (!x)
+ x = t;
+ else
+ x = nn(ZN, OR, x, t);
+ if (verbose&64)
+ { wrap_text(" [", x, "]\n");
+ } } }
+ if (haselse)
+ { if (!y)
+ { y = nn(ZN, '!', x, ZN);
+ }
+ if (verbose&64)
+ { wrap_text(" [else: ", y, "]\n");
+ }
+ haselse->ntyp = 'c'; /* replace else */
+ haselse->lft = y;
+ }
+
+ for (h = e->sub; h; h = h->nxt)
+ { t_record(n, e, h->this->frst);
+ get_seq(n, h->this);
+ }
+ } else
+ { if (e->n->ntyp == ATOMIC
+ || e->n->ntyp == D_STEP
+ || e->n->ntyp == NON_ATOMIC)
+ { get_sub(n, e);
+ } else
+ { set_el(n, e);
+ }
+ }
+checklast: if (e == s->last)
+ break;
+ }
+}
--- /dev/null
+++ b/sys/src/cmd/spin/pangen7.h
@@ -1,0 +1,2413 @@
+/***** spin: pangen7.h *****/
+
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
+
+static const char *pan_par[] = { /* generates pan.p */
+ "#include <sys/ipc.h>",
+ "#include <sys/shm.h>",
+ "#include <time.h>", /* for nanosleep */
+ "#include <assert.h>",
+ "#include <limits.h>",
+ "#ifdef BFS_DISK",
+ "#include <unistd.h>", /* for rmdir */
+ "#include <sys/stat.h>", /* for mkdir */
+ "#include <sys/types.h>",
+ "#include <fcntl.h>", /* for open */
+ "#endif",
+ "",
+ "#define Max(a,b) (((a)>(b))?(a):(b))",
+ "#ifndef WAIT_MAX",
+ " #define WAIT_MAX 2 /* seconds */",
+ "#endif",
+ "#define BFS_GEN 2 /* current and next generation */",
+ "",
+ "typedef struct BFS_Slot BFS_Slot;",
+ "typedef struct BFS_shared BFS_shared;",
+ "typedef struct BFS_data BFS_data;",
+ "",
+ "struct BFS_Slot {",
+ " #ifdef BFS_FIFO",
+ " enum bfs_types type; /* message type */",
+ " #endif",
+ " BFS_State *s_data; /* state data */",
+ " #ifndef BFS_QSZ",
+ " BFS_Slot *nxt; /* linked list */",
+ " #endif",
+ "};",
+ "",
+ "struct BFS_data {",
+ " double memcnt;",
+ " double nstates;",
+ " double nlinks;",
+ " double truncs;",
+ " ulong mreached;",
+ " ulong vsize;",
+ " ulong memory_left;",
+ " ulong punted;",
+ " ulong errors;",
+ " int override; /* after crash, if another proc clears locks */",
+ "};",
+ "",
+ "struct BFS_shared { /* about 13K for BFS_MAXPROCS=16 and BFS_MAXLOCKS=1028 */",
+ " volatile ulong quit; /* set to signal termination -- one word */",
+ " volatile ulong started;",
+ "",
+ " volatile uchar sh_owner[BFS_MAXLOCKS]; /* optional */",
+ "#ifdef BFS_CHECK",
+ " volatile uchar in_count[BFS_MAXLOCKS]; /* optional */",
+ "#endif",
+ " volatile int sh_locks[BFS_MAXLOCKS];",
+ " volatile ulong wait_count[BFS_MAXLOCKS]; /* optional */",
+ "",
+ " volatile BFS_data bfs_data[BFS_MAXPROCS];",
+ " volatile uchar bfs_flag[BFS_MAXPROCS]; /* running 0, normal exit 1, abnormal 2 */",
+ " volatile uchar bfs_idle[BFS_MAXPROCS]; /* set when all input queues are empty */",
+ "#ifdef BFS_DISK",
+ " volatile uchar bfs_out_cnt[BFS_MAXPROCS]; /* set when core writes a state */",
+ "#endif",
+ "",
+ "#ifdef BFS_QSZ",
+ " #define BFS_NORECYCLE",
+ " #if BFS_QSZ<=0",
+ " #error BFS_QSZ must be positive",
+ " #endif",
+ " #ifdef BFS_FIFO",
+ " #error BFS_QSZ cannot be combined with BFS_FIFO",
+ " #endif",
+ " #ifdef BFS_DISK",
+ " #error BFS_QSZ cannot be combined with BFS_DISK",
+ " #endif",
+ " volatile BFS_Slot bfsq[BFS_GEN][BFS_MAXPROCS][BFS_MAXPROCS][BFS_QSZ];",
+ " volatile uint bfs_ix[BFS_GEN][BFS_MAXPROCS][BFS_MAXPROCS];",
+ "#else",
+ " volatile BFS_Slot *head[BFS_GEN][BFS_MAXPROCS][BFS_MAXPROCS];",
+ "#endif",
+ "",
+ "#ifdef BFS_FIFO",
+ " volatile BFS_Slot *tail[BFS_GEN][BFS_MAXPROCS][BFS_MAXPROCS];",
+ " volatile BFS_Slot *dels[BFS_GEN][BFS_MAXPROCS][BFS_MAXPROCS];",
+ "#endif",
+ "#ifdef BFS_LOGMEM",
+ " volatile ulong logmem[1024];",
+ "#endif",
+ " volatile ulong mem_left;",
+ " volatile uchar *allocator; /* start of shared heap, must be last */",
+ "};",
+ "",
+ "enum bfs_types { EMPTY = 0, STATE, DELETED };",
+ "",
+ "extern volatile uchar *bfs_get_shared_mem(key_t, size_t);",
+ "extern BFS_Slot * bfs_new_slot(BFS_Trail *);",
+ "extern BFS_Slot * bfs_prep_slot(BFS_Trail *, BFS_Slot *);",
+ "extern BFS_Slot * bfs_next(void);",
+ "extern BFS_Slot * bfs_pack_state(Trail *, BFS_Trail *, int, BFS_Slot *);",
+ "extern SV_Hold * bfs_new_sv(int);",
+ "#if NRUNS>0",
+ "extern EV_Hold * bfs_new_sv_mask(int);",
+ "#endif",
+ "extern BFS_Trail * bfs_grab_trail(void);",
+ "extern BFS_Trail * bfs_unpack_state(BFS_Slot *);",
+ "extern int bfs_all_empty(void);",
+ "extern int bfs_all_idle(void);",
+ "extern int bfs_all_running(void);",
+ "extern int bfs_idle_and_empty(void);",
+ "extern size_t bfs_find_largest(key_t);",
+ "",
+ "extern void bfs_clear_locks(void);",
+ "extern void bfs_drop_shared_memory(void);",
+ "extern void bfs_explore_state(BFS_Slot *);",
+ "extern void bfs_initial_state(void);",
+ "extern void bfs_mark_done(int);",
+ "extern void bfs_printf(const char *fmt, ...);",
+ "extern void bfs_push_state(Trail *, BFS_Trail *, int);",
+ "extern void bfs_recycle(BFS_Slot *);",
+ "extern void bfs_release_trail(BFS_Trail *);",
+ "extern void bfs_run(void);",
+ "extern void bfs_setup_mem(void);",
+ "extern void bfs_setup(void);",
+ "extern void bfs_shutdown(const char *);",
+ "extern void bfs_statistics(void);",
+ "extern void bfs_store_state(Trail *, short);",
+ "extern void bfs_set_toggle(void);",
+ "extern void bfs_update(void);",
+ "",
+ "#ifdef MA",
+ " #error cannot combine -DMA with -DBFS_PAR",
+ " /* would require us to parallelize g_store */",
+ "#endif",
+ "#ifdef BCS",
+ " #error cannot combine -DBCS with -DBFS_PAR",
+ "#endif",
+ "#ifdef BFS_DISK",
+ " #ifdef BFS_FIFO",
+ " #error cannot combine BFS_DISK and BFS_FIFO",
+ " #endif",
+ " extern void bfs_disk_start(void);",
+ " extern void bfs_disk_stop(void);",
+ " extern void bfs_disk_out(void);",
+ " extern void bfs_disk_inp(void);",
+ " extern void bfs_disk_iclose(void);",
+ " extern void bfs_disk_oclose(void);",
+ " int bfs_out_fd[BFS_MAXPROCS];",
+ " int bfs_inp_fd[BFS_MAXPROCS];",
+ "#endif",
+ "",
+ "static BFS_shared *shared_memory;",
+ "#ifndef BFS_QSZ",
+ "static BFS_Slot *bfs_free_slot; /* local free list */",
+ "#endif",
+ "static BFS_Slot bfs_null;",
+ "static SV_Hold *bfs_svfree[VECTORSZ];",
+ "static uchar *bfs_heap; /* local pointer into heap */",
+ "static ulong bfs_left; /* local part of shared heap */",
+ "#if NRUNS>0",
+ "static void bfs_keep(EV_Hold *);",
+ "#endif",
+ "static long bfs_sent; /* nr msgs sent -- local to each process */",
+ "static long bfs_rcvd; /* nr msgs rcvd */",
+ "static long bfs_sleep_cnt; /* stats */",
+ "static long bfs_wcount;",
+ "static long bfs_gcount;",
+ "static ulong bfs_total_shared;",
+ "#ifdef BFS_STAGGER",
+ " static int bfs_stage_cnt = 0;",
+ " static void bfs_stagger_flush(void);",
+ "#endif",
+ "static int bfs_toggle; /* local variable, 0 or 1 */",
+ "static int bfs_qscan; /* scan input queues in order */",
+ "static ulong bfs_snapped;",
+ "static int shared_mem_id;",
+ "#ifndef NOREDUCE",
+ "static int bfs_nps; /* no preselection */",
+ "#endif",
+ "ulong bfs_punt; /* states dropped for lack of memory */",
+ "#if defined(VERBOSE) || defined(BFS_CHECK)",
+ "static const char *bfs_sname[] = {",
+ " \"EMPTY\", /* 0 */",
+ " \"STATE\", /* 1 */",
+ " \"STATE\", /* 2 = DELETED */",
+ " 0",
+ "};",
+ "#endif",
+ "static const char *bfs_lname[] = { /* match values defined in pangen2.c */",
+ " \"global lock\", /* BFS_GLOB */",
+ " \"ordinal\", /* BFS_ORD */",
+ " \"shared memory\", /* BFS_MEM */",
+ " \"print to stdout\", /* BFS_PRINT */",
+ " \"hashtable\", /* BFS_STATE */",
+ " 0",
+ "};",
+ "",
+ "static ulong bfs_count[DELETED+1]; /* indexed with bfs_types: EMPTY=0, STATE=1, DELETED=2 */",
+ "",
+ "static int bfs_keep_state;",
+ "",
+ "int Cores = 1;",
+ "int who_am_i = 0; /* root */",
+ "",
+ "#ifdef L_BOUND",
+ " int L_bound = L_BOUND;",
+ "#endif",
+ "",
+ "#ifdef BFS_CHECK",
+ "void",
+ "bfs_dump_now(char *s)",
+ "{ int i; char *p = (char *) &now;",
+ "",
+ " e_critical(BFS_PRINT);",
+ " printf(\"%%s\\t\", s);",
+ " printf(\"%%3lu: \", vsize);",
+ " for (i = 0; i < vsize; i++)",
+ " { printf(\"%%3d \", *p++);",
+ " }",
+ " printf(\" %%s\\noffsets:\\t\", s);",
+ " for (i = 0; i < now._nr_pr; i++)",
+ " { printf(\"%%3d \", proc_offset[i]);",
+ " }",
+ " printf(\"\\n\");",
+ " x_critical(BFS_PRINT);",
+ "}",
+ "",
+ "void",
+ "view_state(char *s) /* debugging */",
+ "{ int i;",
+ " char *p;",
+ " e_critical(BFS_PRINT);",
+ " printf(\"cpu%%02d %%s: \", who_am_i, s);",
+ " p = (char *)&now;",
+ " for (i = 0; i < vsize; i++)",
+ " printf(\"%%3d, \", *p++);",
+ " printf(\"\\n\"); fflush(stdout);",
+ " x_critical(BFS_PRINT);",
+ "}",
+ "#endif",
+ "",
+ "void",
+ "bfs_main(int ncores, int cycles)",
+ "{",
+ " if (cycles)",
+ " { fprintf(stderr, \"pan: cycle detection is not supported in this mode\\n\");",
+ " exit(1);",
+ " }",
+ "",
+ " if (ncores == 0) /* i.e., find out */",
+ " { FILE *fd;",
+ " char buf[512];",
+ " if ((fd = fopen(\"/proc/cpuinfo\", \"r\")) == NULL)",
+ " { /* cannot tell */",
+ " ncores = Cores; /* use the default */",
+ " } else",
+ " { while (fgets(buf, sizeof(buf), fd))",
+ " { if (strncmp(buf, \"processor\", strlen(\"processor\")) == 0)",
+ " { ncores++;",
+ " } }",
+ " fclose(fd);",
+ " ncores--;",
+ " if (verbose)",
+ " { printf(\"pan: %%d available cores\\n\", ncores+1);",
+ " } } }",
+ " if (ncores >= BFS_MAXPROCS)",
+ " { Cores = BFS_MAXPROCS-1; /* why -1? */",
+ " } else if (ncores < 1)",
+ " { Cores = 1;",
+ " } else",
+ " { Cores = ncores;",
+ " }",
+ " printf(\"pan: using %%d core%%s\\n\", Cores, (Cores>1)?\"s\":\"\");",
+ " fflush(stdout);",
+ "#ifdef BFS_DISK",
+ " bfs_disk_start();", /* create .spin */
+ "#endif",
+ " bfs_setup(); /* shared memory segments and fork */",
+ " bfs_run();",
+ " if (who_am_i == 0)",
+ " { stop_timer(0);",
+ " }",
+ " bfs_statistics();",
+ " bfs_mark_done(1);",
+ " if (who_am_i == 0)",
+ " { report_time();",
+ "#ifdef BFS_DISK",
+ " bfs_disk_stop();",
+ "#endif",
+ " }",
+ "#ifdef C_EXIT",
+ " C_EXIT; /* trust that it defines a fct */",
+ "#endif",
+ " bfs_drop_shared_memory();",
+ " exit(0);",
+ "}",
+ "",
+ "void",
+ "bfs_setup_mem(void)",
+ "{ size_t n;",
+ " key_t key;",
+ "#ifdef BFS_FIFO",
+ " bfs_null.type = EMPTY;",
+ "#endif",
+ " ntrpt = (Trail *) emalloc(sizeof(Trail));", /* just once */
+ "",
+ " if ((key = ftok(\".\", (int) 'L')) == -1)",
+ " { perror(\"ftok shared memory\");",
+ " exit(1);",
+ " }",
+ " n = bfs_find_largest(key);",
+ " bfs_total_shared = (ulong) n;",
+ "",
+ " shared_memory = (BFS_shared *) bfs_get_shared_mem(key, n); /* root */",
+ " shared_memory->allocator = (uchar *) shared_memory + sizeof(BFS_shared);",
+ " shared_memory->mem_left = (ulong) (n - sizeof(BFS_shared));",
+ "}",
+ "",
+ "ulong bfs_LowLim;",
+ "#ifndef BFS_RESERVE",
+ " #define BFS_RESERVE 5",
+ /* keep memory on global heap in reserve for first few cores */
+ /* that run out of their local allocation of shared mem */
+ /* 1~50 percent, 2~30 percent, 5~20 percent, >Cores=none */
+ "#else",
+ " #if BFS_RESERVE<1",
+ " #error BFS_RESERVE must be at least 1",
+ " #endif",
+ "#endif",
+ "",
+ "void",
+ "bfs_setup(void) /* executed by root */",
+ "{ int i, j;",
+ " ulong n; /* share of shared memory allocated to each core */",
+ "",
+ " n = shared_memory->mem_left / (Cores + Cores/(BFS_RESERVE)); /* keep some reserve */",
+ "",
+ " if ((n%%sizeof(void *)) != 0)",
+ " { n -= (n%%sizeof(void *)); /* align, without exceeding total */",
+ " }",
+ " for (i = 0; i < Cores-1; i++)",
+ " { j = fork();",
+ " if (j == -1)",
+ " { bfs_printf(\"fork failed\\n\");",
+ " exit(1);",
+ " }",
+ " if (j == 0)",
+ " { who_am_i = i+1; /* 1..Cores-1 */",
+ " break;",
+ " } }",
+ "",
+ " e_critical(BFS_MEM);",
+ " bfs_heap = (uchar *) shared_memory->allocator;",
+ " shared_memory->allocator += n;",
+ " shared_memory->mem_left -= n;",
+ " x_critical(BFS_MEM);",
+ "",
+ " bfs_left = n;",
+ " bfs_runs = 1;",
+ " bfs_LowLim = n / (2 * (ulong) Cores);", /* 50% */
+ "}",
+ "",
+ "void",
+ "bfs_run(void)",
+ "{ BFS_Slot *v;",
+ "",
+ "#ifdef BFS_DISK",
+ " bfs_disk_out();", /* create outqs */
+ "#endif",
+ " if (who_am_i == 0)",
+ " { bfs_initial_state();",
+ " }",
+ "#ifdef BFS_DISK",
+ " #ifdef BFS_STAGGER",
+ " bfs_stagger_flush();",
+ " #endif",
+ " bfs_disk_oclose();", /* sync and close outqs */
+ "#endif",
+ "#ifdef BFS_FIFO",
+ " static int i_count;",
+ "#endif",
+ "",
+ " srand(s_rand+HASH_NR);",
+ " bfs_qscan = 0;",
+ " bfs_toggle = 1 - bfs_toggle; /* after initial state */",
+ " e_critical(BFS_GLOB);",
+ " shared_memory->started++;",
+ " x_critical(BFS_GLOB);",
+ "",
+ " while (shared_memory->started != Cores) /* wait for all cores to connect */",
+ " { usleep(1);",
+ " }",
+ "",
+ "#ifdef BFS_DISK",
+ " bfs_disk_out();",
+ " bfs_disk_inp();",
+ "#endif",
+ "",
+ " start_timer();",
+ " while (shared_memory->quit == 0)",
+ " { v = bfs_next(); /* get next message from current generation */",
+ " if (v->s_data) /* v->type == STATE || v->type == DELETED */",
+ " { bfs_count[STATE]++;",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"GOT STATE (depth %%d, nr %%u)\\n\",",
+ " v->s_data->t_info->o_tt, v->s_data->nr);",
+ "#endif",
+ " /* last resort: start dropping states when out of memory */",
+ " if (bfs_left > 1024 || shared_memory->mem_left > 1024)",
+ " { bfs_explore_state(v);",
+ " } else",
+ " { static int warned_loss = 0;",
+ " if (warned_loss == 0 && who_am_i == 0)",
+ " { warned_loss++;",
+ " bfs_printf(\"out of shared memory - losing states\\n\");",
+ " }",
+ " bfs_punt++;",
+ " }",
+ "#if !defined(BFS_FIFO) && !defined(BFS_NORECYCLE)",
+ " bfs_recycle(v);",
+ "#endif",
+ "#ifdef BFS_FIFO",
+ " i_count = 0;",
+ "#endif",
+ " } else",
+ " { bfs_count[EMPTY]++;",
+ "#if defined(BFS_FIFO) && defined(BFS_CHECK)",
+ " assert(v->type == EMPTY);",
+ "#endif",
+ "#ifdef BFS_FIFO",
+ " if (who_am_i == 0)",
+ " { if (bfs_idle_and_empty())",
+ " { if (i_count++ > 10)",
+ " { shared_memory->quit = 1;",
+ " }",
+ " else usleep(1);",
+ " }",
+ " } else if (!bfs_all_running())",
+ " { bfs_shutdown(\"early termination\");",
+ " }",
+ "#else",
+ " if (who_am_i == 0)",
+ " { if (bfs_all_idle()) /* wait for it */",
+ " { if (!bfs_all_empty()) /* more states to process */",
+ " { bfs_set_toggle();",
+ " goto do_toggle;",
+ " } else /* done */",
+ " { shared_memory->quit = 1; /* step 4 */",
+ " }",
+ " } else",
+ " { bfs_sleep_cnt++;",
+ " }",
+ " } else",
+ " { /* wait for quit or idle bit to be reset by root */",
+ " while (shared_memory->bfs_idle[who_am_i] == 1",
+ " && shared_memory->quit == 0)",
+ " { if (bfs_all_running())",
+ " { bfs_sleep_cnt++;",
+ " usleep(10); /* new 6.2.3 */",
+ " } else",
+ " { bfs_shutdown(\"early termination\");",
+ " /* no return */",
+ " } }",
+ "do_toggle: bfs_qscan = 0;",
+ "#ifdef BFS_DISK",
+ " bfs_disk_iclose();",
+ " bfs_disk_oclose();",
+ "#endif",
+ " bfs_toggle = 1 - bfs_toggle;",
+ "#ifdef BFS_DISK",
+ " bfs_disk_out();",
+ " bfs_disk_inp();",
+ "#endif",
+ " #ifdef BFS_CHECK",
+ " bfs_printf(\"toggle: recv from %%d, send to %%d\\n\",",
+ " bfs_toggle, 1 - bfs_toggle);",
+ " #endif",
+ " }",
+ "#endif",
+ " } }",
+ "#ifdef BFS_CHECK",
+ " bfs_printf(\"done, sent %%5ld recvd %%5ld punt %%5lu sleep: %%ld\\n\",",
+ " bfs_sent, bfs_rcvd, bfs_punt, bfs_sleep_cnt);",
+ "#endif",
+ "}",
+ "",
+ "void",
+ "bfs_report_mem(void) /* called from within wrapup() */",
+ "{",
+ " printf(\"%%9.3f total shared memory usage\\n\\n\",",
+ " ((double) bfs_total_shared - (double) bfs_left)/(1024.*1024.));",
+ "}",
+ "",
+ "void",
+ "bfs_statistics(void)",
+ "{",
+ " #ifdef VERBOSE",
+ " enum bfs_types i;",
+ " #endif",
+ " if (verbose)",
+ " bfs_printf(\"states sent %%7ld recvd %%7ld stored %%8g sleeps: %%4ld, %%4ld, %%ld\\n\",",
+ " bfs_sent, bfs_rcvd, nstates, bfs_wcount, bfs_gcount, bfs_sleep_cnt);",
+ " if (0) bfs_printf(\"states punted %%7lu\\n\", bfs_punt);",
+ " #ifdef VERBOSE",
+ " for (i = EMPTY; i <= DELETED; i++)",
+ " { if (bfs_count[i] > 0)",
+ " { bfs_printf(\"%%6s %%8lu\\n\",",
+ " bfs_sname[i], bfs_count[i]);",
+ " } }",
+ " #endif",
+ " bfs_update();",
+ "",
+ " if (who_am_i == 0 && shared_memory)",
+ " { int i; ulong count = 0L;",
+ " done = 1;",
+ "",
+ " e_critical(BFS_PRINT);",
+ " wrapup();",
+ " if (verbose)",
+ " { printf(\"\\nlock-wait counts:\\n\");",
+ " for (i = 0; i < BFS_STATE; i++)",
+ " printf(\"%%16s %%9lu\\n\",",
+ " bfs_lname[i], shared_memory->wait_count[i]);",
+ "#ifndef BITSTATE",
+ " for (i = BFS_STATE; i < BFS_MAXLOCKS; i++)",
+ " { if (0)",
+ " printf(\" [%%6d] %%9lu\\n\",",
+ " i, shared_memory->wait_count[i]);",
+ " count += shared_memory->wait_count[i];",
+ " }",
+ " printf(\"%%16s %%9lu (avg per region)\\n\",",
+ " bfs_lname[BFS_STATE], count/(BFS_MAXLOCKS - BFS_STATE));",
+ "#endif",
+ " }",
+ " fflush(stdout);",
+ " x_critical(BFS_PRINT);",
+ " }",
+ "}",
+ "",
+ "void",
+ "bfs_snapshot(void)",
+ "{ clock_t stop_time;",
+ " double delta_time;",
+ " struct tms stop_tm;",
+ " volatile BFS_data *s;",
+ "",
+ " e_critical(BFS_PRINT);",
+ " printf(\"cpu%%02d Depth= %%7lu States= %%8.3g Transitions= %%8.3g \",",
+ " who_am_i, mreached, nstates, nstates+truncs);",
+ " printf(\"Memory= %%9.3f\\t\", memcnt/1048576.);",
+ " printf(\"SharedMLeft= %%4lu \", bfs_left/1048576);",
+ " stop_time = times(&stop_tm);",
+ " delta_time = ((double) (stop_time - start_time))/((double) sysconf(_SC_CLK_TCK));",
+ " if (delta_time > 0.01)",
+ " { printf(\"t= %%6.3g R= %%6.0g\\n\", delta_time, nstates/delta_time);",
+ " } else",
+ " { printf(\"t= %%6.3g R= %%6.0g\\n\", 0., 0.);",
+ " }",
+ " fflush(stdout);",
+ " x_critical(BFS_PRINT);",
+ "",
+ " s = &shared_memory->bfs_data[who_am_i];",
+ " s->mreached = (ulong) mreached;",
+ " s->vsize = (ulong) vsize;",
+ " s->errors = (int) errors;",
+ " s->memcnt = (double) memcnt;",
+ " s->nstates = (double) nstates;",
+ " s->nlinks = (double) nlinks;",
+ " s->truncs = (double) truncs;",
+ " s->memory_left = (ulong) bfs_left;",
+ " s->punted = (ulong) bfs_punt;",
+ " bfs_snapped++; /* for bfs_best */",
+ "}",
+ "",
+ "void",
+ "bfs_shutdown(const char *s)",
+ "{",
+ " bfs_clear_locks(); /* in case we interrupted at a bad point */",
+ " if (!strstr(s, \"early \") || verbose)",
+ " { bfs_printf(\"stop (%%s)\\n\", s);",
+ " }",
+ " bfs_update();",
+ " if (who_am_i == 0)",
+ " { wrapup();",
+ "#ifdef BFS_DISK",
+ " bfs_disk_stop();",
+ "#endif",
+ " }",
+ " bfs_mark_done(2);",
+ " pan_exit(2);",
+ "}",
+ "",
+ "SV_Hold *bfs_free_hold;",
+ "",
+ "SV_Hold *",
+ "bfs_get_hold(void)",
+ "{ SV_Hold *x;",
+ " if (bfs_free_hold)",
+ " { x = bfs_free_hold;",
+ " bfs_free_hold = bfs_free_hold->nxt;",
+ " } else",
+ " { x = (SV_Hold *) sh_malloc((ulong) sizeof(SV_Hold));",
+ " }",
+ " return x;",
+ "}",
+ "",
+ "BFS_Trail *",
+ "bfs_unpack_state(BFS_Slot *n) /* called in bfs_explore_state */",
+ "{ BFS_Trail *otrpt;",
+ " BFS_State *bfs_t;",
+ " int vecsz;",
+ "",
+ " if (!n || !n->s_data || !n->s_data->t_info)",
+ " { bfs_Uerror(\"internal error\");",
+ " }",
+ " otrpt = (BFS_Trail *) ((BFS_State *) n->s_data)->t_info;",
+ "",
+ " trpt->ostate = otrpt->ostate;",
+ " trpt->st = otrpt->st;",
+ " trpt->o_tt = otrpt->o_tt;",
+ " trpt->pr = otrpt->pr;",
+ " trpt->tau = otrpt->tau;",
+ " trpt->o_pm = otrpt->o_pm;",
+ " if (trpt->ostate)",
+ " trpt->o_t = t_id_lkup[otrpt->t_id];",
+ "#if defined(C_States) && (HAS_TRACK==1)",
+ " c_revert((uchar *) &(now.c_state[0]));",
+ "#endif",
+ " if (trpt->o_pm & 4) /* rv succeeded */",
+ " { return (BFS_Trail *) 0; /* revisit not needed */",
+ " }",
+ "#ifndef NOREDUCE",
+ " bfs_nps = 0;",
+ "#endif",
+ " if (trpt->o_pm & 8) /* rv attempt failed */",
+ " { revrv++;",
+ " if (trpt->tau&8)",
+ " { trpt->tau &= ~8; /* break atomic */",
+ "#ifndef NOREDUCE",
+ " } else if (trpt->tau&32) /* void preselection */",
+ " { trpt->tau &= ~32;",
+ " bfs_nps = 1; /* no preselection in repeat */",
+ "#endif",
+ " } }",
+ " trpt->o_pm &= ~(4|8);",
+ " if (trpt->o_tt > mreached)",
+ " { static ulong nr = 0L, nc;",
+ " mreached = trpt->o_tt;",
+ " nc = (long) nstates/FREQ;",
+ " if (nc > nr)",
+ " { nr = nc;",
+ " bfs_snapshot();",
+ " } }",
+ " depth = trpt->o_tt;",
+ " if (depth >= maxdepth)",
+ " {",
+ "#if SYNC",
+ " if (boq != -1)",
+ " { BFS_Trail *x = (BFS_Trail *) trpt->ostate;",
+ " if (x) x->o_pm |= 4; /* rv not failing */",
+ " }",
+ "#endif",
+ " truncs++;",
+ " if (!warned)",
+ " { warned = 1;",
+ " bfs_printf(\"error: max search depth too small\\n\");",
+ " }",
+ " if (bounded)",
+ " { bfs_uerror(\"depth limit reached\");",
+ " }",
+ " return (BFS_Trail *) 0;",
+ " }",
+ "",
+ " bfs_t = n->s_data;",
+ "#if NRUNS>0",
+ " vsize = bfs_t->omask->sz;",
+ "#else",
+ " vsize = ((State *) (bfs_t->osv))->_vsz;",
+ "#endif",
+ "#if SYNC",
+ " boq = bfs_t->boq;",
+ "#endif",
+ "",
+ "#if defined(Q_PROVISO) && !defined(BITSTATE) && defined(FULLSTACK)",
+ " #ifdef USE_TDH",
+ " if (((uchar *)(bfs_t->lstate))) /* if BFS_INQ is set */",
+ " { *((uchar *) bfs_t->lstate) = 0; /* turn it off */",
+ " }",
+ " #else",
+ " if (bfs_t->lstate) /* bfs_par */",
+ " { bfs_t->lstate->tagged = 0; /* bfs_par state removed from q */",
+ " }",
+ " #endif",
+ "#endif",
+ " memcpy((char *) &now, (uchar *) bfs_t->osv, vsize);",
+ "#if !defined(NOCOMP) && !defined(HC) && NRUNS>0",
+ " Mask = (uchar *) bfs_t->omask->sv; /* in shared memory */",
+ "#endif",
+ "#ifdef BFS_CHECK",
+ " if (0) bfs_dump_now(\"got1\");",
+ "#endif",
+ "#ifdef TRIX",
+ " re_populate();",
+ "#else",
+ " #if NRUNS>0",
+ " if (now._nr_pr > 0)",
+ " {",
+ " #if VECTORSZ>32000",
+ " proc_offset = (int *) bfs_t->omask->po;",
+ " #else",
+ " proc_offset = (short *) bfs_t->omask->po;",
+ " #endif",
+ " proc_skip = (uchar *) bfs_t->omask->ps;",
+ " }",
+ " if (now._nr_qs > 0)",
+ " {",
+ " #if VECTORSZ>32000",
+ " q_offset = (int *) bfs_t->omask->qo;",
+ " #else",
+ " q_offset = (short *) bfs_t->omask->qo;",
+ " #endif",
+ " q_skip = (uchar *) bfs_t->omask->qs;",
+ " }",
+ " #endif",
+ "#endif",
+ " vecsz = ((State *) bfs_t->osv)->_vsz;",
+ "#ifdef BFS_CHECK",
+ " assert(vecsz > 0 && vecsz < VECTORSZ);",
+ "#endif",
+ " { SV_Hold *x = bfs_get_hold();",
+ " x->sv = bfs_t->osv;",
+ " x->nxt = bfs_svfree[vecsz];",
+ " bfs_svfree[vecsz] = x;",
+ " bfs_t->osv = (State *) 0;",
+ " }",
+ "#if NRUNS>0",
+ " bfs_keep(bfs_t->omask);",
+ "#endif",
+ "",
+ "#ifdef BFS_CHECK",
+ " if (0) bfs_dump_now(\"got2\");",
+ " if (0) view_state(\"after\");",
+ "#endif",
+ " return (BFS_Trail *) bfs_t->t_info;",
+ "}",
+ "void",
+ "bfs_initial_state(void)",
+ "{",
+ "#ifdef BFS_CHECK",
+ " assert(trpt != NULL);",
+ "#endif",
+ " trpt->ostate = (H_el *) 0;",
+ " trpt->o_tt = -1;",
+ " trpt->tau = 0;",
+ "#ifdef VERI",
+ " trpt->tau |= 4; /* claim moves first */",
+ "#endif",
+ " bfs_store_state(trpt, boq); /* initial state : bfs_lib.c */",
+ "}",
+ "",
+ "#ifdef BITSTATE",
+ " #define bfs_do_store(v, n) b_store(v, n)",
+ "#else",
+ " #ifdef USE_TDH",
+ " #define bfs_do_store(v, n) o_store(v, n)",
+ " #else",
+ " #define bfs_do_store(v, n) h_store(v, n)",
+ " #endif",
+ "#endif",
+ "",
+ "#ifdef BFS_SEP_HASH",
+ "int",
+ "bfs_seen_before(void)",
+ "{ /* cannot set trpt->tau |= 64 to mark successors outside stack */",
+ " /* since the check is done remotely and the trpt value is gone */",
+ " #ifdef VERI",
+ " if (!trpt->ostate /* initial state */",
+ " || ((trpt->tau&4) /* starting claim moves(s) */",
+ " && !(((BFS_Trail *)trpt->ostate)->tau&4))) /* prev move: prog */",
+ " { return 0; /* claim move: mid-state not stored */",
+ " } /* else */",
+ " #endif",
+ " if (!bfs_do_store((char *)&now, vsize)) /* sep_hash */",
+ " { nstates++; /* local count */",
+ " return 0; /* new state */",
+ " }",
+ " #ifdef BFS_CHECK",
+ " bfs_printf(\"seen before\\n\");",
+ " #endif",
+ " truncs++;",
+ " return 1; /* old state */",
+ "}",
+ "#endif",
+ "",
+ "void",
+ "bfs_explore_state(BFS_Slot *v) /* generate all successors of v */",
+ "{ BFS_Trail *otrpt;",
+ " Trans *t;",
+ "#ifdef HAS_UNLESS",
+ " int E_state;",
+ "#endif",
+ " int tt;",
+ " short II, To = BASE, From = (short) (now._nr_pr-1);",
+ " short oboq = boq;",
+ " uchar _n, _m, ot;",
+ "",
+ " memset(ntrpt, 0, sizeof(Trail));",
+ " otrpt = bfs_unpack_state(v); /* BFS_Trail */",
+ "",
+ " if (!otrpt) { return; } /* e.g., depth limit reached */",
+ "#ifdef L_BOUND",
+ " #if defined(VERBOSE)",
+ " bfs_printf(\"Unpacked state with l_bound %%d -- sds %%p\\n\",",
+ " now._l_bnd, now._l_sds);",
+ " #endif",
+ "#endif",
+ "",
+ "#if defined(C_States) && (HAS_TRACK==1)",
+ " c_revert((uchar *) &(now.c_state[0]));",
+ "#endif",
+ "",
+ "#ifdef BFS_SEP_HASH",
+ " if (bfs_seen_before()) return;",
+ "#endif",
+ "",
+ "#ifdef VERI", /* could move to just before store_state */
+ " if (now._nr_pr == 0 /* claim terminated */",
+ " || stopstate[((Pclaim *)pptr(0))->_t][((Pclaim *)pptr(0))->_p])",
+ " { bfs_uerror(\"end state in claim reached\");",
+ " }",
+ "#endif",
+ " trpt->tau &= ~1; /* timeout off */",
+ "#ifdef VERI",
+ " if (trpt->tau&4) /* claim move */",
+ " { trpt->tau |= (otrpt->tau)&1; /* inherit from prog move */",
+ " From = To = 0; /* claim */",
+ " goto Repeat_two;",
+ " }",
+ "#endif",
+ "#ifndef NOREDUCE",
+ " if (boq == -1 && !(trpt->tau&8) && bfs_nps == 0)",
+ " for (II = now._nr_pr-1; II >= BASE; II -= 1)",
+ " {",
+ "Pickup: this = pptr(II);",
+ " tt = (int) ((P0 *)this)->_p;",
+ " ot = (uchar) ((P0 *)this)->_t;",
+ " if (trans[ot][tt]->atom & 8)",
+ " { t = trans[ot][tt];",
+ " if (t->qu[0] != 0)",
+ " { if (!q_cond(II, t))",
+ " continue;",
+ " }",
+ " From = To = II;",
+ " trpt->tau |= 32; /* preselect marker */",
+ " #ifdef VERBOSE",
+ " bfs_printf(\"%%3ld: proc %%d PreSelected (tau=%%d)\\n\", ",
+ " depth, II, trpt->tau);",
+ " #endif",
+ " goto Repeat_two;",
+ " } }",
+ " trpt->tau &= ~32;",
+ "#endif",
+ "",
+ "Repeat_one:",
+ " if (trpt->tau&8)",
+ " { From = To = (short ) trpt->pr; /* atomic */",
+ " } else",
+ " { From = now._nr_pr-1;",
+ " To = BASE;",
+ " }",
+ "#if defined(VERI) || !defined(NOREDUCE) || defined(ETIM)",
+ "Repeat_two: /* MainLoop */",
+ "#endif",
+ " _n = _m = 0;",
+ " for (II = From; II >= To; II -= 1) /* all processes */",
+ " {",
+ "#ifdef BFS_CHECK",
+ " bfs_printf(\"proc %%d (%%d - %%d)\\n\", II, From, To);",
+ "#endif",
+ "#if SYNC ",
+ " if (boq != -1 && trpt->pr == II)",
+ " { continue; /* no rendezvous with same proc */",
+ " }",
+ "#endif",
+ " this = pptr(II);",
+ " tt = (int) ((P0 *)this)->_p;",
+ " ot = (uchar) ((P0 *)this)->_t;",
+ " ntrpt->pr = (uchar) II;",
+ " ntrpt->st = tt; ",
+ " trpt->o_pm &= ~1; /* no move yet */",
+ "#ifdef EVENT_TRACE",
+ " trpt->o_event = now._event;",
+ "#endif",
+ "#ifdef HAS_PRIORITY",
+ " if (!highest_priority(((P0 *)this)->_pid, II, t))",
+ " { continue;",
+ " }",
+ "#else",
+ " #ifdef HAS_PROVIDED",
+ " if (!provided(II, ot, tt, t))",
+ " { continue;",
+ " }",
+ " #endif",
+ "#endif",
+ "#ifdef HAS_UNLESS",
+ " E_state = 0;",
+ "#endif",
+ " for (t = trans[ot][tt]; t; t = t->nxt) /* all process transitions */",
+ " {",
+ "#ifdef BFS_CHECK",
+ " assert(t_id_lkup[t->t_id] == t); /* for reverse lookup in bfs_unpack_state */",
+ "#endif",
+ "#ifdef VERBOSE",
+ " if (0) bfs_printf(\"\\tproc %%d tr %%d\\n\", II, t->forw);",
+ "#endif",
+ "#ifdef HAS_UNLESS",
+ " if (E_state > 0",
+ " && E_state != t->e_trans)",
+ " break;",
+ "#endif",
+ " /* trpt->o_t = */ ntrpt->o_t = t;",
+ " oboq = boq;",
+ "",
+ " if (!(_m = do_transit(t, II)))",
+ " continue;",
+ "",
+ " trpt->o_pm |= 1; /* we moved */",
+ " (trpt+1)->o_m = _m; /* for unsend */",
+ "#ifdef PEG",
+ " peg[t->forw]++;",
+ "#endif",
+ "#ifdef VERBOSE",
+ " e_critical(BFS_PRINT);",
+ " printf(\"%%3ld: proc %%d exec %%d, \",",
+ " depth, II, t->forw);",
+ " printf(\"%%d to %%d, %%s %%s %%s\",",
+ " tt, t->st, t->tp,",
+ " (t->atom&2)?\"atomic\":\"\",",
+ " (boq != -1)?\"rendez-vous\":\"\");",
+ " #ifdef HAS_UNLESS",
+ " if (t->e_trans)",
+ " printf(\" (escapes to state %%d)\", t->st);",
+ " #endif",
+ " printf(\" %%saccepting [tau=%%d]\\n\",",
+ " (trpt->o_pm&2)?\"\":\"non-\", trpt->tau);",
+ " x_critical(BFS_PRINT);",
+ "#endif",
+ "#ifdef HAS_UNLESS",
+ " E_state = t->e_trans;",
+ " #if SYNC>0",
+ " if (t->e_trans > 0 && boq != -1)",
+ " { fprintf(efd, \"error: rendezvous stmnt in the escape clause\\n\");",
+ " fprintf(efd, \" of unless stmnt not compatible with -DBFS\\n\");",
+ " pan_exit(1);",
+ " }",
+ " #endif",
+ "#endif",
+ " if (t->st > 0)",
+ " { ((P0 *)this)->_p = t->st;",
+ " }",
+ " /* use the ostate ptr, with type *H_el, to temporarily store *BFS_Trail */",
+ "#ifdef BFS_NOTRAIL",
+ " ntrpt->ostate = (H_el *) 0; /* no error-traces in this mode */",
+ "#else",
+ " ntrpt->ostate = (H_el *) otrpt; /* parent stackframe */",
+ "#endif",
+ " /* ntrpt->st = tt; * was already set above */",
+ "",
+ " if (boq == -1 && (t->atom&2)) /* atomic */",
+ " { ntrpt->tau = 8; /* record for next move */",
+ " } else",
+ " { ntrpt->tau = 0; /* no timeout or preselect etc */",
+ " }",
+ "#ifdef VERI",
+ " ntrpt->tau |= trpt->tau&4; /* if claim, inherit */",
+ " if (boq == -1 && !(ntrpt->tau&8)) /* unless rv or atomic */",
+ " { if (ntrpt->tau&4) /* claim */",
+ " { ntrpt->tau &= ~4; /* switch to prog */",
+ " } else",
+ " { ntrpt->tau |= 4; /* switch to claim */",
+ " } }",
+ "#endif",
+ "#ifdef L_BOUND",
+ " { uchar obnd = now._l_bnd;",
+ " uchar *os = now._l_sds;",
+ " #ifdef VERBOSE",
+ " bfs_printf(\"saving bound %%d -- sds %%p\\n\", obnd, (void *) os);",
+ " #endif",
+ "#endif",
+ "",
+ " bfs_store_state(ntrpt, oboq);",
+ "#ifdef EVENT_TRACE",
+ " now._event = trpt->o_event;",
+ "#endif",
+ " /* undo move and generate other successor states */",
+ " trpt++; /* this is where ovals and ipt are set */",
+ " do_reverse(t, II, _m); /* restore now. */",
+ "#ifdef L_BOUND",
+ " #ifdef VERBOSE",
+ " bfs_printf(\"restoring bound %%d -- sds %%p\\n\", obnd, (void *) os);",
+ " #endif",
+ " now._l_bnd = obnd;",
+ " now._l_sds = os;",
+ " }",
+ "#endif",
+ " trpt--;",
+ "#ifdef VERBOSE",
+ " e_critical(BFS_PRINT);",
+ " printf(\"%%3ld: proc %%d \", depth, II);",
+ " printf(\"reverses %%d, %%d to %%d,\", t->forw, tt, t->st);",
+ " printf(\" %%s [abit=%%d,adepth=%%d,\", t->tp, now._a_t, 0);",
+ " printf(\"tau=%%d,%%d]\\n\", trpt->tau, (trpt-1)->tau);",
+ " x_critical(BFS_PRINT);",
+ "#endif",
+ " reached[ot][t->st] = 1;",
+ " reached[ot][tt] = 1;",
+ "",
+ " ((P0 *)this)->_p = tt;",
+ " _n |= _m;",
+ " } }",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"done _n = %%d\\n\", _n);",
+ "#endif",
+ "",
+ "#ifndef NOREDUCE",
+ " /* preselected - no succ definitely outside stack */",
+ " if ((trpt->tau&32) && !(trpt->tau&64))",
+ " { From = now._nr_pr-1; To = BASE;",
+ " #ifdef VERBOSE",
+ " bfs_printf(\"%%3ld: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
+ " depth, II+1, (int) _n, trpt->tau);",
+ " #endif",
+ " _n = 0; trpt->tau &= ~32;",
+ " if (II >= BASE)",
+ " { goto Pickup;",
+ " }",
+ " goto Repeat_two;",
+ " }",
+ " trpt->tau &= ~(32|64);",
+ "#endif",
+ " if (_n == 0",
+ "#ifdef VERI",
+ " && !(trpt->tau&4)",
+ "#endif",
+ " )",
+ " { /* no successor states generated */",
+ " if (boq != -1) /* was rv move */",
+ " { BFS_Trail *x = (BFS_Trail *) trpt->ostate; /* pre-rv state */",
+ " if (x && ((x->tau&8) || (x->tau&32))) /* break atomic or preselect */",
+ " { x->o_pm |= 8; /* mark failure */",
+ " this = pptr(otrpt->pr);",
+ " ((P0 *) this)->_p = otrpt->st; /* reset state */",
+ " unsend(boq); /* retract rv offer */",
+ " boq = -1;",
+ "#ifdef VERBOSE",
+ " printf(\"repush state\\n\");",
+ "#endif",
+ " bfs_push_state(NULL, x, x->o_tt); /* repush rv fail */",
+ " } /* else the rv need not be retried */",
+ " } else if (now._nr_pr > BASE) /* possible deadlock */",
+ " { if ((trpt->tau&8)) /* atomic step blocked */",
+ " { trpt->tau &= ~(1|8); /* 1=timeout, 8=atomic */",
+ " goto Repeat_one;",
+ " }",
+ "#ifdef ETIM",
+ " /* if timeouts were used in the model */",
+ " if (!(trpt->tau&1))",
+ " { trpt->tau |= 1; /* enable timeout */",
+ " goto Repeat_two;",
+ " }",
+ "#endif",
+ " if (!noends && !endstate())",
+ " { bfs_uerror(\"invalid end state.\");",
+ " }",
+ " }",
+ "#ifdef VERI",
+ " else /* boq == -1 && now._nr_pr == BASE && trpt->tau != 4 */",
+ " { trpt->tau |= 4; /* switch to claim for stutter moves */",
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: proc -1 exec -1, (stutter move)\\n\", depth, II);",
+ " #endif",
+ " bfs_store_state(trpt, boq);", /* doesn't store it but queues it */
+ " #ifdef VERBOSE",
+ " printf(\"%%3ld: proc -1 reverses -1, (stutter move)\\n\", depth, II);",
+ " #endif",
+ " trpt->tau &= ~4; /* undo, probably not needed */",
+ " }",
+ "#endif",
+ " }",
+ "#ifdef BFS_NOTRAIL",
+ " bfs_release_trail(otrpt);",
+ "#endif",
+ "}",
+ "#if !defined(BFS_FIFO) && !defined(BFS_NORECYCLE)",
+ "void",
+ "bfs_recycle(BFS_Slot *n)",
+ "{",
+ " #ifdef BFS_CHECK",
+ " assert(n != &bfs_null);",
+ " #endif",
+ " n->nxt = bfs_free_slot;",
+ " bfs_free_slot = n;",
+ "",
+ " #ifdef BFS_CHECK",
+ " bfs_printf(\"recycles %%s -- %%p\\n\",",
+ " n->s_data?\"STATE\":\"EMPTY\", (void *) n);",
+ " #endif",
+ "}",
+ "#endif",
+ "#ifdef BFS_FIFO",
+ "int",
+ "bfs_empty(int p)", /* return Cores if all empty or index of first non-empty q of p */
+ "{ int i;",
+ " const int dst = 0;",
+ " for (i = 0; i < Cores; i++)",
+ " { if (shared_memory->head[dst][p][i] != (BFS_Slot *) 0)",
+ " {",
+ " volatile BFS_Slot *x = shared_memory->head[dst][p][i];",
+ " while (x && x->type == DELETED)",
+ " { x = x->nxt;",
+ " }",
+ " if (!x)",
+ " { continue;",
+ " }",
+ " if (p == who_am_i)",
+ " { shared_memory->head[dst][p][i] = x;",
+ " }",
+ " #ifdef BFS_CHECK",
+ " bfs_printf(\"input q [%%d][%%d][%%d] !empty\\n\",",
+ " dst, p, i);",
+ " #endif",
+ " return i;",
+ " } }",
+ " #ifdef BFS_CHECK",
+ " bfs_printf(\"all input qs [%%d][%%d][0..max] empty\\n\",",
+ " dst, p);",
+ " #endif ",
+ " return Cores;",
+ "}",
+ "#endif",
+ "#ifdef BFS_DISK",
+ "void",
+ "bfs_ewrite(int fd, const void *p, size_t count)",
+ "{",
+ " if (write(fd, p, count) != count)",
+ " { perror(\"diskwrite\");",
+ " Uerror(\"aborting\");",
+ " }",
+ "}",
+ "",
+ "void",
+ "bfs_eread(int fd, void *p, size_t count)",
+ "{",
+ " if (read(fd, p, count) != count)",
+ " { perror(\"diskread\");",
+ " Uerror(\"aborting\");",
+ " }",
+ "}",
+ "",
+ "void",
+ "bfs_sink_disk(int who_are_you, BFS_Slot *n)",
+ "{ SV_Hold *x;",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"sink_disk -> %%d\\n\", who_are_you);",
+ "#endif",
+ " bfs_ewrite(bfs_out_fd[who_are_you], (const void *) n->s_data->t_info, sizeof(BFS_Trail));",
+ " bfs_ewrite(bfs_out_fd[who_are_you], (const void *) &vsize, sizeof(ulong));",
+ " bfs_ewrite(bfs_out_fd[who_are_you], &now, vsize);",
+ "",
+ " bfs_release_trail(n->s_data->t_info);",
+ " n->s_data->t_info = (BFS_Trail *) 0;",
+ "",
+ "#if NRUNS>0",
+ " bfs_ewrite(bfs_out_fd[who_are_you], (const void *) &(n->s_data->omask), sizeof(EV_Hold *));",
+ "#endif",
+ "#ifdef Q_PROVISO",
+ " bfs_ewrite(bfs_out_fd[who_are_you], (const void *) &(n->s_data->lstate), sizeof(H_el *));",
+ "#endif",
+ "#if SYNC>0",
+ " bfs_ewrite(bfs_out_fd[who_are_you], (const void *) &(n->s_data->boq), sizeof(short));",
+ "#endif",
+ "#if VERBOSE",
+ " bfs_ewrite(bfs_out_fd[who_are_you], (const void *) &(n->s_data->nr), sizeof(ulong));",
+ "#endif",
+ " shared_memory->bfs_out_cnt[who_am_i] = 1;", /* wrote at least one state */
+ "}",
+ "void",
+ "bfs_source_disk(int fd, volatile BFS_Slot *n)",
+ "{ ulong nb; /* local temporary */",
+ " SV_Hold *x;",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"source_disk <- %%d\\n\", who_am_i);",
+ "#endif",
+ " n->s_data->t_info = bfs_grab_trail();",
+ " bfs_eread(fd, (void *) n->s_data->t_info, sizeof(BFS_Trail));",
+ " bfs_eread(fd, (void *) &nb, sizeof(ulong));",
+ "",
+ " x = bfs_new_sv(nb); /* space for osv isn't already allocated */",
+ " n->s_data->osv = x->sv;",
+ " x->sv = (State *) 0;",
+ " x->nxt = bfs_free_hold;",
+ " bfs_free_hold = x;",
+ "",
+ " bfs_eread(fd, (void *) n->s_data->osv, (size_t) nb);",
+ "#if NRUNS>0",
+ " bfs_eread(fd, (void *) &(n->s_data->omask), sizeof(EV_Hold *));",
+ "#endif",
+ "#ifdef Q_PROVISO",
+ " bfs_eread(fd, (void *) &(n->s_data->lstate), sizeof(H_el *));",
+ "#endif",
+ "#if SYNC>0",
+ " bfs_eread(fd, (void *) &(n->s_data->boq), sizeof(short));",
+ "#endif",
+ "#if VERBOSE",
+ " bfs_eread(fd, (void *) &(n->s_data->nr), sizeof(ulong));",
+ "#endif",
+ "}",
+ "#endif",
+ "",
+ "#ifndef BFS_QSZ",
+ " #ifdef BFS_STAGGER",
+ "static BFS_Slot *bfs_stage[BFS_STAGGER];",
+ "",
+ "static void",
+ "bfs_stagger_flush(void)",
+ "{ int i, who_are_you;",
+ " int dst = 1 - bfs_toggle;",
+ " BFS_Slot *n;",
+ " who_are_you = (rand()%%Cores);", /* important: all to the same cpu, but reversed */
+ " for (i = bfs_stage_cnt-1; i >= 0; i--)",
+ " { n = bfs_stage[i];",
+ " #ifdef BFS_DISK",
+ " bfs_sink_disk(who_are_you, n);",
+ " bfs_stage[i] = (BFS_Slot *) 0;",
+ " #endif",
+ " n->nxt = (BFS_Slot *) shared_memory->head[dst][who_are_you][who_am_i];",
+ " shared_memory->head[dst][who_are_you][who_am_i] = n;",
+ " /* bfs_sent++; */",
+ " }",
+ " #ifdef VERBOSE",
+ " bfs_printf(\"stagger flush %%d states to %%d\\n\",",
+ " bfs_stage_cnt, who_are_you);",
+ " #endif",
+ " bfs_stage_cnt = 0;",
+ "}",
+ "",
+ "void",
+ "bfs_stagger_add(BFS_Slot *n)",
+ "{",
+ " if (bfs_stage_cnt == BFS_STAGGER)",
+ " { bfs_stagger_flush();",
+ " }",
+ " bfs_stage[bfs_stage_cnt++] = n;",
+ "}",
+ " #endif",
+ "#endif",
+ "",
+ "void",
+ "bfs_push_state(Trail *x, BFS_Trail *y, int tt)",
+ "{ int who_are_you;",
+ "#ifdef BFS_FIFO",
+ " const int dst = 0;",
+ "#else",
+ " int dst = 1 - bfs_toggle;",
+ "#endif",
+ "#ifdef BFS_QSZ",
+ " uint z;",
+ " if (bfs_keep_state > 0)",
+ " { who_are_you = bfs_keep_state - 1;",
+ " } else",
+ " { who_are_you = (rand()%%Cores);",
+ " }",
+ " z = shared_memory->bfs_ix[dst][who_are_you][who_am_i];",
+ " if (z >= BFS_QSZ)",
+ " { static int warned_qloss = 0;",
+ " if (warned_qloss == 0 && who_am_i == 0)",
+ " { warned_qloss++;",
+ " bfs_printf(\"BFS_QSZ too small - losing states\\n\");",
+ " }",
+ " bfs_punt++;",
+ " return;",
+ " }",
+ " shared_memory->bfs_ix[dst][who_are_you][who_am_i] = z+1;",
+ " BFS_Slot *n = bfs_pack_state(x, y, tt, bfs_prep_slot(y, ",
+ " (BFS_Slot *) &(shared_memory->bfsq[dst][who_are_you][who_am_i][z])));",
+ "#else",
+ " BFS_Slot *n = bfs_pack_state(x, y, tt, bfs_new_slot(y));",
+ "",
+ " #ifdef BFS_GREEDY",
+ " who_are_you = who_am_i; /* for testing only */",
+ " #else",
+ " if (bfs_keep_state > 0)",
+ " { who_are_you = bfs_keep_state - 1;",
+ " } else",
+ " {",
+ " #ifdef BFS_STAGGER",
+ " who_are_you = -1;",
+ " bfs_stagger_add(n);",
+ " goto done;",
+ " #else",
+ " who_are_you = (rand()%%Cores);",
+ " #endif",
+ " }",
+ " #endif",
+ " #ifdef BFS_FIFO",
+ " if (!shared_memory->tail[dst][who_are_you][who_am_i])",
+ " { shared_memory->dels[dst][who_are_you][who_am_i] =",
+ " shared_memory->tail[dst][who_are_you][who_am_i] =",
+ " shared_memory->head[dst][who_are_you][who_am_i] = n;",
+ " } else",
+ " { shared_memory->tail[dst][who_are_you][who_am_i]->nxt = n;",
+ " shared_memory->tail[dst][who_are_you][who_am_i] = n;",
+ " }",
+ " shared_memory->bfs_idle[who_are_you] = 0;",
+ " #else",
+ " #ifdef BFS_DISK",
+ " bfs_sink_disk(who_are_you, n);",
+ " #endif",
+ " n->nxt = (BFS_Slot *) shared_memory->head[dst][who_are_you][who_am_i];",
+ " shared_memory->head[dst][who_are_you][who_am_i] = n;",
+ " #endif",
+ " #ifdef BFS_STAGGER",
+ "done:",
+ " #endif",
+ "#endif", /* BFS_QSZ */
+ "#ifdef VERBOSE",
+ " bfs_printf(\"PUT STATE (depth %%ld, nr %%u) to %%d -- s_data: %%p\\n\",",
+ " tt, n->s_data->nr, who_are_you, n->s_data);",
+ "#endif",
+ " bfs_sent++;",
+ "}",
+ "",
+ "BFS_Slot *",
+ "bfs_next(void)",
+ "{ volatile BFS_Slot *n = &bfs_null;",
+ " #ifdef BFS_FIFO",
+ " const int src = 0;",
+ " bfs_qscan = bfs_empty(who_am_i);",
+ " #else",
+ " const int src = bfs_toggle;",
+ " #ifdef BFS_QSZ",
+ " while (bfs_qscan < Cores",
+ " && shared_memory->bfs_ix[src][who_am_i][bfs_qscan] == 0)",
+ " { bfs_qscan++;",
+ " }",
+ " #else",
+ " while (bfs_qscan < Cores",
+ " && shared_memory->head[src][who_am_i][bfs_qscan] == (BFS_Slot *) 0)",
+ " { bfs_qscan++;",
+ " }",
+ " #endif",
+ " #endif",
+ " if (bfs_qscan < Cores)",
+ " {",
+ " #ifdef BFS_FIFO", /* no wait for toggles */
+ " shared_memory->bfs_idle[who_am_i] = 0;",
+ " for (n = shared_memory->head[src][who_am_i][bfs_qscan]; n; n = n->nxt)",
+ " { if (n->type != DELETED)",
+ " { break;",
+ " } }",
+ " #ifdef BFS_CHECK",
+ " assert(n && n->type == STATE); /* q cannot be empty */",
+ " #endif",
+ " if (n->nxt)",
+ " { shared_memory->head[src][who_am_i][bfs_qscan] = n->nxt;",
+ " }", /* else, do not remove it - yet - avoid empty queues */
+ " n->type = DELETED;",
+ " #else",
+ " #ifdef BFS_QSZ",
+ " uint x = --shared_memory->bfs_ix[src][who_am_i][bfs_qscan];",
+ " n = &(shared_memory->bfsq[src][who_am_i][bfs_qscan][x]);",
+ " #else",
+ " n = shared_memory->head[src][who_am_i][bfs_qscan];",
+ " shared_memory->head[src][who_am_i][bfs_qscan] = n->nxt;",
+ " #if defined(BFS_FIFO) && defined(BFS_CHECK)",
+ " assert(n->type == STATE);",
+ " #endif",
+ " n->nxt = (BFS_Slot *) 0;",
+ " #endif",
+ " #ifdef BFS_DISK",
+ " /* the states actually show up in reverse order (FIFO iso LIFO) here */",
+ " /* but that doesnt really matter as long as the count is right */",
+ " bfs_source_disk(bfs_inp_fd[bfs_qscan], n); /* get the data */",
+ " #endif",
+
+ " #endif",
+ " #ifdef BFS_CHECK",
+ " bfs_printf(\"rcv STATE from [%%d][%%d][%%d]\\n\",",
+ " src, who_am_i, bfs_qscan);",
+ " #endif",
+ " bfs_rcvd++;",
+ " } else",
+ " {",
+ " #if defined(BFS_STAGGER) && !defined(BFS_QSZ)",
+ " if (bfs_stage_cnt > 0)",
+ " { bfs_stagger_flush();",
+ " }",
+ " #endif",
+ " shared_memory->bfs_idle[who_am_i] = 1;",
+ " #if defined(BFS_FIFO) && defined(BFS_CHECK)",
+ " assert(n->type == EMPTY);",
+ " #endif",
+ " }",
+ " return (BFS_Slot *) n;",
+ "}",
+ "",
+ "int",
+ "bfs_all_empty(void)",
+ "{ int i;",
+ "#ifdef BFS_DISK",
+ " for (i = 0; i < Cores; i++)",
+ " { if (shared_memory->bfs_out_cnt[i] != 0)",
+ " {",
+ " #ifdef VERBOSE",
+ " bfs_printf(\"bfs_all_empty %%d not empty\\n\", i);",
+ " #endif",
+ " return 0;",
+ " } }",
+ "#else",
+ " int p;",
+ " #ifdef BFS_FIFO",
+ " const int dst = 0;",
+ " #else",
+ " int dst = 1 - bfs_toggle; /* next generation */",
+ " #endif",
+ " for (p = 0; p < Cores; p++)",
+ " for (i = 0; i < Cores; i++)",
+ " #ifdef BFS_QSZ",
+ " { if (shared_memory->bfs_ix[dst][p][i] > 0)",
+ " #else",
+ " { if (shared_memory->head[dst][p][i] != (BFS_Slot *) 0)",
+ " #endif",
+ " { return 0;",
+ " } }",
+ "#endif",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"bfs_all_empty\\n\");",
+ "#endif",
+ " return 1;",
+ "}",
+ "",
+ "#ifdef BFS_FIFO",
+ "BFS_Slot *",
+ "bfs_sweep(void)",
+ "{ BFS_Slot *n;",
+ " int i;",
+ " for (i = 0; i < Cores; i++)",
+ " for (n = (BFS_Slot *) shared_memory->dels[0][who_am_i][i];",
+ " n && n != shared_memory->head[0][who_am_i][i];",
+ " n = n->nxt)",
+ " { if (n->type == DELETED && n->nxt)",
+ " { shared_memory->dels[0][who_am_i][i] = n->nxt;",
+ " n->nxt = (BFS_Slot *) 0;",
+ " return n;",
+ " } }",
+ " return (BFS_Slot *) sh_malloc((ulong) sizeof(BFS_Slot));",
+ "}",
+ "#endif",
+ "",
+ "typedef struct BFS_T_Hold BFS_T_Hold;",
+ "struct BFS_T_Hold {",
+ " volatile BFS_Trail *t;",
+ " BFS_T_Hold *nxt;",
+ "};",
+ "BFS_T_Hold *bfs_t_held, *bfs_t_free;",
+ "",
+ "BFS_Trail *",
+ "bfs_grab_trail(void)", /* call in bfs_source_disk and bfs_new_slot */
+ "{ BFS_Trail *t;",
+ " BFS_T_Hold *h;",
+ "",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"grab trail - bfs_t_held %%p\\n\", (void *) bfs_t_held);",
+ "#endif",
+ " if (bfs_t_held)",
+ " { h = bfs_t_held;",
+ " bfs_t_held = bfs_t_held->nxt;",
+ " t = (BFS_Trail *) h->t;",
+ " h->t = (BFS_Trail *) 0; /* make sure it cannot be reused */",
+ " h->nxt = bfs_t_free;",
+ " bfs_t_free = h;",
+ "",
+ " } else",
+ " { t = (BFS_Trail *) sh_malloc((ulong) sizeof(BFS_Trail));",
+ " }",
+ "#ifdef BFS_CHECK",
+ " assert(t);",
+ "#endif",
+ " t->ostate = (H_el *) 0;",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"grab trail %%p\\n\", (void *) t);",
+ "#endif",
+ " return t;",
+ "}",
+ "",
+ "#if defined(BFS_DISK) || defined(BFS_NOTRAIL)",
+ "void",
+ "bfs_release_trail(BFS_Trail *t)", /* call in bfs_sink_disk (not bfs_recycle) */
+ "{ BFS_T_Hold *h;",
+ " #ifdef BFS_CHECK",
+ " assert(t);",
+ " #endif",
+ " #ifdef VERBOSE",
+ " bfs_printf(\"release trail %%p\\n\", (void *) t);",
+ " #endif",
+ " if (bfs_t_free)",
+ " { h = bfs_t_free;",
+ " bfs_t_free = bfs_t_free->nxt;",
+ " } else",
+ " { h = (BFS_T_Hold *) emalloc(sizeof(BFS_T_Hold));",
+ " }",
+ " h->t = t;",
+ " h->nxt = bfs_t_held;",
+ " bfs_t_held = h;",
+ " #ifdef VERBOSE",
+ " bfs_printf(\"release trail - bfs_t_held %%p\\n\", (void *) bfs_t_held);",
+ " #endif",
+ "}",
+ "#endif",
+ "",
+ "#ifndef BFS_QSZ",
+ "BFS_Slot *",
+ "bfs_new_slot(BFS_Trail *f)",
+ "{ BFS_Slot *t;",
+ "",
+ "#ifdef BFS_FIFO",
+ " t = bfs_sweep();",
+ "#else",
+ " if (bfs_free_slot) /* local */",
+ " { t = bfs_free_slot;",
+ " bfs_free_slot = bfs_free_slot->nxt;",
+ " t->nxt = (BFS_Slot *) 0;",
+ " } else",
+ " { t = (BFS_Slot *) sh_malloc((ulong) sizeof(BFS_Slot));",
+ " }",
+ "#endif",
+ " if (t->s_data)",
+ " { memset(t->s_data, 0, sizeof(BFS_State));",
+ " } else",
+ " { t->s_data = (BFS_State *) sh_malloc((ulong) sizeof(BFS_State));",
+ " }",
+ "",
+ " /* we keep a ptr to the frame of parent states, which is */",
+ " /* used for reconstructing path and recovering failed rvs etc */",
+ " /* we should not overwrite the data at this address with a memset */",
+ "",
+ " if (f)",
+ " { t->s_data->t_info = f;",
+ " } else",
+ " { t->s_data->t_info = bfs_grab_trail();",
+ " }",
+ " return t;",
+ "}",
+ "#else",
+ "BFS_Slot *",
+ "bfs_prep_slot(BFS_Trail *f, BFS_Slot *t)",
+ "{",
+ " if (t->s_data)",
+ " { memset(t->s_data, 0, sizeof(BFS_State));",
+ " } else",
+ " { t->s_data = (BFS_State *) sh_malloc((ulong) sizeof(BFS_State));",
+ " }",
+ " if (f)",
+ " { t->s_data->t_info = f;",
+ " } else",
+ " { t->s_data->t_info = bfs_grab_trail();",
+ " }",
+ " return t;",
+ "}",
+ "#endif",
+ "",
+ "SV_Hold *",
+ "bfs_new_sv(int n)",
+ "{ SV_Hold *h;",
+ "",
+ " if (bfs_svfree[n])",
+ " { h = bfs_svfree[n];",
+ " bfs_svfree[n] = h->nxt;",
+ " h->nxt = (SV_Hold *) 0;",
+ " } else",
+ " { h = (SV_Hold *) sh_malloc((ulong) sizeof(SV_Hold));",
+ "#if 0",
+ " h->sz = n;",
+ "#endif",
+ " h->sv = (State *) sh_malloc((ulong)(sizeof(State) - VECTORSZ + n));",
+ " }",
+ " memcpy((char *)h->sv, (char *)&now, n);",
+ " return h;",
+ "}",
+ "#if NRUNS>0",
+ "static EV_Hold *kept[VECTORSZ]; /* local */",
+ "",
+ "static void",
+ "bfs_keep(EV_Hold *v)",
+ "{ EV_Hold *h;",
+ "",
+ " for (h = kept[v->sz]; h; h = h->nxt) /* check local list */",
+ " { if (v->nrpr == h->nrpr",
+ " && v->nrqs == h->nrqs",
+ "#if !defined(NOCOMP) && !defined(HC)",
+ " && (v->sv == h->sv || memcmp((char *) v->sv, (char *) h->sv, v->sz) == 0)",
+ "#endif",
+ "#ifdef TRIX",
+ " )",
+ "#else",
+ " #if NRUNS>0",
+ " #if VECTORSZ>32000",
+ " && (memcmp((char *) v->po, (char *) h->po, v->nrpr * sizeof(int)) == 0)",
+ " && (memcmp((char *) v->qo, (char *) h->qo, v->nrqs * sizeof(int)) == 0)",
+ " #else",
+ " && (memcmp((char *) v->po, (char *) h->po, v->nrpr * sizeof(short)) == 0)",
+ " && (memcmp((char *) v->qo, (char *) h->qo, v->nrqs * sizeof(short)) == 0)",
+ " #endif",
+ " && (memcmp((char *) v->ps, (char *) h->ps, v->nrpr * sizeof(uchar)) == 0)",
+ " && (memcmp((char *) v->qs, (char *) h->qs, v->nrqs * sizeof(uchar)) == 0))",
+ " #else",
+ " )",
+ " #endif",
+ "#endif",
+ " { break;",
+ " } }",
+ "",
+ " if (!h) /* we don't have one like it yet */",
+ " { v->nxt = kept[v->sz]; /* keep the original owner field */",
+ " kept[v->sz] = v;",
+ " /* all ptrs inside are to shared memory, but nxt is local */",
+ " }",
+ "}",
+ "",
+ "EV_Hold *",
+ "bfs_new_sv_mask(int n)",
+ "{ EV_Hold *h;",
+ "",
+ " for (h = kept[n]; h; h = h->nxt)",
+ " { if ((now._nr_pr == h->nrpr)",
+ " && (now._nr_qs == h->nrqs)",
+ "#if !defined(NOCOMP) && !defined(HC) && NRUNS>0",
+ " && ((char *) Mask == h->sv || (memcmp((char *) Mask, h->sv, n) == 0))",
+ "#endif",
+ "#ifdef TRIX",
+ " )",
+ "#else",
+ " #if NRUNS>0",
+ " #if VECTORSZ>32000",
+ " && (memcmp((char *) proc_offset, (char *) h->po, now._nr_pr * sizeof(int)) == 0)",
+ " && (memcmp((char *) q_offset, (char *) h->qo, now._nr_qs * sizeof(int)) == 0)",
+ " #else",
+ " && (memcmp((char *) proc_offset, (char *) h->po, now._nr_pr * sizeof(short)) == 0)",
+ " && (memcmp((char *) q_offset, (char *) h->qo, now._nr_qs * sizeof(short)) == 0)",
+ " #endif",
+ " && (memcmp((char *) proc_skip, (char *) h->ps, now._nr_pr * sizeof(uchar)) == 0)",
+ " && (memcmp((char *) q_skip, (char *) h->qs, now._nr_qs * sizeof(uchar)) == 0))",
+ " #else",
+ " )",
+ " #endif",
+ "#endif",
+ " { break;",
+ " } }",
+ "",
+ " if (!h)",
+ " { /* once created, the contents are never modified */",
+ " h = (EV_Hold *) sh_malloc((ulong)sizeof(EV_Hold));",
+ " h->owner = who_am_i;",
+ " h->sz = n;",
+ " h->nrpr = now._nr_pr;",
+ " h->nrqs = now._nr_qs;",
+ "#if !defined(NOCOMP) && !defined(HC) && NRUNS>0",
+ " h->sv = (char *) Mask; /* in shared memory, and never modified */",
+ "#endif",
+ "#if NRUNS>0 && !defined(TRIX)",
+ " if (now._nr_pr > 0)",
+ " { h->ps = (char *) proc_skip;",
+ " h->po = (char *) proc_offset;",
+ " }",
+ " if (now._nr_qs > 0)",
+ " { h->qs = (char *) q_skip;",
+ " h->qo = (char *) q_offset;",
+ " }",
+ "#endif",
+ " h->nxt = kept[n];",
+ " kept[n] = h;",
+ " }",
+ " return h;",
+ "}",
+ "#endif", /* NRUNS>0 */
+ "BFS_Slot *",
+ "bfs_pack_state(Trail *f, BFS_Trail *g, int search_depth, BFS_Slot *t)",
+ "{",
+ "#ifdef BFS_CHECK",
+ " assert(t->s_data != NULL);",
+ " assert(t->s_data->t_info != NULL);",
+ " assert(f || g);",
+ "#endif",
+ " if (!g)",
+ " { t->s_data->t_info->ostate = f->ostate;",
+ " t->s_data->t_info->st = f->st;",
+ " t->s_data->t_info->o_tt = search_depth;",
+ " t->s_data->t_info->pr = f->pr;",
+ " t->s_data->t_info->tau = f->tau;",
+ " t->s_data->t_info->o_pm = f->o_pm;",
+ " if (f->o_t)",
+ " { t->s_data->t_info->t_id = f->o_t->t_id;",
+ " } else",
+ " { t->s_data->t_info->t_id = -1;",
+ " t->s_data->t_info->ostate = NULL;",
+ " }",
+ " } /* else t->s_data->t_info == g */",
+ "#if SYNC",
+ " t->s_data->boq = boq;",
+ "#endif",
+ "#ifdef VERBOSE",
+ " { static ulong u_cnt;",
+ " t->s_data->nr = u_cnt++;",
+ " }",
+ "#endif",
+ "#ifdef TRIX",
+ " sv_populate(); /* make sure now is up to date */",
+ "#endif",
+ "#ifndef BFS_DISK",
+ " { SV_Hold *x = bfs_new_sv(vsize);",
+ " t->s_data->osv = x->sv;",
+ " x->sv = (State *) 0;",
+ " x->nxt = bfs_free_hold;",
+ " bfs_free_hold = x;",
+ " }",
+ "#endif",
+ "#if NRUNS>0",
+ " t->s_data->omask = bfs_new_sv_mask(vsize);",
+ "#endif",
+ "",
+ "#if defined(Q_PROVISO) && !defined(BITSTATE) && !defined(NOREDUCE)",
+ " t->s_data->lstate = Lstate; /* Lstate is set in o_store or h_store */",
+ "#endif",
+ "#ifdef BFS_FIFO",
+ " t->type = STATE;",
+ "#endif",
+ " return t;",
+ "}",
+ "",
+ "void",
+ "bfs_store_state(Trail *t, short oboq)",
+ "{",
+ "#ifdef TRIX",
+ " sv_populate();",
+ "#endif",
+ "#if defined(VERI) && defined(Q_PROVISO) && !defined(BITSTATE) && defined(FULLSTACK)",
+ " if (!(t->tau&4)", /* prog move */
+ " && t->ostate)", /* not initial state */
+ " { t->tau |= ((BFS_Trail *) t->ostate)->tau&64;",
+ " } /* lift 64 across claim moves */",
+ "#endif",
+ "",
+ "#ifdef BFS_SEP_HASH",
+ " #if SYNC",
+ " if (boq == -1 && oboq != -1) /* post-rv */",
+ " { BFS_Trail *x = (BFS_Trail *) trpt->ostate; /* pre-rv state */",
+ " if (x)",
+ " { x->o_pm |= 4; /* rv complete */",
+ " } }",
+ " #endif",
+ " d_sfh((uchar *)&now, (int) vsize); /* sep-hash -- sets K1 -- overkill */",
+ " bfs_keep_state = K1%%Cores + 1;",
+ " bfs_push_state(t, NULL, trpt->o_tt+1); /* bfs_store_state - sep_hash */",
+ " bfs_keep_state = 0;",
+ "#else",
+ " #ifdef VERI",
+#if 0
+ in VERI mode store the state when
+ (!t->ostate || (t->tau&4)) in initial state and after each program move
+
+ i.e., dont store when !(!t->ostate || (t->tau&4)) = (t->ostate && !(t->tau&4))
+ the *first* time that the tau flag is not set:
+ possibly after a series of claim moves in an atomic sequence
+#endif
+ " if (!(t->tau&4) && t->ostate && (((BFS_Trail *)t->ostate)->tau&4))",
+ " { /* do not store intermediate state */",
+ " #if defined(VERBOSE) && defined(L_BOUND)",
+ " bfs_printf(\"Un-Stored state bnd %%d -- sds %%p\\n\",",
+ " now._l_bnd, now._l_sds);",
+ " #endif",
+ " bfs_push_state(t, NULL, trpt->o_tt+1); /* claim move */",
+ " } else",
+ " #endif",
+ " if (!bfs_do_store((char *)&now, vsize)) /* includes bfs_visited */",
+ " { nstates++; /* local count */",
+ " trpt->tau |= 64; /* bfs: succ outside stack */",
+ " #if SYNC",
+ " if (boq == -1 && oboq != -1) /* post-rv */",
+ " { BFS_Trail *x = ",
+ " (BFS_Trail *) trpt->ostate; /* pre-rv state */",
+ " if (x)",
+ " { x->o_pm |= 4; /* rv complete */",
+ " } }",
+ " #endif",
+ " bfs_push_state(t, NULL, trpt->o_tt+1); /* successor */",
+ " } else",
+ " { truncs++;",
+ " #ifdef BFS_CHECK",
+ " bfs_printf(\"seen before\\n\");",
+ " #endif",
+ " #if defined(Q_PROVISO) && !defined(BITSTATE) && defined(FULLSTACK)",
+ " #ifdef USE_TDH",
+ " if (Lstate)", /* if BFS_INQ is set */
+ " { trpt->tau |= 64;",
+ " }",
+ " #else",
+ " if (Lstate && Lstate->tagged) /* bfs_store_state */",
+ " { trpt->tau |= 64;",
+ " }",
+ " #endif",
+ " #endif",
+ " }",
+ "#endif",
+ "}",
+ "",
+ "/*** support routines ***/",
+ "",
+ "void",
+ "bfs_clear_locks(void)",
+ "{ int i;",
+ "",
+ " /* clear any locks held by this process only */",
+ " if (shared_memory)",
+ " for (i = 0; i < BFS_MAXLOCKS; i++)",
+ " { if (shared_memory->sh_owner[i] == who_am_i + 1)",
+ " { shared_memory->sh_locks[i] = 0;",
+ "#ifdef BFS_CHECK",
+ " shared_memory->in_count[i] = 0;",
+ "#endif",
+ " shared_memory->sh_owner[i] = 0;",
+ " } }",
+ "}",
+ "",
+ "void",
+ "e_critical(int which)",
+ "{ int w;",
+ "#ifdef BFS_CHECK",
+ " assert(which >= 0 && which < BFS_MAXLOCKS);",
+ "#endif",
+ " if (shared_memory == NULL) return;",
+ " while (tas(&(shared_memory->sh_locks[which])) != 0)",
+ " { w = shared_memory->sh_owner[which]; /* sh_locks[which] could be 0 by now */",
+ " assert(w >= 0 && w <= BFS_MAXPROCS);",
+ " if (w > 0 && shared_memory->bfs_flag[w-1] == 2)",
+ " { /* multiple processes can get here; only one should do this: */",
+ " if (tas(&(shared_memory->bfs_data[w - 1].override)) == 0)",
+ " { fprintf(stderr, \"cpu%%02d: override lock %%d - held by %%d\\n\",",
+ " who_am_i, which, shared_memory->sh_owner[which]);",
+ "#ifdef BFS_CHECK",
+ " shared_memory->in_count[which] = 0;",
+ "#endif",
+ " shared_memory->sh_locks[which] = 0;",
+ " shared_memory->sh_owner[which] = 0;",
+ " } }",
+ " shared_memory->wait_count[which]++; /* not atomic of course */",
+ " }",
+ "#ifdef BFS_CHECK",
+ " if (shared_memory->in_count[which] != 0)",
+ " { fprintf(stderr, \"cpu%%02d: cannot happen lock %%d count %%d\\n\", who_am_i,",
+ " which, shared_memory->in_count[which]);",
+ " }",
+ " shared_memory->in_count[which]++;",
+ "#endif",
+ " shared_memory->sh_owner[which] = who_am_i+1;",
+ "}",
+ "",
+ "void",
+ "x_critical(int which)",
+ "{",
+ " if (shared_memory == NULL) return;",
+ "#ifdef BFS_CHECK",
+ " assert(shared_memory->in_count[which] == 1);",
+ " shared_memory->in_count[which] = 0;",
+ "#endif",
+ " shared_memory->sh_locks[which] = 0;",
+ " shared_memory->sh_owner[which] = 0;",
+ "}",
+ "",
+ "void",
+ "bfs_printf(const char *fmt, ...)",
+ "{ va_list args;",
+ "",
+ " e_critical(BFS_PRINT);",
+ "#ifdef BFS_CHECK",
+ " if (1) { int i=who_am_i; while (i-- > 0) printf(\" \"); }",
+ "#endif",
+ " printf(\"cpu%%02d: \", who_am_i);",
+ " va_start(args, fmt);",
+ " vprintf(fmt, args);",
+ " va_end(args);",
+ " fflush(stdout);",
+ " x_critical(BFS_PRINT);",
+ "}",
+ "",
+ "int",
+ "bfs_all_idle(void)",
+ "{ int i;",
+ "",
+ " if (shared_memory)",
+ " for (i = 0; i < Cores; i++)",
+ " { if (shared_memory->bfs_flag[i] == 0",
+ " && shared_memory->bfs_idle[i] == 0)",
+ " { return 0;",
+ " } }",
+ " return 1;",
+ "}",
+ "",
+ "#ifdef BFS_FIFO",
+ "int",
+ "bfs_idle_and_empty(void)",
+ "{ int p; /* read-only */",
+ " for (p = 0; p < Cores; p++)",
+ " { if (shared_memory->bfs_flag[p] == 0",
+ " && shared_memory->bfs_idle[p] == 0)",
+ " { return 0;",
+ " } }",
+ " for (p = 0; p < Cores; p++)",
+ " { if (bfs_empty(p) < Cores)",
+ " { return 0;",
+ " } }",
+ " return 1;",
+ "}",
+ "#endif",
+ "",
+ "void",
+ "bfs_set_toggle(void) /* executed by root */",
+ "{ int i;",
+ "",
+ " if (shared_memory)",
+ " for (i = 0; i < Cores; i++)",
+ " { shared_memory->bfs_idle[i] = 0;",
+ " }",
+ "}",
+ "",
+ "int",
+ "bfs_all_running(void) /* crash detection */",
+ "{ int i;",
+ " for (i = 0; i < Cores; i++)",
+ " { if (!shared_memory || shared_memory->bfs_flag[i] > 1)",
+ " { return 0;",
+ " } }",
+ " return 1;",
+ "}",
+ "",
+ "void",
+ "bfs_mark_done(int code)",
+ "{",
+ " if (shared_memory)",
+ " { shared_memory->bfs_flag[who_am_i] = (int) code;",
+ " shared_memory->quit = 1;",
+ " }",
+ "}",
+ "",
+ "static uchar *",
+ "bfs_offset(int c)",
+ "{ int p, N;",
+ "#ifdef COLLAPSE",
+ " uchar *q = (uchar *) ncomps; /* it is the first object allocated */",
+ " q += (256+2) * sizeof(ulong); /* preserve contents of ncomps */",
+ "#else",
+ " uchar *q = (uchar *) &(shared_memory->allocator);",
+ "#endif",
+ " /* _NP_+1 proctypes, reachability info:",
+ " * reached[x : 0 .. _NP_+1][ 0 .. NrStates[x] ]",
+ " */",
+ " for (p = N = 0; p <= _NP_; p++)",
+ " { N += NrStates[p]; /* sum for all proctypes */",
+ " }",
+ "",
+ " /* space needed per proctype: N bytes */",
+ " /* rounded up to a multiple of the word size */",
+ " if ((N%%sizeof(void *)) != 0) /* aligned */",
+ " { N += sizeof(void *) - (N%%sizeof(void *));",
+ " }",
+ "",
+ " q += ((c - 1) * (_NP_ + 1) * N);",
+ " return q;",
+ "}",
+ "",
+ "static void",
+ "bfs_putreached(void)",
+ "{ uchar *q;",
+ " int p;",
+ "",
+ " assert(who_am_i > 0);",
+ "",
+ " q = bfs_offset(who_am_i);",
+ " for (p = 0; p <= _NP_; p++)",
+ " { memcpy((void *) q, (const void *) reached[p], (size_t) NrStates[p]);",
+ " q += NrStates[p];",
+ " }",
+ "}",
+ "",
+ "static void",
+ "bfs_getreached(int c)",
+ "{ uchar *q;",
+ " int p, i;",
+ "",
+ " assert(who_am_i == 0 && c >= 1 && c < Cores);",
+ "",
+ " q = (uchar *) bfs_offset(c);",
+ " for (p = 0; p <= _NP_; p++)",
+ " for (i = 0; i < NrStates[p]; i++)",
+ " { reached[p][i] += *q++; /* update local copy */",
+ " }",
+ "}",
+ "",
+ "void",
+ "bfs_update(void)",
+ "{ int i;",
+ " volatile BFS_data *s;",
+ "",
+ " if (!shared_memory) return;",
+ "",
+ " s = &shared_memory->bfs_data[who_am_i];",
+ " if (who_am_i == 0)",
+ " { shared_memory->bfs_flag[who_am_i] = 3; /* or else others dont stop */",
+ " bfs_gcount = 0;",
+ " for (i = 1; i < Cores; i++) /* start at 1 not 0 */",
+ " { while (shared_memory->bfs_flag[i] == 0)",
+ " { sleep(1);",
+ " if (bfs_gcount++ > WAIT_MAX) /* excessively long wait */",
+ " { printf(\"cpu00: give up waiting for cpu%%2d (%%d cores)\\n\", i, Cores);",
+ " bfs_gcount = 0;",
+ " break;",
+ " } }",
+ " s = &shared_memory->bfs_data[i];",
+ " mreached = Max(mreached, s->mreached);",
+ " hmax = vsize = Max(vsize, s->vsize);",
+ " errors += s->errors;",
+ " memcnt += s->memcnt;",
+ " nstates += s->nstates;",
+ " nlinks += s->nlinks;",
+ " truncs += s->truncs;",
+ " bfs_left += s->memory_left;",
+ " bfs_punt += s->punted;",
+ " bfs_getreached(i);",
+ " }",
+ " } else",
+ " { s->mreached = (ulong) mreached;",
+ " s->vsize = (ulong) vsize;",
+ " s->errors = (int) errors;",
+ " s->memcnt = (double) memcnt;",
+ " s->nstates = (double) nstates;",
+ " s->nlinks = (double) nlinks;",
+ " s->truncs = (double) truncs;",
+ " s->memory_left = (ulong) bfs_left;",
+ " s->punted = (ulong) bfs_punt;",
+ " bfs_putreached();",
+ " }",
+ "}",
+ "",
+ "volatile uchar *",
+ "sh_pre_malloc(ulong n) /* used before the local heaps are populated */",
+ "{ volatile uchar *ptr = NULL;",
+ "",
+ " assert(!bfs_runs);",
+ " if ((n%%sizeof(void *)) != 0)",
+ " { n += sizeof(void *) - (n%%sizeof(void *));",
+ " assert((n%%sizeof(void *)) == 0);",
+ " }",
+ "",
+ " e_critical(BFS_MEM); /* needed? */",
+ " if (shared_memory->mem_left < n + 7)", /* 7 for possible alignment */
+ " { x_critical(BFS_MEM);",
+ " bfs_printf(\"want %%lu, have %%lu\\n\",",
+ " n, shared_memory->mem_left);",
+ " bfs_shutdown(\"out of shared memory\");",
+ " assert(0); /* should be unreachable */",
+ " }",
+ " ptr = shared_memory->allocator;",
+ "#if WS>4", /* align to 8 byte boundary */
+ " { int b = (int) ((uint64_t) ptr)&7;",
+ " if (b != 0)",
+ " { ptr += (8-b);",
+ " shared_memory->allocator = ptr;",
+ " } }",
+ "#endif",
+ " shared_memory->allocator += n;",
+ " shared_memory->mem_left -= n;",
+ " x_critical(BFS_MEM);",
+ "",
+ " bfs_pre_allocated += n;",
+ "",
+ " return ptr;",
+ "}",
+ "",
+ "volatile uchar *",
+ "sh_malloc(ulong n)",
+ "{ volatile uchar *ptr = NULL;",
+ "#ifdef BFS_CHECK",
+ " assert(bfs_runs);",
+ "#endif",
+ " if ((n%%sizeof(void *)) != 0)",
+ " { n += sizeof(void *) - (n%%sizeof(void *));",
+ "#ifdef BFS_CHECK",
+ " assert((n%%sizeof(void *)) == 0);",
+ "#endif",
+ " }",
+ "",
+ " /* local heap -- no locks needed */",
+ " if (bfs_left < n)",
+ " { e_critical(BFS_MEM);",
+ " if (shared_memory->mem_left >= n)",
+ " { ptr = (uchar *) shared_memory->allocator;",
+ " shared_memory->allocator += n;",
+ " shared_memory->mem_left -= n;",
+ " x_critical(BFS_MEM);",
+ " return ptr;",
+ " }",
+ " x_critical(BFS_MEM);",
+ "#ifdef BFS_LOGMEM",
+ " int i;",
+ " e_critical(BFS_MEM);",
+ " for (i = 0; i < 1024; i++)",
+ " { if (shared_memory->logmem[i] > 0)",
+ " { bfs_printf(\"\tlog[%%d]\t%%d\\n\", i, shared_memory->logmem[i]);",
+ " } }",
+ " x_critical(BFS_MEM);",
+ "#endif",
+ " bfs_shutdown(\"out of shared memory\"); /* no return */",
+ " }",
+ "#ifdef BFS_LOGMEM",
+ " e_critical(BFS_MEM);",
+ " if (n < 1023)",
+ " { shared_memory->logmem[n]++;",
+ " } else",
+ " { shared_memory->logmem[1023]++;",
+ " }",
+ " x_critical(BFS_MEM);",
+ "#endif",
+ " ptr = (uchar *) bfs_heap;",
+ " bfs_heap += n;",
+ " bfs_left -= n;",
+ "",
+ " if (0) printf(\"sh_malloc %%ld\\n\", n);",
+ " return ptr;",
+ "}",
+ "",
+ "volatile uchar *",
+ "bfs_get_shared_mem(key_t key, size_t n)",
+ "{ char *rval;",
+ "",
+ " assert(who_am_i == 0);",
+ "",
+ " shared_mem_id = shmget(key, n, 0600 | IPC_CREAT | IPC_EXCL); /* create */",
+ " if (shared_mem_id == -1)",
+ " { fprintf(stderr, \"cpu%%02d: tried to get %%d MB of shared memory\\n\",",
+ " who_am_i, (int) n/(1024*1024));",
+ " perror(\"shmget\");",
+ " exit(1);",
+ " }",
+ " if ((rval = (char *) shmat(shared_mem_id, (void *) 0, 0)) == (char *) -1) /* attach */",
+ " { perror(\"shmat\");",
+ " exit(1);",
+ " }",
+ " return (uchar *) rval;",
+ "}",
+ "",
+ "void",
+ "bfs_drop_shared_memory(void)",
+ "{",
+ " if (who_am_i == 0)",
+ " { printf(\"pan: releasing shared memory...\");",
+ " fflush(stdout);",
+ " }",
+ " if (shared_memory)",
+ " { shmdt(shared_memory); /* detach */",
+ " if (who_am_i == 0)",
+ " { shmctl(shared_mem_id, IPC_RMID, (void *) 0); /* remove */",
+ " } }",
+ " if (who_am_i == 0)",
+ " { printf(\"done\\n\");",
+ " fflush(stdout);",
+ " }",
+ "}",
+ "",
+ "size_t",
+ "bfs_find_largest(key_t key)",
+ "{ size_t n;",
+ " const size_t delta = 32*1024*1024;",
+ " int temp_id = -1;",
+ " int atleastonce = 0;",
+ "",
+ " for (n = delta; ; n += delta)",
+ " { if (WS <= 4 && n >= 1024*1024*1024)", /* was n >= INT_MAX */
+ " { n = 1024*1024*1024;",
+ " break;",
+ " }",
+ "#ifdef MEMLIM",
+ " if ((double) n > memlim)",
+ " { n = (size_t) memlim;",
+ " break;",
+ " }",
+ "#endif",
+ " temp_id = shmget(key, n, 0600); /* check for stale copy */",
+ " if (temp_id != -1)",
+ " { if (shmctl(temp_id, IPC_RMID, ((void *) 0)) < 0) /* remove */",
+ " { perror(\"remove_segment_fails 2\");",
+ " exit(1);",
+ " } }",
+ "",
+ " temp_id = shmget(key, n, 0600 | IPC_CREAT | IPC_EXCL); /* create new */",
+ " if (temp_id == -1)",
+ " { n -= delta;",
+ " break;",
+ " } else",
+ " { atleastonce++;",
+ " if (shmctl(temp_id, IPC_RMID, ((void *) 0)) < 0)",
+ " { perror(\"remove_segment_fails 0\");",
+ " exit(1);",
+ " } } }",
+ "",
+ " if (!atleastonce)",
+ " { printf(\"cpu%%02d: no shared memory n=%%d\\n\", who_am_i, (int) n);",
+ " exit(1);",
+ " }",
+ "",
+ " printf(\"cpu%%02d: largest shared memory segment: %%lu MB\\n\",",
+ " who_am_i, (ulong) n/(1024*1024));",
+ "#if 0",
+ " #ifdef BFS_SEP_HASH",
+ " n /= 2; /* not n /= Cores because the queues take most memory */",
+ " printf(\"cpu%%02d: using %%lu MB\\n\", who_am_i, (ulong) n/(1024*1024));",
+ " #endif",
+ "#endif",
+ " fflush(stdout);",
+ "",
+ " if ((n/(1024*1024)) == 32)",
+ " { if (sizeof(void *) == 4) /* a 32 bit machine */",
+ " { fprintf(stderr, \"\\t32MB is the default; increase it to 1 GB with:\\n\");",
+ " fprintf(stderr, \"\\tsudo /sbin/sysctl kernel.shmmax=%%d\\n\", (1<<30));",
+ " fprintf(stderr, \"\\tsudo /sbin/sysctl kernel.shmall=%%d\\n\", (1<<30)/8192);",
+ " } else if (sizeof(void *) == 8) /* a 64 bit machine */",
+ " { fprintf(stderr, \"\\t32MB is the default; increase it to 30 GB with:\\n\");",
+ " fprintf(stderr, \"\\tsudo /sbin/sysctl kernel.shmmax=32212254720\\n\");",
+ " fprintf(stderr, \"\\tsudo /sbin/sysctl kernel.shmall=7864320\\n\");",
+ " fprintf(stderr, \"\\tor for 60 GB:\\n\");",
+ " fprintf(stderr, \"\\tsudo /sbin/sysctl kernel.shmmax=60000000000\\n\");",
+ " fprintf(stderr, \"\\tsudo /sbin/sysctl kernel.shmall=30000000\\n\");",
+ " } else",
+ " { fprintf(stderr, \"\\tweird wordsize %%d\\n\", (int) sizeof(void *));",
+ " } }",
+ "",
+ " return n;",
+ "}",
+ "#ifdef BFS_DISK",
+ "void",
+ "bfs_disk_start(void)", /* setup .spin*/
+ "{ int unused = system(\"rm -fr .spin\");",
+ " if (mkdir(\".spin\", 0777) != 0)",
+ " { perror(\"mkdir\");",
+ " Uerror(\"aborting\");",
+ " }",
+ "}",
+ "void",
+ "bfs_disk_stop(void)", /* remove .spin */
+ "{",
+ " if (system(\"rm -fr .spin\") < 0)",
+ " { perror(\"rm -fr .spin/\");",
+ " }",
+ "}",
+ "void",
+ "bfs_disk_inp(void)", /* this core only */
+ "{ int i; char fnm[16];",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"inp %%d %%d 0..%%d\\n\", bfs_toggle, who_am_i, Cores);",
+ "#endif",
+ " for (i = 0; i < Cores; i++)",
+ " { sprintf(fnm, \".spin/q%%d_%%d_%%d\", bfs_toggle, who_am_i, i);",
+ " if ((bfs_inp_fd[i] = open(fnm, 0444)) < 0)",
+ " { perror(\"open\");",
+ " Uerror(fnm);",
+ " } }",
+ "}",
+ "void",
+ "bfs_disk_out(void)", /* this core only */
+ "{ int i; char fnm[16];",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"out %%d 0..%%d %%d\\n\", 1-bfs_toggle, Cores, who_am_i);",
+ "#endif",
+ " shared_memory->bfs_out_cnt[who_am_i] = 0;",
+ " for (i = 0; i < Cores; i++)",
+ " { sprintf(fnm, \".spin/q%%d_%%d_%%d\", 1-bfs_toggle, i, who_am_i);",
+ " if ((bfs_out_fd[i] = creat(fnm, 0666)) < 0)",
+ " { perror(\"creat\");",
+ " Uerror(fnm);",
+ " } }",
+ "}",
+ "void",
+ "bfs_disk_iclose(void)",
+ "{ int i;",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"close_inp\\n\");",
+ "#endif",
+ " for (i = 0; i < Cores; i++)",
+ " { if (close(bfs_inp_fd[i]) < 0)",
+ " { perror(\"iclose\");",
+ " } }",
+ "}",
+ "void",
+ "bfs_disk_oclose(void)",
+ "{ int i;",
+ "#ifdef VERBOSE",
+ " bfs_printf(\"close_out\\n\");",
+ "#endif",
+ " for (i = 0; i < Cores; i++)",
+ " { if (fsync(bfs_out_fd[i]) < 0)",
+ " { perror(\"fsync\");",
+ " }",
+ " if (close(bfs_out_fd[i]) < 0)",
+ " { perror(\"oclose\");",
+ " } }",
+ "}",
+ "#endif",
+ "void",
+ "bfs_write_snap(int fd)",
+ "{ if (write(fd, snap, strlen(snap)) != strlen(snap))",
+ " { printf(\"pan: error writing %%s\\n\", fnm);",
+ " bfs_shutdown(\"file system error\");",
+ " }",
+ "}",
+ "",
+ "void",
+ "bfs_one_step(BFS_Trail *t, int fd)",
+ "{ if (t && t->t_id != (T_ID) -1)",
+ " { sprintf(snap, \"%%d:%%d:%%d\\n\",",
+ " trcnt++, t->pr, t->t_id);",
+ " bfs_write_snap(fd);",
+ " }",
+ "}",
+ "",
+ "void",
+ "bfs_putter(BFS_Trail *t, int fd)",
+ "{ if (t && t != (BFS_Trail *) t->ostate)",
+ " bfs_putter((BFS_Trail *) t->ostate, fd);",
+ "#ifdef L_BOUND",
+ " if (depthfound == trcnt)",
+ " { strcpy(snap, \"-1:-1:-1\\n\");",
+ " bfs_write_snap(fd);",
+ " depthfound = -1;",
+ " }",
+ "#endif",
+ " bfs_one_step(t, fd);",
+ "}",
+ "",
+ "void",
+ "bfs_nuerror(char *str)",
+ "{ int fd = make_trail();",
+ "",
+ " if (fd < 0) return;",
+ "#ifdef VERI",
+ " sprintf(snap, \"-2:%%d:-2\\n\", (uchar) ((P0 *)pptr(0))->_t);",
+ " bfs_write_snap(fd);",
+ "#endif",
+ "#ifdef MERGED",
+ " sprintf(snap, \"-4:-4:-4\\n\");",
+ " bfs_write_snap(fd);",
+ "#endif",
+ " trcnt = 1;",
+ " if (strstr(str, \"invalid\"))",
+ " { bfs_putter((BFS_Trail *) trpt->ostate, fd);",
+ " } else",
+ " { BFS_Trail x;",
+ " memset((char *) &x, 0, sizeof(BFS_Trail));",
+ " x.pr = trpt->pr;",
+ " x.t_id = (trpt->o_t)?trpt->o_t->t_id:0;",
+ " x.ostate = trpt->ostate;",
+ " bfs_putter(&x, fd);",
+ " }",
+ " close(fd);",
+ " if (errors >= upto && upto != 0)",
+ " { bfs_shutdown(str);",
+ " }",
+ "}",
+ "",
+ "void",
+ "bfs_uerror(char *str)",
+ "{ static char laststr[256];",
+ "",
+ " errors++;",
+ " if (strncmp(str, laststr, 254) != 0)",
+ " { bfs_printf(\"pan:%%d: %%s (at depth %%ld)\\n\",",
+ " errors, str, ((depthfound == -1)?depth:depthfound));",
+ " strncpy(laststr, str, 254);",
+ " }",
+ "#ifdef HAS_CODE",
+ " if (readtrail) { wrap_trail(); return; }",
+ "#endif",
+ " if (every_error != 0 || errors == upto)",
+ " { bfs_nuerror(str);",
+ " }",
+ " if (errors >= upto && upto != 0)",
+ " { bfs_shutdown(\"bfs_uerror\");",
+ " }",
+ " depthfound = -1;",
+ "}\n",
+ "void",
+ "bfs_Uerror(char *str)",
+ "{ /* bfs_uerror(str); */",
+ " bfs_printf(\"pan:%%d: %%s (at depth %%ld)\\n\", ++errors, str,",
+ " ((depthfound == -1)?depth:depthfound));",
+ " bfs_shutdown(\"bfs_Uerror\");",
+ "}",
+ 0,
+};
--- a/sys/src/cmd/spin/reprosrc.c
+++ b/sys/src/cmd/spin/reprosrc.c
@@ -1,22 +1,21 @@
/***** spin: reprosrc.c *****/
-/* Copyright (c) 2002-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include <stdio.h>
+#include <assert.h>
#include "spin.h"
#include "y.tab.h"
static int indent = 1;
+extern YYSTYPE yylval;
extern ProcList *rdy;
-void repro_seq(Sequence *);
+static void repro_seq(Sequence *);
void
doindent(void)
@@ -48,7 +47,7 @@
printf(" };\n");
}
-void
+static void
repro_seq(Sequence *s)
{ Element *e;
Symbol *v;
@@ -96,7 +95,7 @@
doindent();
if (e->n->ntyp == C_CODE)
{ printf("c_code ");
- plunk_inline(stdout, e->n->sym->name, 1);
+ plunk_inline(stdout, e->n->sym->name, 1, 1);
} else if (e->n->ntyp == 'c'
&& e->n->lft->ntyp == C_EXPR)
{ printf("c_expr { ");
@@ -133,4 +132,253 @@
repro_src(void)
{
repro_proc(rdy);
+}
+
+static int in_decl;
+static int in_c_decl;
+static int in_c_code;
+
+void
+blip(int n, char *b)
+{ char mtxt[1024];
+
+ strcpy(mtxt, "");
+
+ switch (n) {
+ default: if (n > 0 && n < 256)
+ sprintf(mtxt, "%c", n);
+ else
+ sprintf(mtxt, "<%d?>", n);
+
+ break;
+ case '(': strcpy(mtxt, "("); in_decl++; break;
+ case ')': strcpy(mtxt, ")"); in_decl--; break;
+ case '{': strcpy(mtxt, "{"); break;
+ case '}': strcpy(mtxt, "}"); break;
+ case '\t': sprintf(mtxt, "\\t"); break;
+ case '\f': sprintf(mtxt, "\\f"); break;
+ case '\n': sprintf(mtxt, "\\n"); break;
+ case '\r': sprintf(mtxt, "\\r"); break;
+ case 'c': sprintf(mtxt, "condition"); break;
+ case 's': sprintf(mtxt, "send"); break;
+ case 'r': sprintf(mtxt, "recv"); break;
+ case 'R': sprintf(mtxt, "recv poll"); break;
+ case '@': sprintf(mtxt, "@"); break;
+ case '?': sprintf(mtxt, "(x->y:z)"); break;
+ case NEXT: sprintf(mtxt, "X"); break;
+ case ALWAYS: sprintf(mtxt, "[]"); break;
+ case EVENTUALLY: sprintf(mtxt, "<>"); break;
+ case IMPLIES: sprintf(mtxt, "->"); break;
+ case EQUIV: sprintf(mtxt, "<->"); break;
+ case UNTIL: sprintf(mtxt, "U"); break;
+ case WEAK_UNTIL: sprintf(mtxt, "W"); break;
+ case IN: sprintf(mtxt, "in"); break;
+ case ACTIVE: sprintf(mtxt, "active"); break;
+ case AND: sprintf(mtxt, "&&"); break;
+ case ARROW: sprintf(mtxt, "->"); break;
+ case ASGN: sprintf(mtxt, "="); break;
+ case ASSERT: sprintf(mtxt, "assert"); break;
+ case ATOMIC: sprintf(mtxt, "atomic"); break;
+ case BREAK: sprintf(mtxt, "break"); break;
+ case C_CODE: sprintf(mtxt, "c_code"); in_c_code++; break;
+ case C_DECL: sprintf(mtxt, "c_decl"); in_c_decl++; break;
+ case C_EXPR: sprintf(mtxt, "c_expr"); break;
+ case C_STATE: sprintf(mtxt, "c_state"); break;
+ case C_TRACK: sprintf(mtxt, "c_track"); break;
+ case CLAIM: sprintf(mtxt, "never"); break;
+ case CONST: sprintf(mtxt, "%d", yylval->val); break;
+ case DECR: sprintf(mtxt, "--"); break;
+ case D_STEP: sprintf(mtxt, "d_step"); break;
+ case D_PROCTYPE: sprintf(mtxt, "d_proctype"); break;
+ case DO: sprintf(mtxt, "do"); break;
+ case DOT: sprintf(mtxt, "."); break;
+ case ELSE: sprintf(mtxt, "else"); break;
+ case EMPTY: sprintf(mtxt, "empty"); break;
+ case ENABLED: sprintf(mtxt, "enabled"); break;
+ case EQ: sprintf(mtxt, "=="); break;
+ case EVAL: sprintf(mtxt, "eval"); break;
+ case FI: sprintf(mtxt, "fi"); break;
+ case FULL: sprintf(mtxt, "full"); break;
+ case GE: sprintf(mtxt, ">="); break;
+ case GET_P: sprintf(mtxt, "get_priority"); break;
+ case GOTO: sprintf(mtxt, "goto"); break;
+ case GT: sprintf(mtxt, ">"); break;
+ case HIDDEN: sprintf(mtxt, "hidden"); break;
+ case IF: sprintf(mtxt, "if"); break;
+ case INCR: sprintf(mtxt, "++"); break;
+
+ case INLINE: sprintf(mtxt, "inline"); break;
+ case INIT: sprintf(mtxt, "init"); break;
+ case ISLOCAL: sprintf(mtxt, "local"); break;
+
+ case LABEL: sprintf(mtxt, "<label-name>"); break;
+
+ case LE: sprintf(mtxt, "<="); break;
+ case LEN: sprintf(mtxt, "len"); break;
+ case LSHIFT: sprintf(mtxt, "<<"); break;
+ case LT: sprintf(mtxt, "<"); break;
+ case LTL: sprintf(mtxt, "ltl"); break;
+
+ case NAME: sprintf(mtxt, "%s", yylval->sym->name); break;
+
+ case XU: switch (yylval->val) {
+ case XR: sprintf(mtxt, "xr"); break;
+ case XS: sprintf(mtxt, "xs"); break;
+ default: sprintf(mtxt, "<?>"); break;
+ }
+ break;
+
+ case TYPE: switch (yylval->val) {
+ case BIT: sprintf(mtxt, "bit"); break;
+ case BYTE: sprintf(mtxt, "byte"); break;
+ case CHAN: sprintf(mtxt, "chan"); in_decl++; break;
+ case INT: sprintf(mtxt, "int"); break;
+ case MTYPE: sprintf(mtxt, "mtype"); break;
+ case SHORT: sprintf(mtxt, "short"); break;
+ case UNSIGNED: sprintf(mtxt, "unsigned"); break;
+ default: sprintf(mtxt, "<unknown type>"); break;
+ }
+ break;
+
+ case NE: sprintf(mtxt, "!="); break;
+ case NEG: sprintf(mtxt, "!"); break;
+ case NEMPTY: sprintf(mtxt, "nempty"); break;
+ case NFULL: sprintf(mtxt, "nfull"); break;
+
+ case NON_ATOMIC: sprintf(mtxt, "<sub-sequence>"); break;
+
+ case NONPROGRESS: sprintf(mtxt, "np_"); break;
+ case OD: sprintf(mtxt, "od"); break;
+ case OF: sprintf(mtxt, "of"); break;
+ case OR: sprintf(mtxt, "||"); break;
+ case O_SND: sprintf(mtxt, "!!"); break;
+ case PC_VAL: sprintf(mtxt, "pc_value"); break;
+ case PRINT: sprintf(mtxt, "printf"); break;
+ case PRINTM: sprintf(mtxt, "printm"); break;
+ case PRIORITY: sprintf(mtxt, "priority"); break;
+ case PROCTYPE: sprintf(mtxt, "proctype"); break;
+ case PROVIDED: sprintf(mtxt, "provided"); break;
+ case RCV: sprintf(mtxt, "?"); break;
+ case R_RCV: sprintf(mtxt, "??"); break;
+ case RSHIFT: sprintf(mtxt, ">>"); break;
+ case RUN: sprintf(mtxt, "run"); break;
+ case SEP: sprintf(mtxt, "::"); break;
+ case SEMI: sprintf(mtxt, ";"); break;
+ case SET_P: sprintf(mtxt, "set_priority"); break;
+ case SHOW: sprintf(mtxt, "show"); break;
+ case SND: sprintf(mtxt, "!"); break;
+
+ case INAME:
+ case UNAME:
+ case PNAME:
+ case STRING: sprintf(mtxt, "%s", yylval->sym->name); break;
+
+ case TRACE: sprintf(mtxt, "trace"); break;
+ case TIMEOUT: sprintf(mtxt, "timeout"); break;
+ case TYPEDEF: sprintf(mtxt, "typedef"); break;
+ case UMIN: sprintf(mtxt, "-"); break;
+ case UNLESS: sprintf(mtxt, "unless"); break;
+ }
+ strcat(b, mtxt);
+}
+
+void
+purge(char *b)
+{
+ if (strlen(b) == 0) return;
+
+ if (b[strlen(b)-1] != ':') /* label? */
+ { if (b[0] == ':' && b[1] == ':')
+ { indent--;
+ doindent();
+ indent++;
+ } else
+ { doindent();
+ }
+ }
+ printf("%s\n", b);
+ strcpy(b, "");
+
+ in_decl = 0;
+ in_c_code = 0;
+ in_c_decl = 0;
+}
+
+int pp_mode;
+extern int lex(void);
+
+void
+pretty_print(void)
+{ int c, lastc = 0;
+ char buf[1024];
+
+ pp_mode = 1;
+ indent = 0;
+ strcpy(buf, "");
+ while ((c = lex()) != EOF)
+ {
+ if ((lastc == IF || lastc == DO) && c != SEP)
+ { indent--; /* c_code if */
+ }
+ if (c == C_DECL || c == C_STATE
+ || c == C_TRACK || c == SEP
+ || c == DO || c == IF
+ || (c == TYPE && !in_decl))
+ { purge(buf); /* start on new line */
+ }
+
+ if (c == '{'
+ && lastc != OF && lastc != IN
+ && lastc != ATOMIC && lastc != D_STEP
+ && lastc != C_CODE && lastc != C_DECL && lastc != C_EXPR)
+ { purge(buf);
+ }
+
+ if (c == PREPROC)
+ { int oi = indent;
+ purge(buf);
+ assert(strlen(yylval->sym->name) < sizeof(buf));
+ strcpy(buf, yylval->sym->name);
+ indent = 0;
+ purge(buf);
+ indent = oi;
+ continue;
+ }
+
+ if (c != ':' && c != SEMI
+ && c != ',' && c != '('
+ && c != '#' && lastc != '#'
+ && c != ARROW && lastc != ARROW
+ && c != '.' && lastc != '.'
+ && c != '!' && lastc != '!'
+ && c != SND && lastc != SND
+ && c != RCV && lastc != RCV
+ && c != O_SND && lastc != O_SND
+ && c != R_RCV && lastc != R_RCV
+ && (c != ']' || lastc != '[')
+ && (c != '>' || lastc != '<')
+ && (c != GT || lastc != LT)
+ && c != '@' && lastc != '@'
+ && c != DO && c != OD && c != IF && c != FI
+ && c != SEP && strlen(buf) > 0)
+ strcat(buf, " ");
+
+ if (c == '}' || c == OD || c == FI)
+ { purge(buf);
+ indent--;
+ }
+ blip(c, buf);
+
+ if (c == '{' || c == DO || c == IF)
+ { purge(buf);
+ indent++;
+ }
+
+ if (c == '}' || c == BREAK || c == SEMI
+ || (c == ':' && lastc == NAME))
+ { purge(buf);
+ }
+ lastc = c;
+ }
+ purge(buf);
}
--- a/sys/src/cmd/spin/run.c
+++ b/sys/src/cmd/spin/run.c
@@ -1,13 +1,10 @@
/***** spin: run.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include <stdlib.h>
#include "spin.h"
@@ -16,9 +13,10 @@
extern RunList *X, *run;
extern Symbol *Fname;
extern Element *LastStep;
-extern int Rvous, lineno, Tval, interactive, MadeChoice;
+extern int Rvous, lineno, Tval, interactive, MadeChoice, Priority_Sum;
extern int TstOnly, verbose, s_trail, xspin, jumpsteps, depth;
-extern int nproc, nstop, no_print, like_java;
+extern int analyze, nproc, nstop, no_print, like_java, old_priority_rules;
+extern short Have_claim;
static long Seed = 1;
static int E_Check = 0, Escape_Check = 0;
@@ -25,6 +23,8 @@
static int eval_sync(Element *);
static int pc_enabled(Lextok *n);
+static int get_priority(Lextok *n);
+static void set_priority(Lextok *n, Lextok *m);
extern void sr_buf(int, int);
void
@@ -42,15 +42,14 @@
Element *
rev_escape(SeqList *e)
-{ Element *r;
+{ Element *r = (Element *) 0;
- if (!e)
- return (Element *) 0;
+ if (e)
+ { if ((r = rev_escape(e->nxt)) == ZE) /* reversed order */
+ { r = eval_sub(e->this->frst);
+ } }
- if ((r = rev_escape(e->nxt)) != ZE) /* reversed order */
- return r;
-
- return eval_sub(e->this->frst);
+ return r;
}
Element *
@@ -57,9 +56,9 @@
eval_sub(Element *e)
{ Element *f, *g;
SeqList *z;
- int i, j, k;
+ int i, j, k, only_pos;
- if (!e->n)
+ if (!e || !e->n)
return ZE;
#ifdef DEBUG
printf("\n\teval_sub(%d %s: line %d) ",
@@ -69,8 +68,13 @@
#endif
if (e->n->ntyp == GOTO)
{ if (Rvous) return ZE;
- LastStep = e; f = get_lab(e->n, 1);
+ LastStep = e;
+ f = get_lab(e->n, 1);
+ f = huntele(f, e->status, -1); /* 5.2.3: was missing */
cross_dsteps(e->n, f->n);
+#ifdef DEBUG
+ printf("GOTO leads to %d\n", f->seqno);
+#endif
return f;
}
if (e->n->ntyp == UNLESS)
@@ -80,6 +84,7 @@
{ Element *has_else = ZE;
Element *bas_else = ZE;
int nr_else = 0, nr_choices = 0;
+ only_pos = -1;
if (interactive
&& !MadeChoice && !E_Check
@@ -89,8 +94,10 @@
{ printf("Select stmnt (");
whoruns(0); printf(")\n");
if (nproc-nstop > 1)
- printf("\tchoice 0: other process\n");
- }
+ { printf("\tchoice 0: other process\n");
+ nr_choices++;
+ only_pos = 0;
+ } }
for (z = e->sub, j=0; z; z = z->nxt)
{ j++;
if (interactive
@@ -113,14 +120,22 @@
if (!Enabled0(z->this->frst))
printf("unexecutable, ");
else
- nr_choices++;
+ { nr_choices++;
+ only_pos = j;
+ }
comment(stdout, z->this->frst->n, 0);
printf("\n");
} }
if (nr_choices == 0 && has_else)
- printf("\tchoice %d: (else)\n", nr_else);
+ { printf("\tchoice %d: (else)\n", nr_else);
+ only_pos = nr_else;
+ }
+ if (nr_choices <= 1 && only_pos != -1 && !MadeChoice)
+ { MadeChoice = only_pos;
+ }
+
if (interactive && depth >= jumpsteps
&& !Escape_Check
&& !(e->status&(D_ATOM))
@@ -132,8 +147,11 @@
else
printf("Select [0-%d]: ", j);
fflush(stdout);
- scanf("%s", buf);
- if (isdigit(buf[0]))
+ if (scanf("%64s", buf) <= 0)
+ { printf("no input\n");
+ return ZE;
+ }
+ if (isdigit((int)buf[0]))
k = atoi(buf);
else
{ if (buf[0] == 'q')
@@ -155,6 +173,7 @@
else
k = Rand()%j; /* nondeterminism */
}
+
has_else = ZE;
bas_else = ZE;
for (i = 0, z = e->sub; i < j+k; i++)
@@ -215,7 +234,7 @@
} else
{ SeqList *x;
if (!(e->status & (D_ATOM))
- && e->esc && verbose&32)
+ && e->esc && (verbose&32))
{ printf("Stmnt [");
comment(stdout, e->n, 0);
printf("] has escape(s): ");
@@ -234,11 +253,18 @@
if (!(e->status & D_ATOM)) /* escapes don't reach inside d_steps */
/* 4.2.4: only the guard of a d_step can have an escape */
#endif
+#if 1
+ if (!s_trail) /* trail determines selections, new 5.2.5 */
+#endif
{ Escape_Check++;
if (like_java)
{ if ((g = rev_escape(e->esc)) != ZE)
{ if (verbose&4)
- printf("\tEscape taken\n");
+ { printf("\tEscape taken (-J) ");
+ if (g->n && g->n->fn)
+ printf("%s:%d", g->n->fn->name, g->n->ln);
+ printf("\n");
+ }
Escape_Check--;
return g;
}
@@ -246,18 +272,24 @@
{ for (x = e->esc; x; x = x->nxt)
{ if ((g = eval_sub(x->this->frst)) != ZE)
{ if (verbose&4)
- printf("\tEscape taken\n");
+ { printf("\tEscape taken ");
+ if (g->n && g->n->fn)
+ printf("%s:%d", g->n->fn->name, g->n->ln);
+ printf("\n");
+ }
Escape_Check--;
return g;
} } }
Escape_Check--;
}
-
switch (e->n->ntyp) {
+ case ASGN:
+ if (check_track(e->n) == STRUCT) { break; }
+ /* else fall thru */
case TIMEOUT: case RUN:
case PRINT: case PRINTM:
case C_CODE: case C_EXPR:
- case ASGN: case ASSERT:
+ case ASSERT:
case 's': case 'r': case 'c':
/* toplevel statements only */
LastStep = e;
@@ -308,7 +340,8 @@
t = Sym_typ(now->rgt);
break;
}
- typ_ck(Sym_typ(now->lft), t, "assignment");
+ typ_ck(Sym_typ(now->lft), t, "assignment");
+
return setval(now->lft, eval(now->rgt));
}
@@ -371,6 +404,10 @@
case NEMPTY: return (qlen(now)>0);
case ENABLED: if (s_trail) return 1;
return pc_enabled(now->lft);
+
+ case GET_P: return get_priority(now->lft);
+ case SET_P: set_priority(now->lft->lft, now->lft->rgt); return 1;
+
case EVAL: return eval(now->lft);
case PC_VAL: return pc_value(now->lft);
case NONPROGRESS: return nonprogress();
@@ -384,15 +421,21 @@
case 'c': return eval(now->lft); /* condition */
case PRINT: return TstOnly?1:interprint(stdout, now);
case PRINTM: return TstOnly?1:printm(stdout, now);
- case ASGN: return assign(now);
+ case ASGN:
+ if (check_track(now) == STRUCT) { return 1; }
+ return assign(now);
- case C_CODE: printf("%s:\t", now->sym->name);
- plunk_inline(stdout, now->sym->name, 0);
+ case C_CODE: if (!analyze)
+ { printf("%s:\t", now->sym->name);
+ plunk_inline(stdout, now->sym->name, 0, 1);
+ }
return 1; /* uninterpreted */
- case C_EXPR: printf("%s:\t", now->sym->name);
- plunk_expr(stdout, now->sym->name);
- printf("\n");
+ case C_EXPR: if (!analyze)
+ { printf("%s:\t", now->sym->name);
+ plunk_expr(stdout, now->sym->name);
+ printf("\n");
+ }
return 1; /* uninterpreted */
case ASSERT: if (TstOnly || eval(now->lft)) return 1;
@@ -407,6 +450,11 @@
case '.': return 1; /* return label for compound */
case '@': return 0; /* stop state */
case ELSE: return 1; /* only hit here in guided trails */
+
+ case ',': /* reached through option -A with array initializer */
+ case 0:
+ return 0; /* not great, but safe */
+
default : printf("spin: bad node type %d (run)\n", now->ntyp);
if (s_trail) printf("spin: trail file doesn't match spec?\n");
fatal("aborting", 0);
@@ -426,7 +474,6 @@
j = n->lft->val;
else
j = eval(n->lft);
- Buf[0] = '\0';
sr_buf(j, 1);
dotag(fd, Buf);
}
@@ -437,9 +484,9 @@
interprint(FILE *fd, Lextok *n)
{ Lextok *tmp = n->lft;
char c, *s = n->sym->name;
- int i, j; char lbuf[512];
- extern char Buf[];
- char tBuf[4096];
+ int i, j; char lbuf[512]; /* matches value in sr_buf() */
+ extern char Buf[]; /* global, size 4096 */
+ char tBuf[4096]; /* match size of global Buf[] */
Buf[0] = '\0';
if (!no_print)
@@ -490,7 +537,7 @@
}
dotag(fd, Buf);
}
- if (strlen(Buf) > 4096) fatal("printf string too long", 0);
+ if (strlen(Buf) >= 4096) fatal("printf string too long", 0);
return 1;
}
@@ -512,6 +559,7 @@
verbose = v;
return i;
+ case SET_P:
case C_CODE: case C_EXPR:
case PRINT: case PRINTM:
case ASGN: case ASSERT:
@@ -552,6 +600,7 @@
case '@':
return X->pid == (nproc-nstop-1);
case '.':
+ case SET_P:
return 1;
case GOTO:
if (Rvous) return 0;
@@ -594,9 +643,91 @@
for (Y = run; Y; Y = Y->nxt)
if (--i == pid)
{ oX = X; X = Y;
- result = Enabled0(Y->pc);
+ result = Enabled0(X->pc);
X = oX;
break;
}
return result;
+}
+
+int
+pc_highest(Lextok *n)
+{ int i = nproc - nstop;
+ int pid = eval(n);
+ int target = 0, result = 1;
+ RunList *Y, *oX;
+
+ if (X->prov && !eval(X->prov)) return 0; /* can't be highest unless fully enabled */
+
+ for (Y = run; Y; Y = Y->nxt)
+ { if (--i == pid)
+ { target = Y->priority;
+ break;
+ } }
+if (0) printf("highest for pid %d @ priority = %d\n", pid, target);
+
+ oX = X;
+ i = nproc - nstop;
+ for (Y = run; Y; Y = Y->nxt)
+ { i--;
+if (0) printf(" pid %d @ priority %d\t", Y->pid, Y->priority);
+ if (Y->priority > target)
+ { X = Y;
+if (0) printf("enabled: %s\n", Enabled0(X->pc)?"yes":"nope");
+if (0) printf("provided: %s\n", eval(X->prov)?"yes":"nope");
+ if (Enabled0(X->pc) && (!X->prov || eval(X->prov)))
+ { result = 0;
+ break;
+ } }
+else
+if (0) printf("\n");
+ }
+ X = oX;
+
+ return result;
+}
+
+int
+get_priority(Lextok *n)
+{ int i = nproc - nstop;
+ int pid = eval(n);
+ RunList *Y;
+
+ if (old_priority_rules)
+ { return 1;
+ }
+
+ for (Y = run; Y; Y = Y->nxt)
+ { if (--i == pid)
+ { return Y->priority;
+ } }
+ return 0;
+}
+
+void
+set_priority(Lextok *n, Lextok *p)
+{ int i = nproc - nstop - Have_claim;
+ int pid = eval(n);
+ RunList *Y;
+
+ if (old_priority_rules)
+ { return;
+ }
+ for (Y = run; Y; Y = Y->nxt)
+ { if (--i == pid)
+ { Priority_Sum -= Y->priority;
+ Y->priority = eval(p);
+ Priority_Sum += Y->priority;
+ if (1)
+ { printf("%3d: setting priority of proc %d (%s) to %d\n",
+ depth, pid, Y->n->name, Y->priority);
+ } } }
+ if (verbose&32)
+ { printf("\tPid\tName\tPriority\n");
+ for (Y = run; Y; Y = Y->nxt)
+ { printf("\t%d\t%s\t%d\n",
+ Y->pid,
+ Y->n->name,
+ Y->priority);
+ } }
}
--- a/sys/src/cmd/spin/sched.c
+++ b/sys/src/cmd/spin/sched.c
@@ -1,13 +1,10 @@
/***** spin: sched.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include <stdlib.h>
#include "spin.h"
@@ -19,19 +16,21 @@
extern Symbol *Fname, *context;
extern int lineno, nr_errs, dumptab, xspin, jumpsteps, columns;
extern int u_sync, Elcnt, interactive, TstOnly, cutoff;
-extern short has_enabled;
-extern int limited_vis;
+extern short has_enabled, has_priority, has_code, replay;
+extern int limited_vis, product, nclaims, old_priority_rules;
+extern int old_scope_rules, scope_seq[128], scope_level, has_stdin;
+extern int pc_highest(Lextok *n);
+
RunList *X = (RunList *) 0;
RunList *run = (RunList *) 0;
RunList *LastX = (RunList *) 0; /* previous executing proc */
ProcList *rdy = (ProcList *) 0;
Element *LastStep = ZE;
-int nproc=0, nstop=0, Tval=0;
+int nproc=0, nstop=0, Tval=0, Priority_Sum = 0;
int Rvous=0, depth=0, nrRdy=0, MadeChoice;
short Have_claim=0, Skip_claim=0;
-static int Priority_Sum = 0;
static void setlocals(RunList *);
static void setparams(RunList *, ProcList *, Lextok *);
static void talk(RunList *);
@@ -42,13 +41,20 @@
r->n = p->n;
r->tn = p->tn;
+ r->b = p->b;
r->pid = nproc++ - nstop + Skip_claim;
+ r->priority = weight;
+ p->priority = (unsigned char) weight; /* not quite the best place of course */
- if ((verbose&4) || (verbose&32))
- printf("Starting %s with pid %d\n", p->n->name, r->pid);
-
+ if (!noparams && ((verbose&4) || (verbose&32)))
+ { printf("Starting %s with pid %d",
+ p->n?p->n->name:"--", r->pid);
+ if (has_priority) printf(" priority %d", r->priority);
+ printf("\n");
+ }
if (!p->s)
- fatal("parsing error, no sequence %s", p->n?p->n->name:"--");
+ fatal("parsing error, no sequence %s",
+ p->n?p->n->name:"--");
r->pc = huntele(p->s->frst, p->s->frst->status, -1);
r->ps = p->s;
@@ -58,14 +64,18 @@
r->nxt = run;
r->prov = p->prov;
- r->priority = weight;
+ if (weight < 1 || weight > 255)
+ { fatal("bad process priority, valid range: 1..255", (char *) 0);
+ }
+
if (noparams) setlocals(r);
Priority_Sum += weight;
+
run = r;
}
ProcList *
-ready(Symbol *n, Lextok *p, Sequence *s, int det, Lextok *prov)
+ready(Symbol *n, Lextok *p, Sequence *s, int det, Lextok *prov, enum btypes b)
/* n=name, p=formals, s=body det=deterministic prov=provided */
{ ProcList *r = (ProcList *) emalloc(sizeof(ProcList));
Lextok *fp, *fpt; int j; extern int Npars;
@@ -73,9 +83,15 @@
r->n = n;
r->p = p;
r->s = s;
+ r->b = b;
r->prov = prov;
- r->tn = nrRdy++;
- r->det = (short) det;
+ r->tn = (short) nrRdy++;
+ n->sc = scope_seq[scope_level]; /* scope_level should be 0 */
+
+ if (det != 0 && det != 1)
+ { fprintf(stderr, "spin: bad value for det (cannot happen)\n");
+ }
+ r->det = (unsigned char) det;
r->nxt = rdy;
rdy = r;
@@ -128,13 +144,15 @@
run->pid - Have_claim, run->n->name);
pstext(run->pid - Have_claim, Buf);
} else
- printf("proc %d = %s\n",
- run->pid - Have_claim, run->n->name);
+ { printf("proc %d = %s\n",
+ run->pid - Have_claim, run->n->name);
+ }
return;
}
if (dumptab
|| analyze
+ || product
|| s_trail
|| !(verbose&4))
return;
@@ -161,9 +179,11 @@
Symbol *s = m->sym; /* proctype name */
Lextok *n = m->lft; /* actual parameters */
- if (m->val < 1) m->val = 1; /* minimum priority */
+ if (m->val < 1)
+ { m->val = 1; /* minimum priority */
+ }
for (p = rdy; p; p = p->nxt)
- if (strcmp(s->name, p->n->name) == 0)
+ { if (strcmp(s->name, p->n->name) == 0)
{ if (nproc-nstop >= MAXP)
{ printf("spin: too many processes (%d max)\n", MAXP);
break;
@@ -173,7 +193,7 @@
setparams(run, p, n);
setlocals(run); /* after setparams */
return run->pid - Have_claim + Skip_claim; /* effective simu pid */
- }
+ } }
return 0; /* process not found */
}
@@ -208,26 +228,29 @@
RunList *r, *q = (RunList *) 0;
for (p = rdy; p; p = p->nxt)
- if (p->tn == n
- && strcmp(p->n->name, ":never:") == 0)
+ if (p->tn == n && p->b == N_CLAIM)
{ runnable(p, 1, 1);
goto found;
}
- printf("spin: couldn't find claim (ignored)\n");
+ printf("spin: couldn't find claim %d (ignored)\n", n);
+ if (verbose&32)
+ for (p = rdy; p; p = p->nxt)
+ printf("\t%d = %s\n", p->tn, p->n->name);
+
Skip_claim = 1;
goto done;
found:
/* move claim to far end of runlist, and reassign it pid 0 */
if (columns == 2)
- { depth = 0;
- pstext(0, "0::never:");
+ { extern char Buf[];
+ depth = 0;
+ sprintf(Buf, "%d:%s", 0, p->n->name);
+ pstext(0, Buf);
for (r = run; r; r = r->nxt)
- { if (!strcmp(r->n->name, ":never:"))
- continue;
- sprintf(Buf, "%d:%s",
- r->pid+1, r->n->name);
- pstext(r->pid+1, Buf);
- } }
+ { if (r->b != N_CLAIM)
+ { sprintf(Buf, "%d:%s", r->pid+1, r->n->name);
+ pstext(r->pid+1, Buf);
+ } } }
if (run->pid == 0) return; /* it is the first process started */
@@ -288,7 +311,7 @@
nproc - Have_claim + Skip_claim,
(xspin || nproc!=1)?"es":"");
short_cut:
- if (xspin) alldone(0); /* avoid an abort from xspin */
+ if (s_trail || xspin) alldone(0); /* avoid an abort from xspin */
if (fini) alldone(1);
}
@@ -332,6 +355,24 @@
return e;
}
+static int
+x_can_run(void) /* the currently selected process in X can run */
+{
+ if (X->prov && !eval(X->prov))
+ {
+if (0) printf("pid %d cannot run: not provided\n", X->pid);
+ return 0;
+ }
+ if (has_priority && !old_priority_rules)
+ { Lextok *n = nn(ZN, CONST, ZN, ZN);
+ n->val = X->pid;
+if (0) printf("pid %d %s run (priority)\n", X->pid, pc_highest(n)?"can":"cannot");
+ return pc_highest(n);
+ }
+if (0) printf("pid %d can run\n", X->pid);
+ return 1;
+}
+
static RunList *
pickproc(RunList *Y)
{ SeqList *z; Element *has_else;
@@ -343,7 +384,25 @@
return NULL;
}
if (!interactive || depth < jumpsteps)
- { /* was: j = (int) Rand()%(nproc-nstop); */
+ { if (has_priority && !old_priority_rules) /* new 6.3.2 */
+ { j = Rand()%(nproc-nstop);
+ for (X = run; X; X = X->nxt)
+ { if (j-- <= 0)
+ break;
+ }
+ if (X == NULL)
+ { fatal("unexpected, pickproc", (char *)0);
+ }
+ j = nproc - nstop;
+ while (j-- > 0)
+ { if (x_can_run())
+ { Y = X;
+ break;
+ }
+ X = (X->nxt)?X->nxt:run;
+ }
+ return Y;
+ }
if (Priority_Sum < nproc-nstop)
fatal("cannot happen - weights", (char *)0);
j = (int) Rand()%Priority_Sum;
@@ -354,6 +413,7 @@
X = X->nxt;
if (!X) { Y = NULL; X = run; }
}
+
} else
{ int only_choice = -1;
int no_choice = 0, proc_no_ch, proc_k;
@@ -365,8 +425,7 @@
Choices[X->pid] = (short) k;
- if (!X->pc
- || (X->prov && !eval(X->prov)))
+ if (!X->pc || !x_can_run())
{ if (X == run)
Choices[X->pid] = 0;
continue;
@@ -457,9 +516,12 @@
} else
{ char buf[256];
fflush(stdout);
- scanf("%s", buf);
+ if (scanf("%64s", buf) == 0)
+ { printf("\tno input\n");
+ goto try_again;
+ }
j = -1;
- if (isdigit(buf[0]))
+ if (isdigit((int) buf[0]))
j = atoi(buf);
else
{ if (buf[0] == 'q')
@@ -484,6 +546,26 @@
}
void
+multi_claims(void)
+{ ProcList *p, *q = NULL;
+
+ if (nclaims > 1)
+ { printf(" the model contains %d never claims:", nclaims);
+ for (p = rdy; p; p = p->nxt)
+ { if (p->b == N_CLAIM)
+ { printf("%s%s", q?", ":" ", p->n->name);
+ q = p;
+ } }
+ printf("\n");
+ printf(" only one claim is used in a verification run\n");
+ printf(" choose which one with ./pan -a -N name (defaults to -N %s)\n",
+ q?q->n->name:"--");
+ printf(" or use e.g.: spin -search -ltl %s %s\n",
+ q?q->n->name:"--", Fname?Fname->name:"filename");
+ }
+}
+
+void
sched(void)
{ Element *e;
RunList *Y = NULL; /* previous process in run queue */
@@ -498,6 +580,10 @@
dumplabels();
return;
}
+ if (has_code && !analyze)
+ { printf("spin: warning: c_code fragments remain uninterpreted\n");
+ printf(" in random simulations with spin; use ./pan -r instead\n");
+ }
if (has_enabled && u_sync > 0)
{ printf("spin: error, cannot use 'enabled()' in ");
@@ -504,13 +590,23 @@
printf("models with synchronous channels.\n");
nr_errs++;
}
- if (analyze)
+ if (product)
+ { sync_product();
+ alldone(0);
+ }
+ if (analyze && (!replay || has_code))
{ gensrc();
+ multi_claims();
return;
- } else if (s_trail)
+ }
+ if (replay && !has_code)
+ { return;
+ }
+ if (s_trail)
{ match_trail();
return;
}
+
if (claimproc)
printf("warning: never claim not used in random simulation\n");
if (eventmap)
@@ -543,9 +639,9 @@
depth++; LastStep = ZE;
oX = X; /* a rendezvous could change it */
go = 1;
- if (X && X->prov && X->pc
+ if (X->pc
&& !(X->pc->status & D_ATOM)
- && !eval(X->prov))
+ && !x_can_run())
{ if (!xspin && ((verbose&32) || (verbose&4)))
{ p_talk(X->pc, 1);
printf("\t<<Not Enabled>>\n");
@@ -557,9 +653,10 @@
&& ((verbose&32) || (verbose&4)))
{ if (X == oX)
if (!(e->status & D_ATOM) || (verbose&32)) /* no talking in d_steps */
- { p_talk(X->pc, 1);
+ { if (!LastStep) LastStep = X->pc;
+ /* A. Tanaka, changed order */
+ p_talk(LastStep, 1);
printf(" [");
- if (!LastStep) LastStep = X->pc;
comment(stdout, LastStep->n, 0);
printf("]\n");
}
@@ -570,7 +667,8 @@
if (xspin)
printf("\n");
}
- if (oX != X)
+ if (oX != X
+ || (X->pc->status & (ATOM|D_ATOM))) /* new 5.0 */
{ e = silent_moves(e);
notbeyond = 0;
}
@@ -587,10 +685,12 @@
}
} else
{ depth--;
- if (oX->pc->status & D_ATOM)
- non_fatal("stmnt in d_step blocks", (char *)0);
-
- if (X->pc->n->ntyp == '@'
+ if (oX->pc && (oX->pc->status & D_ATOM))
+ { non_fatal("stmnt in d_step blocks", (char *)0);
+ }
+ if (X->pc
+ && X->pc->n
+ && X->pc->n->ntyp == '@'
&& X->pid == (nproc-nstop-1))
{ if (X != run && Y != NULL)
Y->nxt = X->nxt;
@@ -610,14 +710,19 @@
X = (X->nxt) ? X->nxt : run;
} else
{ if (p_blocked(X->pid))
- { if (Tval) break;
- Tval = 1;
- if (depth >= jumpsteps)
+ { if (Tval && !has_stdin)
+ { break;
+ }
+ if (!Tval && depth >= jumpsteps)
{ oX = X;
X = (RunList *) 0; /* to suppress indent */
dotag(stdout, "timeout\n");
X = oX;
+ Tval = 1;
} } } }
+
+ if (!run || !X) break; /* new 5.0 */
+
Y = pickproc(X);
notbeyond = 0;
}
@@ -662,7 +767,7 @@
printf(" [");
comment(stdout, s_was->n, 0);
printf("]\n");
- tmp = orun; orun = X; X = tmp;
+ tmp = orun; /* orun = X; */ X = tmp;
if (!LastStep) LastStep = X->pc;
p_talk(LastStep, 1);
printf(" [");
@@ -692,7 +797,9 @@
int i;
for (t = r->symtab; t; t = t->next)
- if (strcmp(t->name, s->name) == 0)
+ if (strcmp(t->name, s->name) == 0
+ && (old_scope_rules
+ || strcmp((const char *)t->bscp, (const char *)s->bscp) == 0))
return; /* it's already there */
t = (Symbol *) emalloc(sizeof(Symbol));
@@ -699,11 +806,16 @@
t->name = s->name;
t->type = s->type;
t->hidden = s->hidden;
+ t->isarray = s->isarray;
t->nbits = s->nbits;
t->nel = s->nel;
t->ini = s->ini;
t->setat = depth;
t->context = r->n;
+
+ t->bscp = (unsigned char *) emalloc(strlen((const char *)s->bscp)+1);
+ strcpy((char *)t->bscp, (const char *)s->bscp);
+
if (s->type != STRUCT)
{ if (s->val) /* if already initialized, copy info */
{ t->val = (int *) emalloc(s->nel*sizeof(int));
@@ -710,7 +822,8 @@
for (i = 0; i < s->nel; i++)
t->val[i] = s->val[i];
} else
- (void) checkvar(t, 0); /* initialize it */
+ { (void) checkvar(t, 0); /* initialize it */
+ }
} else
{ if (s->Sval)
fatal("saw preinitialized struct %s", s->name);
@@ -759,7 +872,7 @@
if (!a)
fatal("missing actual parameters: '%s'", p->n->name);
- if (t->sym->nel != 1)
+ if (t->sym->nel > 1 || t->sym->isarray)
fatal("array in parameter list, %s", t->sym->name);
k = eval(a->lft);
@@ -768,7 +881,7 @@
ft = Sym_typ(t);
if (at != ft && (at == CHAN || ft == CHAN))
- { char buf[128], tag1[64], tag2[64];
+ { char buf[256], tag1[64], tag2[64];
(void) sputtype(tag1, ft);
(void) sputtype(tag2, at);
sprintf(buf, "type-clash in params of %s(..), (%s<-> %s)",
@@ -809,8 +922,11 @@
return ZS;
}
for (r = X->symtab; r; r = r->next)
- if (strcmp(r->name, s->name) == 0)
- break;
+ { if (strcmp(r->name, s->name) == 0
+ && (old_scope_rules
+ || strcmp((const char *)r->bscp, (const char *)s->bscp) == 0))
+ { break;
+ } }
if (!r)
{ addsymbol(X, s);
r = X->symtab;
@@ -878,7 +994,11 @@
printf(" -");
else
printf("%2d", X->pid - Have_claim);
- printf(" (%s) ", X->n->name);
+ if (old_priority_rules)
+ { printf(" (%s) ", X->n->name);
+ } else
+ { printf(" (%s:%d) ", X->n->name, X->priority);
+ }
}
static void
@@ -895,6 +1015,7 @@
void
p_talk(Element *e, int lnr)
{ static int lastnever = -1;
+ static char nbuf[128];
int newnever = -1;
if (e && e->n)
@@ -918,9 +1039,22 @@
whoruns(lnr);
if (e)
- { printf("line %3d %s (state %d)",
+ { if (e->n)
+ { char *ptr = e->n->fn->name;
+ char *qtr = nbuf;
+ while (*ptr != '\0')
+ { if (*ptr != '"')
+ { *qtr++ = *ptr;
+ }
+ ptr++;
+ }
+ *qtr = '\0';
+ } else
+ { strcpy(nbuf, "-");
+ }
+ printf("%s:%d (state %d)",
+ nbuf,
e->n?e->n->ln:-1,
- e->n?e->n->fn->name:"-",
e->seqno);
if (!xspin
&& ((e->status&ENDSTATE) || has_lab(e, 2))) /* 2=end */
@@ -943,8 +1077,9 @@
{ fatal("remote ref to label '%s' inside d_step",
n->sym->name);
}
- if ((i = find_lab(n->sym, n->lft->sym, 1)) == 0)
- fatal("unknown labelname: %s", n->sym->name);
+ if ((i = find_lab(n->sym, n->lft->sym, 1)) == 0) /* remotelab */
+ { fatal("unknown labelname: %s", n->sym->name);
+ }
return i;
}
@@ -970,7 +1105,8 @@
} }
if (prno < 0)
- return 0; /* non-existing process */
+ { return 0; /* non-existing process */
+ }
#if 0
i = nproc - nstop;
for (Y = run; Y; Y = Y->nxt)
@@ -978,7 +1114,7 @@
printf(" %s: i=%d, prno=%d, ->pid=%d\n", Y->n->name, i, prno, Y->pid);
}
#endif
- i = nproc - nstop;
+ i = nproc - nstop + Skip_claim; /* 6.0: added Skip_claim */
for (Y = run; Y; Y = Y->nxt)
if (--i == prno)
{ if (strcmp(Y->n->name, n->lft->sym->name) != 0)
@@ -988,12 +1124,13 @@
}
if (strcmp(n->sym->name, "_p") == 0)
{ if (Y->pc)
- return Y->pc->seqno;
+ { return Y->pc->seqno;
+ }
/* harmless, can only happen with -t */
return 0;
}
-#if 1
- /* new 4.0 allow remote variables */
+
+ /* check remote variables */
oX = X;
X = Y;
@@ -1001,8 +1138,14 @@
n->lft = n->rgt;
os = n->sym;
- n->sym = findloc(n->sym);
-
+ if (!n->sym->context)
+ { n->sym->context = Y->n;
+ }
+ { int rs = old_scope_rules;
+ old_scope_rules = 1; /* 6.4.0 */
+ n->sym = findloc(n->sym);
+ old_scope_rules = rs;
+ }
i = getval(n);
n->sym = os;
@@ -1009,9 +1152,6 @@
n->lft = onl;
X = oX;
return i;
-#else
- break;
-#endif
}
printf("remote ref: %s[%d] ", n->lft->sym->name, prno-added);
non_fatal("%s not found", n->sym->name);
--- a/sys/src/cmd/spin/spin.h
+++ b/sys/src/cmd/spin/spin.h
@@ -1,13 +1,10 @@
/***** spin: spin.h *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#ifndef SEEN_SPIN_H
#define SEEN_SPIN_H
@@ -15,7 +12,16 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
+#if !defined(WIN32) && !defined(WIN64)
+ #include <unistd.h>
+#endif
+#if !defined(PC) && !defined(_PLAN9)
+ #include <memory.h>
+#endif
+enum { INIV, PUTV, LOGV }; /* used in pangen1.c */
+enum btypes { NONE, N_CLAIM, I_PROC, A_PROC, P_PROC, E_TRACE, N_TRACE };
+
typedef struct Lextok {
unsigned short ntyp; /* node type */
short ismtyp; /* CONST derived from MTYP */
@@ -22,6 +28,7 @@
int val; /* value attribute */
int ln; /* line number */
int indstep; /* part of d_step sequence */
+ int uiid; /* inline id, if non-zero */
struct Symbol *fn; /* file name */
struct Symbol *sym; /* symbol reference */
struct Sequence *sq; /* sequence */
@@ -54,6 +61,9 @@
64=treat as if local; 128=read at least once
*/
unsigned char colnr; /* for use with xspin during simulation */
+ unsigned char isarray; /* set if decl specifies array bound */
+ unsigned char *bscp; /* block scope */
+ int sc; /* scope seq no -- set only for proctypes */
int nbits; /* optional width specifier */
int nel; /* 1 if scalar, >1 if array */
int setat; /* last depth value changed */
@@ -124,7 +134,7 @@
int merge_single;
short merge_in; /* nr of incoming edges */
short merge_mark; /* state was generated in merge sequence */
- unsigned char status; /* used by analyzer generator */
+ unsigned int status; /* used by analyzer generator */
struct FSM_use *dead; /* optional dead variable list */
struct SeqList *sub; /* subsequences, for compounds */
struct SeqList *esc; /* zero or more escape sequences */
@@ -136,6 +146,7 @@
Element *frst;
Element *last; /* links onto continuations */
Element *extent; /* last element in original */
+ int minel; /* minimum Seqno, set and used only in guided.c */
int maxel; /* 1+largest id in sequence */
} Sequence;
@@ -148,6 +159,7 @@
Symbol *s;
Symbol *c;
Element *e;
+ int uiid; /* non-zero if label appears in an inline */
int visible; /* label referenced in claim (slice relevant) */
struct Label *nxt;
} Label;
@@ -157,11 +169,17 @@
struct Lbreak *nxt;
} Lbreak;
+typedef struct L_List {
+ Lextok *n;
+ struct L_List *nxt;
+} L_List;
+
typedef struct RunList {
Symbol *n; /* name */
int tn; /* ordinal of type */
int pid; /* process id */
int priority; /* for simulations only */
+ enum btypes b; /* the type of process */
Element *pc; /* current stmnt */
Sequence *ps; /* used by analyzer generator */
Lextok *prov; /* provided clause */
@@ -174,11 +192,19 @@
Lextok *p; /* parameters */
Sequence *s; /* body */
Lextok *prov; /* provided clause */
+ enum btypes b; /* e.g., claim, trace, proc */
short tn; /* ordinal number */
- short det; /* deterministic */
+ unsigned char det; /* deterministic */
+ unsigned char unsafe; /* contains global var inits */
+ unsigned char priority; /* process priority, if any */
struct ProcList *nxt; /* linked list */
} ProcList;
+typedef struct QH {
+ int n;
+ struct QH *nxt;
+} QH;
+
typedef Lextok *Lexptr;
#define YYSTYPE Lexptr
@@ -194,7 +220,8 @@
#define DONE2 16 /* used in putcode and main*/
#define D_ATOM 32 /* deterministic atomic */
#define ENDSTATE 64 /* normal endstate */
-#define CHECK2 128
+#define CHECK2 128 /* status bits for remote ref check */
+#define CHECK3 256 /* status bits for atomic jump check */
#define Nhash 255 /* slots in symbol hash-table */
@@ -216,18 +243,24 @@
#define SOMETHINGBIG 65536
#define RATHERSMALL 512
+#define MAXSCOPESZ 1024
#ifndef max
-#define max(a,b) (((a)<(b)) ? (b) : (a))
+ #define max(a,b) (((a)<(b)) ? (b) : (a))
#endif
-enum { INIV, PUTV, LOGV }; /* for pangen[14].c */
+#ifdef PC
+ #define MFLAGS "wb"
+#else
+ #define MFLAGS "w"
+#endif
/***** prototype definitions *****/
Element *eval_sub(Element *);
Element *get_lab(Lextok *, int);
-Element *huntele(Element *, int, int);
+Element *huntele(Element *, unsigned int, int);
Element *huntstart(Element *);
+Element *mk_skip(void);
Element *target(Element *);
Lextok *do_unless(Lextok *, Lextok *);
@@ -238,8 +271,9 @@
Lextok *rem_lab(Symbol *, Lextok *, Symbol *);
Lextok *rem_var(Symbol *, Lextok *, Symbol *, Lextok *);
Lextok *tail_add(Lextok *, Lextok *);
+Lextok *return_statement(Lextok *);
-ProcList *ready(Symbol *, Lextok *, Sequence *, int, Lextok *);
+ProcList *ready(Symbol *, Lextok *, Sequence *, int, Lextok *, enum btypes);
SeqList *seqlist(Sequence *, SeqList *);
Sequence *close_seq(int);
@@ -250,7 +284,8 @@
Symbol *lookup(char *);
Symbol *prep_inline(Symbol *, Lextok *);
-char *emalloc(int);
+char *put_inline(FILE *, char *);
+char *emalloc(size_t);
long Rand(void);
int any_oper(Lextok *, int);
@@ -258,6 +293,7 @@
int c_add_sv(FILE *);
int cast_val(int, int, int);
int checkvar(Symbol *, int);
+int check_track(Lextok *);
int Cnt_flds(Lextok *);
int cnt_mpars(Lextok *);
int complete_rendez(void);
@@ -274,6 +310,7 @@
int in_bound(Symbol *, int);
int interprint(FILE *, Lextok *);
int printm(FILE *, Lextok *);
+int is_inline(void);
int ismtype(char *);
int isproctype(char *);
int isutype(char *);
@@ -280,6 +317,7 @@
int Lval_struct(Lextok *, Symbol *, int, int);
int main(int, char **);
int pc_value(Lextok *);
+int pid_is_claim(int);
int proper_enabler(Lextok *);
int putcode(FILE *, Sequence *, Element *, int, int, int);
int q_is_sync(Lextok *);
@@ -298,7 +336,6 @@
int tl_main(int, char *[]);
int Width_set(int *, int, Lextok *);
int yyparse(void);
-int yywrap(void);
int yylex(void);
void AST_track(Lextok *, int);
@@ -309,7 +346,6 @@
void c_add_def(FILE *);
void c_add_loc(FILE *, char *);
void c_add_locinit(FILE *, int, char *);
-void c_add_use(FILE *);
void c_chandump(FILE *);
void c_preview(void);
void c_struct(FILE *, char *, Symbol *);
@@ -321,6 +357,7 @@
void checkrun(Symbol *, int);
void comment(FILE *, Lextok *, int);
void cross_dsteps(Lextok *, Lextok *);
+void disambiguate(void);
void doq(Symbol *, int, RunList *);
void dotag(FILE *, char *);
void do_locinits(FILE *);
@@ -344,20 +381,22 @@
void ini_struct(Symbol *);
void loose_ends(void);
void make_atomic(Sequence *, int);
+void mark_last(void);
void match_trail(void);
void no_side_effects(char *);
void nochan_manip(Lextok *, Lextok *, int);
void non_fatal(char *, char *);
-void ntimes(FILE *, int, int, char *c[]);
+void ntimes(FILE *, int, int, const char *c[]);
void open_seq(int);
void p_talk(Element *, int);
-void pickup_inline(Symbol *, Lextok *);
+void pickup_inline(Symbol *, Lextok *, Lextok *);
void plunk_c_decls(FILE *);
void plunk_c_fcts(FILE *);
void plunk_expr(FILE *, char *);
-void plunk_inline(FILE *, char *, int);
+void plunk_inline(FILE *, char *, int, int);
void prehint(Symbol *);
void preruse(FILE *, Lextok *);
+void pretty_print(void);
void prune_opts(Lextok *);
void pstext(int, char *);
void pushbreak(void);
@@ -383,17 +422,23 @@
void struct_name(Lextok *, Symbol *, int, char *);
void symdump(void);
void symvar(Symbol *);
+void sync_product(void);
void trackchanuse(Lextok *, Lextok *, int);
void trackvar(Lextok *, Lextok *);
void trackrun(Lextok *);
-void trapwonly(Lextok *, char *); /* spin.y and main.c */
+void trapwonly(Lextok * /* , char * */); /* spin.y and main.c */
void typ2c(Symbol *);
void typ_ck(int, int, char *);
void undostmnt(Lextok *, int);
void unrem_Seq(void);
void unskip(int);
-void varcheck(Element *, Element *);
void whoruns(int);
void wrapup(int);
void yyerror(char *, ...);
+
+extern int unlink(const char *);
+
+#define TMP_FILE1 "._s_p_i_n_"
+#define TMP_FILE2 "._n_i_p_s_"
+
#endif
--- a/sys/src/cmd/spin/spin.y
+++ b/sys/src/cmd/spin/spin.y
@@ -1,47 +1,69 @@
/***** spin: spin.y *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
%{
#include "spin.h"
+#include <sys/types.h>
+#ifndef PC
+#include <unistd.h>
+#endif
#include <stdarg.h>
-#define YYDEBUG 0
+#define YYMAXDEPTH 20000 /* default is 10000 */
+#define YYDEBUG 0
#define Stop nn(ZN,'@',ZN,ZN)
+#define PART0 "place initialized declaration of "
+#define PART1 "place initialized chan decl of "
+#define PART2 " at start of proctype "
+static Lextok *ltl_to_string(Lextok *);
+
extern Symbol *context, *owner;
-extern int u_sync, u_async, dumptab;
-extern short has_sorted, has_random, has_enabled, has_pcvalue, has_np;
-extern short has_code, has_state, has_io;
+extern Lextok *for_body(Lextok *, int);
+extern void for_setup(Lextok *, Lextok *, Lextok *);
+extern Lextok *for_index(Lextok *, Lextok *);
+extern Lextok *sel_index(Lextok *, Lextok *, Lextok *);
+extern void keep_track_off(Lextok *);
+extern void safe_break(void);
+extern void restore_break(void);
+extern int u_sync, u_async, dumptab, scope_level;
+extern int initialization_ok;
+extern short has_sorted, has_random, has_enabled, has_pcvalue, has_np, has_priority;
+extern short has_code, has_state, has_ltl, has_io;
extern void count_runs(Lextok *);
extern void no_internals(Lextok *);
extern void any_runs(Lextok *);
+extern void explain(int);
+extern void ltl_list(char *, char *);
extern void validref(Lextok *, Lextok *);
+extern void sanity_check(Lextok *);
extern char yytext[];
int Mpars = 0; /* max nr of message parameters */
-int runsafe = 1; /* 1 if all run stmnts are in init */
+int nclaims = 0; /* nr of never claims */
+int ltl_mode = 0; /* set when parsing an ltl formula */
int Expand_Ok = 0, realread = 1, IArgs = 0, NamesNotAdded = 0;
+int in_for = 0, in_seq = 0, par_cnt = 0;
+int dont_simplify = 0;
char *claimproc = (char *) 0;
char *eventmap = (char *) 0;
-static int Embedded = 0, inEventMap = 0, has_ini = 0;
+static char *ltl_name;
+static int Embedded = 0, inEventMap = 0, has_ini = 0;
%}
-%token ASSERT PRINT PRINTM
+%token ASSERT PRINT PRINTM PREPROC
%token C_CODE C_DECL C_EXPR C_STATE C_TRACK
-%token RUN LEN ENABLED EVAL PC_VAL
-%token TYPEDEF MTYPE INLINE LABEL OF
-%token GOTO BREAK ELSE SEMI
-%token IF FI DO OD SEP
+%token RUN LEN ENABLED SET_P GET_P EVAL PC_VAL
+%token TYPEDEF MTYPE INLINE RETURN LABEL OF
+%token GOTO BREAK ELSE SEMI ARROW
+%token IF FI DO OD FOR SELECT IN SEP DOTDOT
%token ATOMIC NON_ATOMIC D_STEP UNLESS
%token TIMEOUT NONPROGRESS
%token ACTIVE PROCTYPE D_PROCTYPE
@@ -50,12 +72,16 @@
%token FULL EMPTY NFULL NEMPTY
%token CONST TYPE XU /* val */
%token NAME UNAME PNAME INAME /* sym */
-%token STRING CLAIM TRACE INIT /* sym */
+%token STRING CLAIM TRACE INIT LTL /* sym */
%right ASGN
%left SND O_SND RCV R_RCV /* SND doubles as boolean negation */
+%left IMPLIES EQUIV /* ltl */
%left OR
%left AND
+%left ALWAYS EVENTUALLY /* ltl */
+%left UNTIL WEAK_UNTIL RELEASE /* ltl */
+%right NEXT /* ltl */
%left '|'
%left '^'
%left '&'
@@ -81,17 +107,25 @@
unit : proc /* proctype { } */
| init /* init { } */
| claim /* never claim */
+ | ltl /* ltl formula */
| events /* event assertions */
| one_decl /* variables, chans */
| utype /* user defined types */
| c_fcts /* c functions etc. */
| ns /* named sequence */
- | SEMI /* optional separator */
+ | semi /* optional separator */
| error
;
+l_par : '(' { par_cnt++; }
+ ;
+
+r_par : ')' { par_cnt--; }
+ ;
+
+
proc : inst /* optional instantiator */
- proctype NAME {
+ proctype NAME {
setptype($3, PROCTYPE, ZN);
setpname($3);
context = $3->sym;
@@ -99,7 +133,7 @@
Expand_Ok++; /* expand struct names in decl */
has_ini = 0;
}
- '(' decl ')' { Expand_Ok--;
+ l_par decl r_par { Expand_Ok--;
if (has_ini)
fatal("initializer in parameter list", (char *) 0);
}
@@ -106,14 +140,23 @@
Opt_priority
Opt_enabler
body { ProcList *rl;
- rl = ready($3->sym, $6, $11->sq, $2->val, $10);
if ($1 != ZN && $1->val > 0)
{ int j;
+ rl = ready($3->sym, $6, $11->sq, $2->val, $10, A_PROC);
for (j = 0; j < $1->val; j++)
- runnable(rl, $9?$9->val:1, 1);
+ { runnable(rl, $9?$9->val:1, 1);
announce(":root:");
+ }
if (dumptab) $3->sym->ini = $1;
+ } else
+ { rl = ready($3->sym, $6, $11->sq, $2->val, $10, P_PROC);
}
+ if (rl && has_ini == 1) /* global initializations, unsafe */
+ { /* printf("proctype %s has initialized data\n",
+ $3->sym->name);
+ */
+ rl->unsafe = 1;
+ }
context = ZS;
}
;
@@ -124,7 +167,7 @@
inst : /* empty */ { $$ = ZN; }
| ACTIVE { $$ = nn(ZN,CONST,ZN,ZN); $$->val = 1; }
- | ACTIVE '[' CONST ']' {
+ | ACTIVE '[' const_expr ']' {
$$ = nn(ZN,CONST,ZN,ZN); $$->val = $3->val;
if ($3->val > 255)
non_fatal("max nr of processes is 255\n", "");
@@ -133,10 +176,10 @@
$$ = nn(ZN,CONST,ZN,ZN);
$$->val = 0;
if (!$3->sym->type)
- non_fatal("undeclared variable %s",
+ fatal("undeclared variable %s",
$3->sym->name);
else if ($3->sym->ini->ntyp != CONST)
- non_fatal("need constant initializer for %s\n",
+ fatal("need constant initializer for %s\n",
$3->sym->name);
else
$$->val = $3->sym->ini->val;
@@ -146,7 +189,7 @@
init : INIT { context = $1->sym; }
Opt_priority
body { ProcList *rl;
- rl = ready(context, ZN, $4->sq, 0, ZN);
+ rl = ready(context, ZN, $4->sq, 0, ZN, I_PROC);
runnable(rl, $3?$3->val:1, 1);
announce(":root:");
context = ZS;
@@ -153,16 +196,49 @@
}
;
-claim : CLAIM { context = $1->sym;
- if (claimproc)
- non_fatal("claim %s redefined", claimproc);
+ltl : LTL optname2 { ltl_mode = 1; ltl_name = $2->sym->name; }
+ ltl_body { if ($4) ltl_list($2->sym->name, $4->sym->name);
+ ltl_mode = 0; has_ltl = 1;
+ }
+ ;
+
+ltl_body: '{' full_expr OS '}' { $$ = ltl_to_string($2); }
+ | error { $$ = NULL; }
+ ;
+
+claim : CLAIM optname { if ($2 != ZN)
+ { $1->sym = $2->sym; /* new 5.3.0 */
+ }
+ nclaims++;
+ context = $1->sym;
+ if (claimproc && !strcmp(claimproc, $1->sym->name))
+ { fatal("claim %s redefined", claimproc);
+ }
claimproc = $1->sym->name;
}
- body { (void) ready($1->sym, ZN, $3->sq, 0, ZN);
+ body { (void) ready($1->sym, ZN, $4->sq, 0, ZN, N_CLAIM);
context = ZS;
}
;
+optname : /* empty */ { char tb[32];
+ memset(tb, 0, 32);
+ sprintf(tb, "never_%d", nclaims);
+ $$ = nn(ZN, NAME, ZN, ZN);
+ $$->sym = lookup(tb);
+ }
+ | NAME { $$ = $1; }
+ ;
+
+optname2 : /* empty */ { char tb[32]; static int nltl = 0;
+ memset(tb, 0, 32);
+ sprintf(tb, "ltl_%d", nltl++);
+ $$ = nn(ZN, NAME, ZN, ZN);
+ $$->sym = lookup(tb);
+ }
+ | NAME { $$ = $1; }
+ ;
+
events : TRACE { context = $1->sym;
if (eventmap)
non_fatal("trace %s redefined", eventmap);
@@ -169,18 +245,28 @@
eventmap = $1->sym->name;
inEventMap++;
}
- body { (void) ready($1->sym, ZN, $3->sq, 0, ZN);
+ body {
+ if (strcmp($1->sym->name, ":trace:") == 0)
+ { (void) ready($1->sym, ZN, $3->sq, 0, ZN, E_TRACE);
+ } else
+ { (void) ready($1->sym, ZN, $3->sq, 0, ZN, N_TRACE);
+ }
context = ZS;
inEventMap--;
}
;
-utype : TYPEDEF NAME { if (context)
- fatal("typedef %s must be global",
- $2->sym->name);
+utype : TYPEDEF NAME '{' { if (context)
+ { fatal("typedef %s must be global",
+ $2->sym->name);
+ }
owner = $2->sym;
+ in_seq = $1->ln;
}
- '{' decl_lst '}' { setuname($5); owner = ZS; }
+ decl_lst '}' { setuname($5);
+ owner = ZS;
+ in_seq = 0;
+ }
;
nm : NAME { $$ = $1; }
@@ -190,8 +276,8 @@
}
;
-ns : INLINE nm '(' { NamesNotAdded++; }
- args ')' { prep_inline($2->sym, $5);
+ns : INLINE nm l_par { NamesNotAdded++; }
+ args r_par { prep_inline($2->sym, $5);
NamesNotAdded--;
}
;
@@ -227,6 +313,8 @@
NamesNotAdded--;
$$ = nn(ZN, C_CODE, ZN, ZN);
$$->sym = s;
+ $$->ln = $1->ln;
+ $$->fn = $1->fn;
has_code = 1;
}
| C_DECL { Symbol *s;
@@ -236,6 +324,8 @@
s->type = CODE_DECL;
$$ = nn(ZN, C_CODE, ZN, ZN);
$$->sym = s;
+ $$->ln = $1->ln;
+ $$->fn = $1->fn;
has_code = 1;
}
;
@@ -242,17 +332,29 @@
cexpr : C_EXPR { Symbol *s;
NamesNotAdded++;
s = prep_inline(ZS, ZN);
+/* if context is 0 this was inside an ltl formula
+ mark the last inline added to seqnames */
+ if (!context)
+ { mark_last();
+ }
NamesNotAdded--;
$$ = nn(ZN, C_EXPR, ZN, ZN);
$$->sym = s;
+ $$->ln = $1->ln;
+ $$->fn = $1->fn;
no_side_effects(s->name);
has_code = 1;
}
;
-body : '{' { open_seq(1); }
+body : '{' { open_seq(1); in_seq = $1->ln; }
sequence OS { add_seq(Stop); }
- '}' { $$->sq = close_seq(0); }
+ '}' { $$->sq = close_seq(0); in_seq = 0;
+ if (scope_level != 0)
+ { non_fatal("missing '}' ?", 0);
+ scope_level = 0;
+ }
+ }
;
sequence: step { if ($1) add_seq($1); }
@@ -264,7 +366,11 @@
| NAME ':' one_decl { fatal("label preceding declaration,", (char *)0); }
| NAME ':' XU { fatal("label predecing xr/xs claim,", 0); }
| stmnt { $$ = $1; }
- | stmnt UNLESS stmnt { $$ = do_unless($1, $3); }
+ | stmnt UNLESS { if ($1->ntyp == DO) { safe_break(); } }
+ stmnt { if ($1->ntyp == DO) { restore_break(); }
+ $$ = do_unless($1, $4);
+ }
+ | error { printf("Not a Step\n"); }
;
vis : /* empty */ { $$ = ZN; }
@@ -277,7 +383,9 @@
| ASGN
;
-one_decl: vis TYPE var_list { setptype($3, $2->val, $1); $$ = $3; }
+one_decl: vis TYPE var_list { setptype($3, $2->val, $1);
+ $$ = $3;
+ }
| vis UNAME var_list { setutype($3, $2->sym, $1);
$$ = expand($3, Expand_Ok);
}
@@ -310,26 +418,76 @@
| ivar ',' var_list { $$ = nn($1, TYPE, ZN, $3); }
;
+c_list : CONST { $1->ntyp = CONST; $$ = $1; }
+ | CONST ',' c_list { $1->ntyp = CONST; $$ = nn($1, ',', $1, $3); }
+ ;
+
ivar : vardcl { $$ = $1;
$1->sym->ini = nn(ZN,CONST,ZN,ZN);
$1->sym->ini->val = 0;
+ if (!initialization_ok)
+ { Lextok *zx, *xz;
+ zx = nn(ZN, NAME, ZN, ZN);
+ zx->sym = $1->sym;
+ xz = nn(zx, ASGN, zx, $1->sym->ini);
+ keep_track_off(xz);
+ /* make sure zx doesnt turn out to be a STRUCT later */
+ add_seq(xz);
+ }
}
- | vardcl ASGN expr { $1->sym->ini = $3; $$ = $1;
- trackvar($1,$3); has_ini = 1;
+ | vardcl ASGN '{' c_list '}' {
+ if (!$1->sym->isarray)
+ fatal("%s must be an array", $1->sym->name);
+ $$ = $1;
+ $1->sym->ini = $4;
+ has_ini = 1;
+ $1->sym->hidden |= (4|8); /* conservative */
+ if (!initialization_ok)
+ { Lextok *zx = nn(ZN, NAME, ZN, ZN);
+ zx->sym = $1->sym;
+ add_seq(nn(zx, ASGN, zx, $4));
+ }
}
+ | vardcl ASGN expr { $$ = $1;
+ $1->sym->ini = $3;
+ if ($3->ntyp == CONST
+ || ($3->ntyp == NAME && $3->sym->context))
+ { has_ini = 2; /* local init */
+ } else
+ { has_ini = 1; /* possibly global */
+ }
+ trackvar($1, $3);
+ if (any_oper($3, RUN))
+ { fatal("cannot use 'run' in var init, saw", (char *) 0);
+ }
+ nochan_manip($1, $3, 0);
+ no_internals($1);
+ if (!initialization_ok)
+ { Lextok *zx = nn(ZN, NAME, ZN, ZN);
+ zx->sym = $1->sym;
+ add_seq(nn(zx, ASGN, zx, $3));
+ }
+ }
| vardcl ASGN ch_init { $1->sym->ini = $3;
$$ = $1; has_ini = 1;
+ if (!initialization_ok)
+ { non_fatal(PART1 "'%s'" PART2, $1->sym->name);
+ }
}
;
-ch_init : '[' CONST ']' OF
- '{' typ_list '}' { if ($2->val) u_async++;
- else u_sync++;
+ch_init : '[' const_expr ']' OF
+ '{' typ_list '}' { if ($2->val)
+ u_async++;
+ else
+ u_sync++;
{ int i = cnt_mpars($6);
Mpars = max(Mpars, i);
}
$$ = nn(ZN, CHAN, ZN, $6);
$$->val = $2->val;
+ $$->ln = $1->ln;
+ $$->fn = $1->fn;
}
;
@@ -342,13 +500,33 @@
}
$1->sym->nel = 1; $$ = $1;
}
- | NAME '[' CONST ']' { $1->sym->nel = $3->val; $$ = $1; }
+ | NAME '[' const_expr ']' { $1->sym->nel = $3->val; $1->sym->isarray = 1; $$ = $1; }
+ | NAME '[' NAME ']' { /* make an exception for an initialized scalars */
+ $$ = nn(ZN, CONST, ZN, ZN);
+ fprintf(stderr, "spin: %s:%d, warning: '%s' in array bound ",
+ $1->fn->name, $1->ln, $3->sym->name);
+ if ($3->sym->ini->val > 0)
+ { fprintf(stderr, "evaluated as %d\n", $3->sym->ini->val);
+ $$->val = $3->sym->ini->val;
+ } else
+ { fprintf(stderr, "evaluated as 8 by default (to avoid zero)\n");
+ $$->val = 8;
+ }
+ $1->sym->nel = $$->val;
+ $1->sym->isarray = 1;
+ $$ = $1;
+ }
;
varref : cmpnd { $$ = mk_explicit($1, Expand_Ok, NAME); }
;
-pfld : NAME { $$ = nn($1, NAME, ZN, ZN); }
+pfld : NAME { $$ = nn($1, NAME, ZN, ZN);
+ if ($1->sym->isarray && !in_for)
+ { non_fatal("missing array index for '%s'",
+ $1->sym->name);
+ }
+ }
| NAME { owner = ZS; }
'[' expr ']' { $$ = nn($1, NAME, $4, ZN); }
;
@@ -363,7 +541,7 @@
Embedded--;
if (!Embedded && !NamesNotAdded
&& !$1->sym->type)
- non_fatal("undeclared variable: %s",
+ fatal("undeclared variable: %s",
$1->sym->name);
if ($3) validref($1, $3->lft);
owner = ZS;
@@ -374,13 +552,21 @@
| '.' cmpnd %prec DOT { $$ = nn(ZN, '.', $2, ZN); }
;
-stmnt : Special { $$ = $1; }
- | Stmnt { $$ = $1;
- if (inEventMap)
- non_fatal("not an event", (char *)0);
+stmnt : Special { $$ = $1; initialization_ok = 0; }
+ | Stmnt { $$ = $1; initialization_ok = 0;
+ if (inEventMap) non_fatal("not an event", (char *)0);
}
;
+for_pre : FOR l_par { in_for = 1; }
+ varref { trapwonly($4 /*, "for" */);
+ pushbreak(); /* moved up */
+ $$ = $4;
+ }
+ ;
+
+for_post: '{' sequence OS '}' ;
+
Special : varref RCV { Expand_Ok++; }
rargs { Expand_Ok--; has_io++;
$$ = nn($1, 'r', $1, $4);
@@ -392,13 +578,30 @@
$$->val=0; trackchanuse($4, ZN, 'S');
any_runs($4);
}
+ | for_pre ':' expr DOTDOT expr r_par {
+ for_setup($1, $3, $5); in_for = 0;
+ }
+ for_post { $$ = for_body($1, 1);
+ }
+ | for_pre IN varref r_par { $$ = for_index($1, $3); in_for = 0;
+ }
+ for_post { $$ = for_body($5, 1);
+ }
+ | SELECT l_par varref ':' expr DOTDOT expr r_par {
+ trapwonly($3 /*, "select" */);
+ $$ = sel_index($3, $5, $7);
+ }
| IF options FI { $$ = nn($1, IF, ZN, ZN);
$$->sl = $2->sl;
+ $$->ln = $1->ln;
+ $$->fn = $1->fn;
prune_opts($$);
}
| DO { pushbreak(); }
options OD { $$ = nn($1, DO, ZN, ZN);
$$->sl = $3->sl;
+ $$->ln = $1->ln;
+ $$->fn = $1->fn;
prune_opts($$);
}
| BREAK { $$ = nn(ZN, GOTO, ZN, ZN);
@@ -420,9 +623,22 @@
}
$1->sym->type = LABEL;
}
+ | NAME ':' { $$ = nn($1, ':',ZN,ZN);
+ if ($1->sym->type != 0
+ && $1->sym->type != LABEL) {
+ non_fatal("bad label-name %s",
+ $1->sym->name);
+ }
+ $$->lft = nn(ZN, 'c', nn(ZN,CONST,ZN,ZN), ZN);
+ $$->lft->lft->val = 1; /* skip */
+ $1->sym->type = LABEL;
+ }
+ | error { $$ = nn(ZN, 'c', nn(ZN,CONST,ZN,ZN), ZN);
+ $$->lft->val = 1; /* skip */
+ }
;
-Stmnt : varref ASGN expr { $$ = nn($1, ASGN, $1, $3);
+Stmnt : varref ASGN full_expr { $$ = nn($1, ASGN, $1, $3);
trackvar($1, $3);
nochan_manip($1, $3, 0);
no_internals($1);
@@ -443,10 +659,11 @@
if ($1->sym->type == CHAN)
fatal("arithmetic on chan id's", (char *)0);
}
- | PRINT '(' STRING { realread = 0; }
- prargs ')' { $$ = nn($3, PRINT, $5, ZN); realread = 1; }
- | PRINTM '(' varref ')' { $$ = nn(ZN, PRINTM, $3, ZN); }
- | PRINTM '(' CONST ')' { $$ = nn(ZN, PRINTM, $3, ZN); }
+ | SET_P l_par two_args r_par { $$ = nn(ZN, SET_P, $3, ZN); has_priority++; }
+ | PRINT l_par STRING { realread = 0; }
+ prargs r_par { $$ = nn($3, PRINT, $5, ZN); realread = 1; }
+ | PRINTM l_par varref r_par { $$ = nn(ZN, PRINTM, $3, ZN); }
+ | PRINTM l_par CONST r_par { $$ = nn(ZN, PRINTM, $3, ZN); }
| ASSERT full_expr { $$ = nn(ZN, ASSERT, $2, ZN); AST_track($2, 0); }
| ccode { $$ = $1; }
| varref R_RCV { Expand_Ok++; }
@@ -480,11 +697,17 @@
| ATOMIC '{' { open_seq(0); }
sequence OS '}' { $$ = nn($1, ATOMIC, ZN, ZN);
$$->sl = seqlist(close_seq(3), 0);
- make_atomic($$->sl->this, 0);
+ $$->ln = $1->ln;
+ $$->fn = $1->fn;
+ make_atomic($$->sl->this, 0);
}
- | D_STEP '{' { open_seq(0); rem_Seq(); }
+ | D_STEP '{' { open_seq(0);
+ rem_Seq();
+ }
sequence OS '}' { $$ = nn($1, D_STEP, ZN, ZN);
$$->sl = seqlist(close_seq(4), 0);
+ $$->ln = $1->ln;
+ $$->fn = $1->fn;
make_atomic($$->sl->this, D_ATOM);
unrem_Seq();
}
@@ -491,10 +714,23 @@
| '{' { open_seq(0); }
sequence OS '}' { $$ = nn(ZN, NON_ATOMIC, ZN, ZN);
$$->sl = seqlist(close_seq(5), 0);
+ $$->ln = $1->ln;
+ $$->fn = $1->fn;
}
| INAME { IArgs++; }
- '(' args ')' { pickup_inline($1->sym, $4); IArgs--; }
+ l_par args r_par { initialization_ok = 0;
+ pickup_inline($1->sym, $4, ZN);
+ IArgs--;
+ }
Stmnt { $$ = $7; }
+
+ | varref ASGN INAME { IArgs++; }
+ l_par args r_par { initialization_ok = 0;
+ pickup_inline($3->sym, $6, $1);
+ IArgs--;
+ }
+ Stmnt { $$ = $9; }
+ | RETURN full_expr { $$ = return_statement($2); }
;
options : option { $$->sl = seqlist($1->sq, 0); }
@@ -503,22 +739,39 @@
option : SEP { open_seq(0); }
sequence OS { $$ = nn(ZN,0,ZN,ZN);
- $$->sq = close_seq(6); }
+ $$->sq = close_seq(6);
+ $$->ln = $1->ln;
+ $$->fn = $1->fn;
+ }
;
OS : /* empty */
- | SEMI { /* redundant semi at end of sequence */ }
+ | semi { /* redundant semi at end of sequence */ }
;
-MS : SEMI { /* at least one semi-colon */ }
- | MS SEMI { /* but more are okay too */ }
+semi : SEMI
+ | ARROW
;
+MS : semi { /* at least one semi-colon */ }
+ | MS semi { /* but more are okay too */ }
+ ;
+
aname : NAME { $$ = $1; }
| PNAME { $$ = $1; }
;
-expr : '(' expr ')' { $$ = $2; }
+const_expr: CONST { $$ = $1; }
+ | '-' const_expr %prec UMIN { $$ = $2; $$->val = -($2->val); }
+ | l_par const_expr r_par { $$ = $2; }
+ | const_expr '+' const_expr { $$ = $1; $$->val = $1->val + $3->val; }
+ | const_expr '-' const_expr { $$ = $1; $$->val = $1->val - $3->val; }
+ | const_expr '*' const_expr { $$ = $1; $$->val = $1->val * $3->val; }
+ | const_expr '/' const_expr { $$ = $1; $$->val = $1->val / $3->val; }
+ | const_expr '%' const_expr { $$ = $1; $$->val = $1->val % $3->val; }
+ ;
+
+expr : l_par expr r_par { $$ = $2; }
| expr '+' expr { $$ = nn(ZN, '+', $1, $3); }
| expr '-' expr { $$ = nn(ZN, '-', $1, $3); }
| expr '*' expr { $$ = nn(ZN, '*', $1, $3); }
@@ -541,7 +794,7 @@
| '-' expr %prec UMIN { $$ = nn(ZN, UMIN, $2, ZN); }
| SND expr %prec NEG { $$ = nn(ZN, '!', $2, ZN); }
- | '(' expr SEMI expr ':' expr ')' {
+ | l_par expr ARROW expr ':' expr r_par {
$$ = nn(ZN, OR, $4, $6);
$$ = nn(ZN, '?', $2, $$);
}
@@ -548,21 +801,18 @@
| RUN aname { Expand_Ok++;
if (!context)
- fatal("used 'run' outside proctype",
+ fatal("used 'run' outside proctype",
(char *) 0);
- if (strcmp(context->name, ":init:") != 0)
- runsafe = 0;
}
- '(' args ')'
+ l_par args r_par
Opt_priority { Expand_Ok--;
$$ = nn($2, RUN, $5, ZN);
- $$->val = ($7) ? $7->val : 1;
+ $$->val = ($7) ? $7->val : 0;
trackchanuse($5, $2, 'A'); trackrun($$);
}
- | LEN '(' varref ')' { $$ = nn($3, LEN, $3, ZN); }
- | ENABLED '(' expr ')' { $$ = nn(ZN, ENABLED, $3, ZN);
- has_enabled++;
- }
+ | LEN l_par varref r_par { $$ = nn($3, LEN, $3, ZN); }
+ | ENABLED l_par expr r_par { $$ = nn(ZN, ENABLED, $3, ZN); has_enabled++; }
+ | GET_P l_par expr r_par { $$ = nn(ZN, GET_P, $3, ZN); has_priority++; }
| varref RCV { Expand_Ok++; }
'[' rargs ']' { Expand_Ok--; has_io++;
$$ = nn($1, 'R', $1, $5);
@@ -572,7 +822,7 @@
$$ = nn($1, 'R', $1, $5);
$$->val = has_random = 1;
}
- | varref { $$ = $1; trapwonly($1, "varref"); }
+ | varref { $$ = $1; trapwonly($1 /*, "varref" */); }
| cexpr { $$ = $1; }
| CONST { $$ = nn(ZN,CONST,ZN,ZN);
$$->ismtyp = $1->ismtyp;
@@ -582,7 +832,7 @@
| NONPROGRESS { $$ = nn(ZN,NONPROGRESS, ZN, ZN);
has_np++;
}
- | PC_VAL '(' expr ')' { $$ = nn(ZN, PC_VAL, $3, ZN);
+ | PC_VAL l_par expr r_par { $$ = nn(ZN, PC_VAL, $3, ZN);
has_pcvalue++;
}
| PNAME '[' expr ']' '@' NAME
@@ -591,47 +841,63 @@
{ $$ = rem_var($1->sym, $3, $6->sym, $6->lft); }
| PNAME '@' NAME { $$ = rem_lab($1->sym, ZN, $3->sym); }
| PNAME ':' pfld { $$ = rem_var($1->sym, ZN, $3->sym, $3->lft); }
+ | ltl_expr { $$ = $1; /* sanity_check($1); */ }
;
Opt_priority: /* none */ { $$ = ZN; }
- | PRIORITY CONST { $$ = $2; }
+ | PRIORITY CONST { $$ = $2; has_priority++; }
;
full_expr: expr { $$ = $1; }
- | Expr { $$ = $1; }
+ | Expr { $$ = $1; }
;
-Opt_enabler: /* none */ { $$ = ZN; }
- | PROVIDED '(' full_expr ')' { if (!proper_enabler($3))
- { non_fatal("invalid PROVIDED clause",
- (char *)0);
- $$ = ZN;
- } else
- $$ = $3;
- }
- | PROVIDED error { $$ = ZN;
- non_fatal("usage: provided ( ..expr.. )",
- (char *)0);
+ltl_expr: expr UNTIL expr { $$ = nn(ZN, UNTIL, $1, $3); }
+ | expr RELEASE expr { $$ = nn(ZN, RELEASE, $1, $3); }
+ | expr WEAK_UNTIL expr { $$ = nn(ZN, ALWAYS, $1, ZN);
+ $$ = nn(ZN, OR, $$, nn(ZN, UNTIL, $1, $3));
}
+ | expr IMPLIES expr {
+ $$ = nn(ZN, '!', $1, ZN);
+ $$ = nn(ZN, OR, $$, $3);
+ }
+ | expr EQUIV expr { $$ = nn(ZN, EQUIV, $1, $3); }
+ | NEXT expr %prec NEG { $$ = nn(ZN, NEXT, $2, ZN); }
+ | ALWAYS expr %prec NEG { $$ = nn(ZN, ALWAYS,$2, ZN); }
+ | EVENTUALLY expr %prec NEG { $$ = nn(ZN, EVENTUALLY, $2, ZN); }
;
/* an Expr cannot be negated - to protect Probe expressions */
Expr : Probe { $$ = $1; }
- | '(' Expr ')' { $$ = $2; }
+ | l_par Expr r_par { $$ = $2; }
| Expr AND Expr { $$ = nn(ZN, AND, $1, $3); }
| Expr AND expr { $$ = nn(ZN, AND, $1, $3); }
+ | expr AND Expr { $$ = nn(ZN, AND, $1, $3); }
| Expr OR Expr { $$ = nn(ZN, OR, $1, $3); }
| Expr OR expr { $$ = nn(ZN, OR, $1, $3); }
- | expr AND Expr { $$ = nn(ZN, AND, $1, $3); }
| expr OR Expr { $$ = nn(ZN, OR, $1, $3); }
;
-Probe : FULL '(' varref ')' { $$ = nn($3, FULL, $3, ZN); }
- | NFULL '(' varref ')' { $$ = nn($3, NFULL, $3, ZN); }
- | EMPTY '(' varref ')' { $$ = nn($3, EMPTY, $3, ZN); }
- | NEMPTY '(' varref ')' { $$ = nn($3,NEMPTY, $3, ZN); }
+Probe : FULL l_par varref r_par { $$ = nn($3, FULL, $3, ZN); }
+ | NFULL l_par varref r_par { $$ = nn($3, NFULL, $3, ZN); }
+ | EMPTY l_par varref r_par { $$ = nn($3, EMPTY, $3, ZN); }
+ | NEMPTY l_par varref r_par { $$ = nn($3,NEMPTY, $3, ZN); }
;
+Opt_enabler: /* none */ { $$ = ZN; }
+ | PROVIDED l_par full_expr r_par { if (!proper_enabler($3))
+ { non_fatal("invalid PROVIDED clause",
+ (char *)0);
+ $$ = ZN;
+ } else
+ $$ = $3;
+ }
+ | PROVIDED error { $$ = ZN;
+ non_fatal("usage: provided ( ..expr.. )",
+ (char *)0);
+ }
+ ;
+
basetype: TYPE { $$->sym = ZS;
$$->val = $1->val;
if ($$->val == UNSIGNED)
@@ -647,6 +913,9 @@
| basetype ',' typ_list { $$ = nn($1, $1->val, ZN, $3); }
;
+two_args: expr ',' expr { $$ = nn(ZN, ',', $1, $3); }
+ ;
+
args : /* empty */ { $$ = ZN; }
| arg { $$ = $1; }
;
@@ -656,7 +925,7 @@
;
margs : arg { $$ = $1; }
- | expr '(' arg ')' { if ($1->ntyp == ',')
+ | expr l_par arg r_par { if ($1->ntyp == ',')
$$ = tail_add($1, $3);
else
$$ = nn(ZN, ',', $1, $3);
@@ -676,9 +945,9 @@
;
rarg : varref { $$ = $1; trackvar($1, $1);
- trapwonly($1, "rarg"); }
- | EVAL '(' expr ')' { $$ = nn(ZN,EVAL,$3,ZN);
- trapwonly($1, "eval rarg"); }
+ trapwonly($1 /*, "rarg" */); }
+ | EVAL l_par expr r_par { $$ = nn(ZN,EVAL,$3,ZN);
+ trapwonly($1 /*, "eval rarg" */); }
| CONST { $$ = nn(ZN,CONST,ZN,ZN);
$$->ismtyp = $1->ismtyp;
$$->val = $1->val;
@@ -698,12 +967,12 @@
else
$$ = nn(ZN, ',', $1, $3);
}
- | rarg '(' rargs ')' { if ($1->ntyp == ',')
+ | rarg l_par rargs r_par { if ($1->ntyp == ',')
$$ = tail_add($1, $3);
else
$$ = nn(ZN, ',', $1, $3);
}
- | '(' rargs ')' { $$ = $2; }
+ | l_par rargs r_par { $$ = $2; }
;
nlst : NAME { $$ = nn($1, NAME, ZN, ZN);
@@ -714,6 +983,138 @@
| nlst ',' { $$ = $1; /* commas optional */ }
;
%%
+
+#define binop(n, sop) fprintf(fd, "("); recursive(fd, n->lft); \
+ fprintf(fd, ") %s (", sop); recursive(fd, n->rgt); \
+ fprintf(fd, ")");
+#define unop(n, sop) fprintf(fd, "%s (", sop); recursive(fd, n->lft); \
+ fprintf(fd, ")");
+
+static void
+recursive(FILE *fd, Lextok *n)
+{
+ if (n)
+ switch (n->ntyp) {
+ case NEXT:
+ unop(n, "X");
+ break;
+ case ALWAYS:
+ unop(n, "[]");
+ break;
+ case EVENTUALLY:
+ unop(n, "<>");
+ break;
+ case '!':
+ unop(n, "!");
+ break;
+ case UNTIL:
+ binop(n, "U");
+ break;
+ case WEAK_UNTIL:
+ binop(n, "W");
+ break;
+ case RELEASE: /* see http://en.wikipedia.org/wiki/Linear_temporal_logic */
+ binop(n, "V");
+ break;
+ case OR:
+ binop(n, "||");
+ break;
+ case AND:
+ binop(n, "&&");
+ break;
+ case IMPLIES:
+ binop(n, "->");
+ break;
+ case EQUIV:
+ binop(n, "<->");
+ break;
+ case C_EXPR:
+ fprintf(fd, "c_expr { %s }", put_inline(fd, n->sym->name));
+ break;
+ default:
+ comment(fd, n, 0);
+ break;
+ }
+}
+
+static Lextok *
+ltl_to_string(Lextok *n)
+{ Lextok *m = nn(ZN, 0, ZN, ZN);
+ char *retval;
+ char ltl_formula[2048];
+ FILE *tf = fopen(TMP_FILE1, "w+"); /* tmpfile() fails on Windows 7 */
+
+ /* convert the parsed ltl to a string
+ by writing into a file, using existing functions,
+ and then passing it to the existing interface for
+ conversion into a never claim
+ (this means parsing everything twice, which is
+ a little redundant, but adds only miniscule overhead)
+ */
+
+ if (!tf)
+ { fatal("cannot create temporary file", (char *) 0);
+ }
+ dont_simplify = 1;
+ recursive(tf, n);
+ dont_simplify = 0;
+ (void) fseek(tf, 0L, SEEK_SET);
+
+ memset(ltl_formula, 0, sizeof(ltl_formula));
+ retval = fgets(ltl_formula, sizeof(ltl_formula), tf);
+ fclose(tf);
+
+ (void) unlink(TMP_FILE1);
+
+ if (!retval)
+ { printf("%p\n", retval);
+ fatal("could not translate ltl ltl_formula", 0);
+ }
+
+ if (1) printf("ltl %s: %s\n", ltl_name, ltl_formula);
+
+ m->sym = lookup(ltl_formula);
+
+ return m;
+}
+
+int
+is_temporal(int t)
+{
+ return (t == EVENTUALLY || t == ALWAYS || t == UNTIL
+ || t == WEAK_UNTIL || t == RELEASE);
+}
+
+int
+is_boolean(int t)
+{
+ return (t == AND || t == OR || t == IMPLIES || t == EQUIV);
+}
+
+#if 0
+/* flags correct formula like: ltl { true U (true U true) } */
+void
+sanity_check(Lextok *t) /* check proper embedding of ltl_expr */
+{
+ if (!t) return;
+ sanity_check(t->lft);
+ sanity_check(t->rgt);
+
+ if (t->lft && t->rgt)
+ { if (!is_boolean(t->ntyp)
+ && (is_temporal(t->lft->ntyp)
+ || is_temporal(t->rgt->ntyp)))
+ { printf("spin: attempt to apply '");
+ explain(t->ntyp);
+ printf("' to '");
+ explain(t->lft->ntyp);
+ printf("' and '");
+ explain(t->rgt->ntyp);
+ printf("'\n");
+ /* non_fatal("missing parentheses?", (char *)0); */
+ } }
+}
+#endif
void
yyerror(char *fmt, ...)
--- a/sys/src/cmd/spin/spinlex.c
+++ b/sys/src/cmd/spin/spinlex.c
@@ -1,15 +1,15 @@
/***** spin: spinlex.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
#include "spin.h"
#include "y.tab.h"
@@ -21,8 +21,11 @@
Symbol *nm; /* name of the type */
Lextok *cn; /* contents */
Lextok *params; /* formal pars if any */
+ Lextok *rval; /* variable to assign return value, if any */
char **anms; /* literal text for actual pars */
char *prec; /* precondition for c_code or c_expr */
+ int uiid; /* unique inline id */
+ int is_expr; /* c_expr in an ltl formula */
int dln, cln; /* def and call linenr */
Symbol *dfn, *cfn; /* def and call filename */
struct IType *nxt; /* linked list */
@@ -32,19 +35,24 @@
Symbol *s;
Symbol *t;
Symbol *ival;
+ Symbol *fnm;
+ int lno;
struct C_Added *nxt;
} C_Added;
extern RunList *X;
extern ProcList *rdy;
-extern Symbol *Fname;
+extern Symbol *Fname, *oFname;
extern Symbol *context, *owner;
extern YYSTYPE yylval;
-extern short has_last, has_code;
-extern int verbose, IArgs, hastrack, separate;
+extern short has_last, has_code, has_priority;
+extern int verbose, IArgs, hastrack, separate, in_for;
+extern int implied_semis, ltl_mode, in_seq, par_cnt;
short has_stack = 0;
int lineno = 1;
+int scope_seq[128], scope_level = 0;
+char CurScope[MAXSCOPESZ];
char yytext[2048];
FILE *yyin, *yyout;
@@ -55,45 +63,62 @@
static unsigned char in_comment=0;
static int IArgno = 0, Inlining = -1;
static int check_name(char *);
+static int last_token = 0;
-#if 1
-#define Token(y) { if (in_comment) goto again; \
- yylval = nn(ZN,0,ZN,ZN); return y; }
-
#define ValToken(x, y) { if (in_comment) goto again; \
- yylval = nn(ZN,0,ZN,ZN); yylval->val = x; return y; }
+ yylval = nn(ZN,0,ZN,ZN); \
+ yylval->val = x; \
+ last_token = y; \
+ return y; \
+ }
#define SymToken(x, y) { if (in_comment) goto again; \
- yylval = nn(ZN,0,ZN,ZN); yylval->sym = x; return y; }
-#else
-#define Token(y) { yylval = nn(ZN,0,ZN,ZN); \
- if (!in_comment) return y; else goto again; }
+ yylval = nn(ZN,0,ZN,ZN); \
+ yylval->sym = x; \
+ last_token = y; \
+ return y; \
+ }
-#define ValToken(x, y) { yylval = nn(ZN,0,ZN,ZN); yylval->val = x; \
- if (!in_comment) return y; else goto again; }
+static int getinline(void);
+static void uninline(void);
-#define SymToken(x, y) { yylval = nn(ZN,0,ZN,ZN); yylval->sym = x; \
- if (!in_comment) return y; else goto again; }
-#endif
+static int PushBack;
+static int PushedBack;
+static char pushedback[4096];
-static int getinline(void);
-static void uninline(void);
+static void
+push_back(char *s)
+{
+ if (PushedBack + strlen(s) > 4094)
+ { fatal("select statement too large", 0);
+ }
+ strcat(pushedback, s);
+ PushedBack += strlen(s);
+}
-#if 1
-#define Getchar() ((Inlining<0)?getc(yyin):getinline())
-#define Ungetch(c) {if (Inlining<0) ungetc(c,yyin); else uninline(); }
-
-#else
-
static int
Getchar(void)
{ int c;
+
+ if (PushedBack > 0 && PushBack < PushedBack)
+ { c = pushedback[PushBack++];
+ if (PushBack == PushedBack)
+ { pushedback[0] = '\0';
+ PushBack = PushedBack = 0;
+ }
+ return c; /* expanded select statement */
+ }
if (Inlining<0)
- c = getc(yyin);
- else
- c = getinline();
-#if 1
- printf("<%c>", c);
+ { c = getc(yyin);
+ } else
+ { c = getinline();
+ }
+#if 0
+ if (0)
+ { printf("<%c:%d>[%d] ", c, c, Inlining);
+ } else
+ { printf("%c", c);
+ }
#endif
return c;
}
@@ -101,17 +126,27 @@
static void
Ungetch(int c)
{
+ if (PushedBack > 0 && PushBack > 0)
+ { PushBack--;
+ return;
+ }
+
if (Inlining<0)
- ungetc(c,yyin);
- else
- uninline();
-#if 1
- printf("<bs>");
-#endif
+ { ungetc(c,yyin);
+ } else
+ { uninline();
+ }
+ if (0)
+ { printf("\n<bs{%d}bs>\n", c);
+ }
}
-#endif
static int
+notdollar(int c)
+{ return (c != '$' && c != '\n');
+}
+
+static int
notquote(int c)
{ return (c != '\"' && c != '\n');
}
@@ -133,15 +168,17 @@
static void
getword(int first, int (*tst)(int))
-{ int i=0; char c;
+{ int i=0, c;
yytext[i++]= (char) first;
while (tst(c = Getchar()))
- { yytext[i++] = c;
+ { yytext[i++] = (char) c;
if (c == '\\')
- yytext[i++] = Getchar(); /* no tst */
- }
+ { c = Getchar();
+ yytext[i++] = (char) c; /* no tst */
+ } }
yytext[i] = '\0';
+
Ungetch(c);
}
@@ -150,7 +187,8 @@
{ int c;
if ((c = Getchar()) == tok)
- return ifyes;
+ { return ifyes;
+ }
Ungetch(c);
return ifno;
@@ -161,10 +199,11 @@
static void
def_inline(Symbol *s, int ln, char *ptr, char *prc, Lextok *nms)
{ IType *tmp;
- char *nw = (char *) emalloc((int) strlen(ptr)+1);
+ int cnt = 0;
+ char *nw = (char *) emalloc(strlen(ptr)+1);
strcpy(nw, ptr);
- for (tmp = seqnames; tmp; tmp = tmp->nxt)
+ for (tmp = seqnames; tmp; cnt++, tmp = tmp->nxt)
if (!strcmp(s->name, tmp->nm->name))
{ non_fatal("procedure name %s redefined",
tmp->nm->name);
@@ -179,11 +218,12 @@
tmp->cn = (Lextok *) nw;
tmp->params = nms;
if (strlen(prc) > 0)
- { tmp->prec = (char *) emalloc((int) strlen(prc)+1);
+ { tmp->prec = (char *) emalloc(strlen(prc)+1);
strcpy(tmp->prec, prc);
}
tmp->dln = ln;
tmp->dfn = Fname;
+ tmp->uiid = cnt+1; /* so that 0 means: not an inline */
tmp->nxt = seqnames;
seqnames = tmp;
}
@@ -250,6 +290,20 @@
return 0;
}
+Lextok *
+return_statement(Lextok *n)
+{
+ if (Inline_stub[Inlining]->rval)
+ { Lextok *g = nn(ZN, NAME, ZN, ZN);
+ Lextok *h = Inline_stub[Inlining]->rval;
+ g->sym = lookup("rv_");
+ return nn(h, ASGN, h, n);
+ } else
+ { fatal("return statement outside inline", (char *) 0);
+ }
+ return ZN;
+}
+
static int
getinline(void)
{ int c;
@@ -261,16 +315,20 @@
c = *Inliner[Inlining]++;
}
} else
+ {
c = *Inliner[Inlining]++;
+ }
if (c == '\0')
- { lineno = Inline_stub[Inlining]->cln;
+ {
+ lineno = Inline_stub[Inlining]->cln;
Fname = Inline_stub[Inlining]->cfn;
Inlining--;
+
#if 0
if (verbose&32)
- printf("spin: line %d, done inlining %s\n",
- lineno, Inline_stub[Inlining+1]->nm->name);
+ printf("spin: %s:%d, done inlining %s\n",
+ Fname, lineno, Inline_stub[Inlining+1]->nm->name);
#endif
return Getchar();
}
@@ -286,6 +344,16 @@
Inliner[Inlining]--;
}
+int
+is_inline(void)
+{
+ if (Inlining < 0)
+ return 0; /* i.e., not an inline */
+ if (Inline_stub[Inlining] == NULL)
+ fatal("unexpected, inline_stub not set", 0);
+ return Inline_stub[Inlining]->uiid;
+}
+
IType *
find_inline(char *s)
{ IType *tmp;
@@ -295,6 +363,7 @@
break;
if (!tmp)
fatal("cannot happen, missing inline def %s", s);
+
return tmp;
}
@@ -306,7 +375,17 @@
r->s = s; /* pointer to a data object */
r->t = t; /* size of object, or "global", or "local proctype_name" */
r->ival = ival;
+ r->lno = lineno;
+ r->fnm = Fname;
r->nxt = c_added;
+
+ if(strncmp(r->s->name, "\"unsigned unsigned", 18) == 0)
+ { int i;
+ for (i = 10; i < 18; i++)
+ { r->s->name[i] = ' ';
+ }
+ /* printf("corrected <%s>\n", r->s->name); */
+ }
c_added = r;
}
@@ -319,6 +398,8 @@
r->t = t;
r->ival = stackonly; /* abuse of name */
r->nxt = c_tracked;
+ r->fnm = Fname;
+ r->lno = lineno;
c_tracked = r;
if (stackonly != ZS)
@@ -329,36 +410,76 @@
&& strcmp(stackonly->name, "\"StackOnly\"") != 0)
non_fatal("expecting '[Un]Matched', saw %s", stackonly->name);
else
- has_stack = 1;
+ has_stack = 1; /* unmatched stack */
}
}
char *
-jump_etc(char *op)
-{ char *p = op;
+skip_white(char *p)
+{
+ if (p != NULL)
+ { while (*p == ' ' || *p == '\t')
+ p++;
+ } else
+ { fatal("bad format - 1", (char *) 0);
+ }
+ return p;
+}
- /* kludgy - try to get the type separated from the name */
+char *
+skip_nonwhite(char *p)
+{
+ if (p != NULL)
+ { while (*p != ' ' && *p != '\t')
+ p++;
+ } else
+ { fatal("bad format - 2", (char *) 0);
+ }
+ return p;
+}
- while (*p == ' ' || *p == '\t')
- p++; /* initial white space */
- while (*p != ' ' && *p != '\t')
- p++; /* type name */
- while (*p == ' ' || *p == '\t')
- p++; /* white space */
- while (*p == '*')
- p++; /* decorations */
- while (*p == ' ' || *p == '\t')
- p++; /* white space */
+static char *
+jump_etc(C_Added *r)
+{ char *op = r->s->name;
+ char *p = op;
+ char *q = (char *) 0;
+ int oln = lineno;
+ Symbol *ofnm = Fname;
+ /* try to get the type separated from the name */
+ lineno = r->lno;
+ Fname = r->fnm;
+
+ p = skip_white(p); /* initial white space */
+
+ if (strncmp(p, "enum", strlen("enum")) == 0) /* special case: a two-part typename */
+ { p += strlen("enum")+1;
+ p = skip_white(p);
+ }
+ if (strncmp(p, "unsigned", strlen("unsigned")) == 0) /* possibly a two-part typename */
+ { p += strlen("unsigned")+1;
+ q = p = skip_white(p);
+ }
+ p = skip_nonwhite(p); /* type name */
+ p = skip_white(p); /* white space */
+ while (*p == '*') p++; /* decorations */
+ p = skip_white(p); /* white space */
+
if (*p == '\0')
- fatal("c_state format (%s)", op);
+ { if (q)
+ { p = q; /* unsigned with implied 'int' */
+ } else
+ { fatal("c_state format (%s)", op);
+ } }
- if (strchr(p, '[')
- && !strchr(p, '{'))
+ if (strchr(p, '[') && !strchr(p, '{'))
{ non_fatal("array initialization error, c_state (%s)", p);
- return (char *) 0;
+ p = (char *) 0;
}
+ lineno = oln;
+ Fname = ofnm;
+
return p;
}
@@ -379,7 +500,7 @@
if (*q == '\\')
*q++ = ' '; /* skip over the next */
}
- p = jump_etc(r->s->name); /* e.g., "int **q" */
+ p = jump_etc(r); /* e.g., "int **q" */
if (p)
fprintf(fd, " now.%s = %s;\n", p, r->ival->name);
@@ -391,7 +512,7 @@
if (*q == '\\')
*q++ = ' '; /* skip over the next */
}
- p = jump_etc(r->s->name); /* e.g., "int **q" */
+ p = jump_etc(r); /* e.g., "int **q" */
if (p)
fprintf(fd, " %s = %s;\n", p, r->ival->name); /* no now. prefix */
@@ -413,7 +534,7 @@
if (*q == '\"')
*q = ' ';
- p = jump_etc(r->s->name); /* e.g., "int **q" */
+ p = jump_etc(r); /* e.g., "int **q" */
q = r->t->name + strlen(" Local");
while (*q == ' ' || *q == '\t')
@@ -435,9 +556,9 @@
}
if (p)
- fprintf(fd, " ((P%d *)this)->%s = %s;\n",
- tpnr, p, r->ival->name);
-
+ { fprintf(fd, "\t\t((P%d *)this)->%s = %s;\n",
+ tpnr, p, r->ival->name);
+ }
}
fprintf(fd, "}\n");
}
@@ -514,32 +635,38 @@
}
void
-c_add_stack(FILE *fd)
+c_stack_size(FILE *fd)
{ C_Added *r;
int cnt = 0;
- if ((!c_added && !c_tracked) || !has_stack) return;
-
-
for (r = c_tracked; r; r = r->nxt)
if (r->ival != ZS)
+ { fprintf(fd, "%s%s",
+ (cnt==0)?"":"+", r->t->name);
cnt++;
+ }
+ if (cnt == 0)
+ { fprintf(fd, "WS");
+ }
+}
- if (cnt == 0) return;
+void
+c_add_stack(FILE *fd)
+{ C_Added *r;
+ int cnt = 0;
- fprintf(fd, " uchar c_stack[");
+ if ((!c_added && !c_tracked) || !has_stack)
+ { return;
+ }
- cnt = 0;
for (r = c_tracked; r; r = r->nxt)
- { if (r->ival == ZS) continue;
+ if (r->ival != ZS)
+ { cnt++;
+ }
- fprintf(fd, "%s%s",
- (cnt==0)?"":"+", r->t->name);
- cnt++;
+ if (cnt > 0)
+ { fprintf(fd, " uchar c_stack[StackSize];\n");
}
-
- if (cnt == 0) fprintf(fd, "WS"); /* can't happen */
- fprintf(fd, "];\n");
}
void
@@ -568,6 +695,7 @@
for (r = c_added; r; r = r->nxt) /* pickup local decls */
if (strncmp(r->t->name, " Local", strlen(" Local")) == 0)
{ p = r->t->name + strlen(" Local");
+fprintf(fd, "/* XXX p=<%s>, s=<%s>, buf=<%s> r->s->name=<%s>XXX */\n", p, s, buf, r->s->name);
while (*p == ' ' || *p == '\t')
p++;
if (strcmp(p, buf) == 0)
@@ -578,7 +706,7 @@
c_add_def(FILE *fd) /* 3 - called in plunk_c_fcts() */
{ C_Added *r;
- fprintf(fd, "#if defined(C_States) && defined(HAS_TRACK)\n");
+ fprintf(fd, "#if defined(C_States) && (HAS_TRACK==1)\n");
for (r = c_added; r; r = r->nxt)
{ r->s->name[strlen(r->s->name)-1] = ' ';
r->s->name[0] = ' '; /* remove the "s */
@@ -610,9 +738,10 @@
}
if (has_stack)
- { fprintf(fd, "void\nc_stack(uchar *p_t_r)\n{\n");
+ { fprintf(fd, "int cpu_printf(const char *, ...);\n");
+ fprintf(fd, "void\nc_stack(uchar *p_t_r)\n{\n");
fprintf(fd, "#ifdef VERBOSE\n");
- fprintf(fd, " printf(\"c_stack %%u\\n\", p_t_r);\n");
+ fprintf(fd, " cpu_printf(\"c_stack %%u\\n\", p_t_r);\n");
fprintf(fd, "#endif\n");
for (r = c_tracked; r; r = r->nxt)
{ if (r->ival == ZS) continue;
@@ -630,7 +759,7 @@
fprintf(fd, "void\nc_update(uchar *p_t_r)\n{\n");
fprintf(fd, "#ifdef VERBOSE\n");
- fprintf(fd, " printf(\"c_update %%u\\n\", p_t_r);\n");
+ fprintf(fd, " printf(\"c_update %%p\\n\", p_t_r);\n");
fprintf(fd, "#endif\n");
for (r = c_added; r; r = r->nxt)
{ if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0
@@ -660,7 +789,7 @@
if (has_stack)
{ fprintf(fd, "void\nc_unstack(uchar *p_t_r)\n{\n");
fprintf(fd, "#ifdef VERBOSE\n");
- fprintf(fd, " printf(\"c_unstack %%u\\n\", p_t_r);\n");
+ fprintf(fd, " cpu_printf(\"c_unstack %%u\\n\", p_t_r);\n");
fprintf(fd, "#endif\n");
for (r = c_tracked; r; r = r->nxt)
{ if (r->ival == ZS) continue;
@@ -675,7 +804,7 @@
fprintf(fd, "void\nc_revert(uchar *p_t_r)\n{\n");
fprintf(fd, "#ifdef VERBOSE\n");
- fprintf(fd, " printf(\"c_revert %%u\\n\", p_t_r);\n");
+ fprintf(fd, " printf(\"c_revert %%p\\n\", p_t_r);\n");
fprintf(fd, "#endif\n");
for (r = c_added; r; r = r->nxt)
{ if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0
@@ -708,11 +837,13 @@
plunk_reverse(fd, p->nxt, matchthis);
if (!p->nm->context
- && p->nm->type == matchthis)
+ && p->nm->type == matchthis
+ && p->is_expr == 0)
{ fprintf(fd, "\n/* start of %s */\n", p->nm->name);
z = (char *) p->cn;
while (*z == '\n' || *z == '\r' || *z == '\\')
- z++;
+ { z++;
+ }
/* e.g.: \#include "..." */
y = z;
@@ -772,14 +903,28 @@
} }
}
+extern short terse;
+extern short nocast;
+
void
plunk_expr(FILE *fd, char *s)
{ IType *tmp;
+ char *q;
tmp = find_inline(s);
check_inline(tmp);
- fprintf(fd, "%s", (char *) tmp->cn);
+ if (terse && nocast)
+ { for (q = (char *) tmp->cn; q && *q != '\0'; q++)
+ { fflush(fd);
+ if (*q == '"')
+ { fprintf(fd, "\\");
+ }
+ fprintf(fd, "%c", *q);
+ }
+ } else
+ { fprintf(fd, "%s", (char *) tmp->cn);
+ }
}
void
@@ -791,9 +936,11 @@
{ tmp = find_inline(n->sym->name);
if (tmp->prec)
{ fprintf(fd, "if (!(%s)) { if (!readtrail) { depth++; ", tmp->prec);
- fprintf(fd, "trpt++; trpt->pr = II; trpt->o_t = t;");
- fprintf(fd, "trpt->st = tt; Uerror(\"%s\"); } ", tmp->prec);
- fprintf(fd, "else { printf(\"pan: precondition false: %s\\n\"); ", tmp->prec);
+ fprintf(fd, "trpt++; trpt->pr = II; trpt->o_t = t; trpt->st = tt; ");
+ fprintf(fd, "uerror(\"c_expr line %d precondition false: %s\"); continue;",
+ tmp->dln, tmp->prec);
+ fprintf(fd, " } else { printf(\"pan: precondition false: %s\\n\"); ",
+ tmp->prec);
fprintf(fd, "_m = 3; goto P999; } } \n\t\t");
}
} else
@@ -813,8 +960,25 @@
|| strchr(bdy, '(') > bdy); /* possible C-function call */
}
+char *
+put_inline(FILE *fd, char *s)
+{ IType *tmp;
+
+ tmp = find_inline(s);
+ check_inline(tmp);
+ return (char *) tmp->cn;
+}
+
void
-plunk_inline(FILE *fd, char *s, int how) /* c_code with precondition */
+mark_last(void)
+{
+ if (seqnames)
+ { seqnames->is_expr = 1;
+ }
+}
+
+void
+plunk_inline(FILE *fd, char *s, int how, int gencode) /* c_code with precondition */
{ IType *tmp;
tmp = find_inline(s);
@@ -822,16 +986,32 @@
fprintf(fd, "{ ");
if (how && tmp->prec)
- { fprintf(fd, "if (!(%s)) { if (!readtrail) { depth++; ", tmp->prec);
- fprintf(fd, "trpt++; trpt->pr = II; trpt->o_t = t;");
- fprintf(fd, "trpt->st = tt; Uerror(\"%s\"); } ", tmp->prec);
- fprintf(fd, "else { printf(\"pan: precondition false: %s\\n\"); ", tmp->prec);
- fprintf(fd, "_m = 3; goto P999; } } ");
+ { fprintf(fd, "if (!(%s)) { if (!readtrail) {",
+ tmp->prec);
+ fprintf(fd, " uerror(\"c_code line %d precondition false: %s\"); continue; ",
+ tmp->dln,
+ tmp->prec);
+ fprintf(fd, "} else { ");
+ fprintf(fd, "printf(\"pan: precondition false: %s\\n\"); _m = 3; goto P999; } } ",
+ tmp->prec);
}
+
+ if (!gencode) /* not in d_step */
+ { fprintf(fd, "\n\t\tsv_save();");
+ }
+
fprintf(fd, "%s", (char *) tmp->cn);
fprintf(fd, " }\n");
}
+int
+side_scan(char *t, char *pat)
+{ char *r = strstr(t, pat);
+ return (r
+ && *(r-1) != '"'
+ && *(r-1) != '\'');
+}
+
void
no_side_effects(char *s)
{ IType *tmp;
@@ -845,9 +1025,9 @@
tmp = find_inline(s);
t = (char *) tmp->cn;
- if (strchr(t, ';')
- || strstr(t, "++")
- || strstr(t, "--"))
+ if (side_scan(t, ";")
+ || side_scan(t, "++")
+ || side_scan(t, "--"))
{
bad: lineno = tmp->dln;
Fname = tmp->dfn;
@@ -857,8 +1037,10 @@
while ((t = strchr(t, '=')) != NULL)
{ if (*(t-1) == '!'
|| *(t-1) == '>'
- || *(t-1) == '<')
- { t++;
+ || *(t-1) == '<'
+ || *(t-1) == '"'
+ || *(t-1) == '\'')
+ { t += 2;
continue;
}
t++;
@@ -869,16 +1051,16 @@
}
void
-pickup_inline(Symbol *t, Lextok *apars)
+pickup_inline(Symbol *t, Lextok *apars, Lextok *rval)
{ IType *tmp; Lextok *p, *q; int j;
tmp = find_inline(t->name);
if (++Inlining >= MAXINL)
- fatal("inline fcts too deeply nested", 0);
-
+ fatal("inlines nested too deeply", 0);
tmp->cln = lineno; /* remember calling point */
tmp->cfn = Fname; /* and filename */
+ tmp->rval = rval;
for (p = apars, q = tmp->params, j = 0; p && q; p = p->rgt, q = q->rgt)
j++; /* count them */
@@ -887,7 +1069,7 @@
tmp->anms = (char **) emalloc(j * sizeof(char *));
for (p = apars, j = 0; p; p = p->rgt, j++)
- { tmp->anms[j] = (char *) emalloc((int) strlen(IArg_cont[j])+1);
+ { tmp->anms[j] = (char *) emalloc(strlen(IArg_cont[j])+1);
strcpy(tmp->anms[j], IArg_cont[j]);
}
@@ -897,14 +1079,18 @@
Inline_stub[Inlining] = tmp;
#if 0
if (verbose&32)
- printf("spin: line %d, file %s, inlining '%s' (from line %d, file %s)\n",
- tmp->cln, tmp->cfn->name, t->name, tmp->dln, tmp->dfn->name);
+ printf("spin: %s:%d, inlining '%s' (from %s:%d)\n",
+ tmp->cfn->name, tmp->cln, t->name, tmp->dfn->name, tmp->dln);
#endif
for (j = 0; j < Inlining; j++)
- if (Inline_stub[j] == Inline_stub[Inlining])
- fatal("cyclic inline attempt on: %s", t->name);
+ { if (Inline_stub[j] == Inline_stub[Inlining])
+ { fatal("cyclic inline attempt on: %s", t->name);
+ } }
+ last_token = SEMI; /* avoid insertion of extra semi */
}
+extern int pp_mode;
+
static void
do_directive(int first)
{ int c = first; /* handles lines starting with pound */
@@ -930,13 +1116,15 @@
fatal("malformed preprocessor directive - .fname", 0);
if ((c = Getchar()) != '\"')
- fatal("malformed preprocessor directive - .fname", 0);
+ { printf("got %c, expected \" -- lineno %d\n", c, lineno);
+ fatal("malformed preprocessor directive - .fname (%s)", yytext);
+ }
- getword(c, notquote);
+ getword(Getchar(), notquote); /* was getword(c, notquote); */
if (Getchar() != '\"')
fatal("malformed preprocessor directive - fname.", 0);
- strcat(yytext, "\"");
+ /* strcat(yytext, "\""); */
Fname = lookup(yytext);
done:
while (Getchar() != '\n')
@@ -965,34 +1153,37 @@
break;
}
}
- fatal("cannot happen", (char *) 0);
+ fatal("cannot happen", (char *) 0); /* unreachable */
}
+
Symbol *
prep_inline(Symbol *s, Lextok *nms)
{ int c, nest = 1, dln, firstchar, cnr;
- char *p, buf[SOMETHINGBIG], buf2[RATHERSMALL];
+ char *p;
Lextok *t;
+ static char Buf1[SOMETHINGBIG], Buf2[RATHERSMALL];
static int c_code = 1;
for (t = nms; t; t = t->rgt)
if (t->lft)
{ if (t->lft->ntyp != NAME)
- fatal("bad param to inline %s", s->name);
+ fatal("bad param to inline %s", s?s->name:"--");
t->lft->sym->hidden |= 32;
}
if (!s) /* C_Code fragment */
{ s = (Symbol *) emalloc(sizeof(Symbol));
- s->name = (char *) emalloc((int) strlen("c_code")+26);
+ s->name = (char *) emalloc(strlen("c_code")+26);
sprintf(s->name, "c_code%d", c_code++);
s->context = context;
s->type = CODE_FRAG;
} else
- s->type = PREDEF;
+ { s->type = PREDEF;
+ }
- p = &buf[0];
- buf2[0] = '\0';
+ p = &Buf1[0];
+ Buf2[0] = '\0';
for (;;)
{ c = Getchar();
switch (c) {
@@ -999,7 +1190,7 @@
case '[':
if (s->type != CODE_FRAG)
goto bad;
- precondition(&buf2[0]); /* e.g., c_code [p] { r = p-r; } */
+ precondition(&Buf2[0]); /* e.g., c_code [p] { r = p-r; } */
continue;
case '{':
break;
@@ -1017,19 +1208,22 @@
dln = lineno;
if (s->type == CODE_FRAG)
{ if (verbose&32)
- sprintf(buf, "\t/* line %d %s */\n\t\t",
+ { sprintf(Buf1, "\t/* line %d %s */\n\t\t",
lineno, Fname->name);
- else
- strcpy(buf, "");
+ } else
+ { strcpy(Buf1, "");
+ }
} else
- sprintf(buf, "\n#line %d %s\n{", lineno, Fname->name);
- p += strlen(buf);
+ { sprintf(Buf1, "\n#line %d \"%s\"\n{", lineno, Fname->name);
+ }
+ p += strlen(Buf1);
firstchar = 1;
cnr = 1; /* not zero */
more:
- *p++ = c = Getchar();
- if (p - buf >= SOMETHINGBIG)
+ c = Getchar();
+ *p++ = (char) c;
+ if (p - Buf1 >= SOMETHINGBIG)
fatal("inline text too long", 0);
switch (c) {
case '\n':
@@ -1045,11 +1239,13 @@
if (--nest <= 0)
{ *p = '\0';
if (s->type == CODE_FRAG)
- *--p = '\0'; /* remove trailing '}' */
- def_inline(s, dln, &buf[0], &buf2[0], nms);
- if (firstchar && s)
- printf("%3d: %s, warning: empty inline definition (%s)\n",
+ { *--p = '\0'; /* remove trailing '}' */
+ }
+ def_inline(s, dln, &Buf1[0], &Buf2[0], nms);
+ if (firstchar)
+ { printf("%3d: %s, warning: empty inline definition (%s)\n",
dln, Fname->name, s->name);
+ }
return s; /* normal return */
}
break;
@@ -1057,30 +1253,240 @@
if (cnr == 0)
{ p--;
do_directive(c); /* reads to newline */
- break;
- } /* else fall through */
- default:
- firstchar = 0;
+ } else
+ { firstchar = 0;
+ cnr++;
+ }
+ break;
case '\t':
case ' ':
case '\f':
cnr++;
break;
+ case '"':
+ do {
+ c = Getchar();
+ *p++ = (char) c;
+ if (c == '\\')
+ { *p++ = (char) Getchar();
+ }
+ if (p - Buf1 >= SOMETHINGBIG)
+ { fatal("inline text too long", 0);
+ }
+ } while (c != '"'); /* end of string */
+ /* *p = '\0'; */
+ break;
+ case '\'':
+ c = Getchar();
+ *p++ = (char) c;
+ if (c == '\\')
+ { *p++ = (char) Getchar();
+ }
+ c = Getchar();
+ *p++ = (char) c;
+ assert(c == '\'');
+ break;
+ default:
+ firstchar = 0;
+ cnr++;
+ break;
}
goto more;
}
+static void
+set_cur_scope(void)
+{ int i;
+ char tmpbuf[256];
+
+ strcpy(CurScope, "_");
+
+ if (context)
+ for (i = 0; i < scope_level; i++)
+ { sprintf(tmpbuf, "%d_", scope_seq[i]);
+ strcat(CurScope, tmpbuf);
+ }
+}
+
static int
+pre_proc(void)
+{ char b[512];
+ int c, i = 0;
+
+ b[i++] = '#';
+ while ((c = Getchar()) != '\n' && c != EOF)
+ { b[i++] = (char) c;
+ }
+ b[i] = '\0';
+ yylval = nn(ZN, 0, ZN, ZN);
+ yylval->sym = lookup(b);
+ return PREPROC;
+}
+
+static int specials[] = {
+ '}', ')', ']',
+ OD, FI, ELSE, BREAK,
+ C_CODE, C_EXPR, C_DECL,
+ NAME, CONST, INCR, DECR, 0
+};
+
+int
+follows_token(int c)
+{ int i;
+
+ for (i = 0; specials[i]; i++)
+ { if (c == specials[i])
+ { return 1;
+ } }
+ return 0;
+}
+#define DEFER_LTL
+#ifdef DEFER_LTL
+/* defer ltl formula to the end of the spec
+ * no matter where they appear in the original
+ */
+
+static int deferred = 0;
+static FILE *defer_fd;
+
+int
+get_deferred(void)
+{
+ if (!defer_fd)
+ { return 0; /* nothing was deferred */
+ }
+ fclose(defer_fd);
+
+ defer_fd = fopen(TMP_FILE2, "r");
+ if (!defer_fd)
+ { non_fatal("cannot retrieve deferred ltl formula", (char *) 0);
+ return 0;
+ }
+ fclose(yyin);
+ yyin = defer_fd;
+ return 1;
+}
+
+void
+zap_deferred(void)
+{
+ (void) unlink(TMP_FILE2);
+}
+
+int
+put_deferred(void)
+{ int c, cnt;
+ if (!defer_fd)
+ { defer_fd = fopen(TMP_FILE2, "w+");
+ if (!defer_fd)
+ { non_fatal("cannot defer ltl expansion", (char *) 0);
+ return 0;
+ } }
+ fprintf(defer_fd, "ltl ");
+ cnt = 0;
+ while ((c = getc(yyin)) != EOF)
+ { if (c == '{')
+ { cnt++;
+ }
+ if (c == '}')
+ { cnt--;
+ if (cnt == 0)
+ { break;
+ } }
+ fprintf(defer_fd, "%c", c);
+ }
+ fprintf(defer_fd, "}\n");
+ fflush(defer_fd);
+ return 1;
+}
+#endif
+
+#define EXPAND_SELECT
+#ifdef EXPAND_SELECT
+static char tmp_hold[256];
+static int tmp_has;
+
+void
+new_select(void)
+{ tmp_hold[0] = '\0';
+ tmp_has = 0;
+}
+
+int
+scan_to(int stop, int (*tst)(int), char *buf)
+{ int c, i = 0;
+
+ do { c = Getchar();
+ if (tmp_has < sizeof(tmp_hold))
+ { tmp_hold[tmp_has++] = c;
+ }
+ if (c == '\n')
+ { lineno++;
+ } else if (buf)
+ { buf[i++] = c;
+ }
+ if (tst && !tst(c) && c != ' ' && c != '\t')
+ { break;
+ }
+ } while (c != stop && c != EOF);
+
+ if (buf)
+ { buf[i-1] = '\0';
+ }
+
+ if (c != stop)
+ { if (0)
+ { printf("saw: '%c', expected '%c'\n", c, stop);
+ }
+ if (tmp_has < sizeof(tmp_hold))
+ { tmp_hold[tmp_has] = '\0';
+ push_back(tmp_hold);
+ if (0)
+ { printf("pushed back: <'%s'>\n", tmp_hold);
+ }
+ return 0; /* internal expansion fails */
+ } else
+ { fatal("expecting select ( name : constant .. constant )", 0);
+ } }
+ return 1; /* success */
+}
+#endif
+
+int
lex(void)
{ int c;
-
again:
c = Getchar();
yytext[0] = (char) c;
yytext[1] = '\0';
switch (c) {
+ case EOF:
+#ifdef DEFER_LTL
+ if (!deferred)
+ { deferred = 1;
+ if (get_deferred())
+ { goto again;
+ }
+ } else
+ { zap_deferred();
+ }
+#endif
+ return c;
case '\n': /* newline */
lineno++;
+ /* make most semi-colons optional */
+ if (implied_semis
+ /* && context */
+ && in_seq
+ && par_cnt == 0
+ && follows_token(last_token))
+ { if (0)
+ { printf("insert ; line %d, last_token %d in_seq %d\n",
+ lineno-1, last_token, in_seq);
+ }
+ ValToken(1, SEMI);
+ }
+ /* else fall thru */
case '\r': /* carriage return */
goto again;
@@ -1089,6 +1495,10 @@
case '#': /* preprocessor directive */
if (in_comment) goto again;
+ if (pp_mode)
+ { last_token = PREPROC;
+ return pre_proc();
+ }
do_directive(c);
goto again;
@@ -1099,6 +1509,13 @@
strcat(yytext, "\"");
SymToken(lookup(yytext), STRING)
+ case '$':
+ getword('\"', notdollar);
+ if (Getchar() != '$')
+ fatal("ltl definition not terminated", yytext);
+ strcat(yytext, "\"");
+ SymToken(lookup(yytext), STRING)
+
case '\'': /* new 3.0.9 */
c = Getchar();
if (c == '\\')
@@ -1117,8 +1534,15 @@
}
if (isdigit_(c))
- { getword(c, isdigit_);
- ValToken(atoi(yytext), CONST)
+ { long int nr;
+ getword(c, isdigit_);
+ errno = 0;
+ nr = strtol(yytext, NULL, 10);
+ if (errno != 0)
+ { fprintf(stderr, "spin: value out of range: '%s' read as '%d'\n",
+ yytext, (int) nr);
+ }
+ ValToken((int)nr, CONST)
}
if (isalpha_(c) || c == '_')
@@ -1125,12 +1549,89 @@
{ getword(c, isalnum_);
if (!in_comment)
{ c = check_name(yytext);
- if (c) return c;
+
+#ifdef EXPAND_SELECT
+ if (c == SELECT && Inlining < 0)
+ { char name[64], from[32], upto[32];
+ int i, a, b;
+ new_select();
+ if (!scan_to('(', 0, 0)
+ || !scan_to(':', isalnum, name)
+ || !scan_to('.', isdigit, from)
+ || !scan_to('.', 0, 0)
+ || !scan_to(')', isdigit, upto))
+ { goto not_expanded;
+ }
+ a = atoi(from);
+ b = atoi(upto);
+ if (0)
+ { printf("Select %s from %d to %d\n",
+ name, a, b);
+ }
+ if (a > b)
+ { non_fatal("bad range in select statement", 0);
+ goto again;
+ }
+ if (b - a <= 32)
+ { push_back("if ");
+ for (i = a; i <= b; i++)
+ { char buf[128];
+ push_back(":: ");
+ sprintf(buf, "%s = %d ",
+ name, i);
+ push_back(buf);
+ }
+ push_back("fi ");
+ } else
+ { char buf[128];
+ sprintf(buf, "%s = %d; do ",
+ name, a);
+ push_back(buf);
+ sprintf(buf, ":: (%s < %d) -> %s++ ",
+ name, b, name);
+ push_back(buf);
+ push_back(":: break od; ");
+ }
+ goto again;
+ }
+not_expanded:
+#endif
+
+#ifdef DEFER_LTL
+ if (c == LTL && !deferred)
+ { if (put_deferred())
+ { goto again;
+ } }
+#endif
+ if (c)
+ { last_token = c;
+ return c;
+ }
/* else fall through */
}
goto again;
}
+ if (ltl_mode)
+ { switch (c) {
+ case '-': c = follow('>', IMPLIES, '-'); break;
+ case '[': c = follow(']', ALWAYS, '['); break;
+ case '<': c = follow('>', EVENTUALLY, '<');
+ if (c == '<')
+ { c = Getchar();
+ if (c == '-')
+ { c = follow('>', EQUIV, '-');
+ if (c == '-')
+ { Ungetch(c);
+ c = '<';
+ }
+ } else
+ { Ungetch(c);
+ c = '<';
+ } }
+ default: break;
+ } }
+
switch (c) {
case '/': c = follow('*', 0, '/');
if (!c) { in_comment = 1; goto again; }
@@ -1139,7 +1640,7 @@
if (!c) { in_comment = 0; goto again; }
break;
case ':': c = follow(':', SEP, ':'); break;
- case '-': c = follow('>', SEMI, follow('-', DECR, '-')); break;
+ case '-': c = follow('>', ARROW, follow('-', DECR, '-')); break;
case '+': c = follow('+', INCR, '+'); break;
case '<': c = follow('<', LSHIFT, follow('=', LE, LT)); break;
case '>': c = follow('>', RSHIFT, follow('=', GE, GT)); break;
@@ -1149,12 +1650,35 @@
case '&': c = follow('&', AND, '&'); break;
case '|': c = follow('|', OR, '|'); break;
case ';': c = SEMI; break;
+ case '.': c = follow('.', DOTDOT, '.'); break;
+ case '{': scope_seq[scope_level++]++; set_cur_scope(); break;
+ case '}': scope_level--; set_cur_scope(); break;
default : break;
}
- Token(c)
+ ValToken(0, c)
}
static struct {
+ char *s; int tok;
+} LTL_syms[] = {
+ /* [], <>, ->, and <-> are intercepted in lex() */
+ { "U", UNTIL },
+ { "V", RELEASE },
+ { "W", WEAK_UNTIL },
+ { "X", NEXT },
+ { "always", ALWAYS },
+ { "eventually", EVENTUALLY },
+ { "until", UNTIL },
+ { "stronguntil",UNTIL },
+ { "weakuntil", WEAK_UNTIL },
+ { "release", RELEASE },
+ { "next", NEXT },
+ { "implies", IMPLIES },
+ { "equivalent", EQUIV },
+ { 0, 0 },
+};
+
+static struct {
char *s; int tok; int val; char *sym;
} Names[] = {
{"active", ACTIVE, 0, 0},
@@ -1178,14 +1702,19 @@
{"eval", EVAL, 0, 0},
{"false", CONST, 0, 0},
{"fi", FI, 0, 0},
+ {"for", FOR, 0, 0},
{"full", FULL, 0, 0},
+ {"get_priority", GET_P, 0, 0},
{"goto", GOTO, 0, 0},
{"hidden", HIDDEN, 0, ":hide:"},
{"if", IF, 0, 0},
+ {"in", IN, 0, 0},
{"init", INIT, 0, ":init:"},
+ {"inline", INLINE, 0, 0},
{"int", TYPE, INT, 0},
{"len", LEN, 0, 0},
{"local", ISLOCAL, 0, ":local:"},
+ {"ltl", LTL, 0, ":ltl:"},
{"mtype", TYPE, MTYPE, 0},
{"nempty", NEMPTY, 0, 0},
{"never", CLAIM, 0, ":never:"},
@@ -1201,9 +1730,11 @@
{"priority", PRIORITY, 0, 0},
{"proctype", PROCTYPE, 0, 0},
{"provided", PROVIDED, 0, 0},
+ {"return", RETURN, 0, 0},
{"run", RUN, 0, 0},
{"d_step", D_STEP, 0, 0},
- {"inline", INLINE, 0, 0},
+ {"select", SELECT, 0, 0},
+ {"set_priority", SET_P, 0, 0},
{"short", TYPE, SHORT, 0},
{"skip", CONST, 1, 0},
{"timeout", TIMEOUT, 0, 0},
@@ -1223,13 +1754,23 @@
{ int i;
yylval = nn(ZN, 0, ZN, ZN);
+
+ if (ltl_mode)
+ { for (i = 0; LTL_syms[i].s; i++)
+ { if (strcmp(s, LTL_syms[i].s) == 0)
+ { return LTL_syms[i].tok;
+ } } }
+
for (i = 0; Names[i].s; i++)
- if (strcmp(s, Names[i].s) == 0)
+ { if (strcmp(s, Names[i].s) == 0)
{ yylval->val = Names[i].val;
if (Names[i].sym)
yylval->sym = lookup(Names[i].sym);
+ if (Names[i].tok == IN && !in_for)
+ { continue;
+ }
return Names[i].tok;
- }
+ } }
if ((yylval->val = ismtype(s)) != 0)
{ yylval->ismtyp = 1;
@@ -1239,6 +1780,9 @@
if (strcmp(s, "_last") == 0)
has_last++;
+ if (strcmp(s, "_priority") == 0)
+ has_priority++;
+
if (Inlining >= 0 && !ReDiRect)
{ Lextok *tt, *t = Inline_stub[Inlining]->params;
@@ -1253,19 +1797,29 @@
Inline_stub[Inlining]->nm->name,
Inline_stub[Inlining]->anms[i]);
#endif
-
for (tt = Inline_stub[Inlining]->params; tt; tt = tt->rgt)
if (!strcmp(Inline_stub[Inlining]->anms[i],
tt->lft->sym->name))
{ /* would be cyclic if not caught */
- printf("spin: line %d replacement value: %s\n",
- lineno, tt->lft->sym->name);
- fatal("formal par of %s matches replacement value",
+ printf("spin: %s:%d replacement value: %s\n",
+ oFname->name?oFname->name:"--", lineno, tt->lft->sym->name);
+ fatal("formal par of %s contains replacement value",
Inline_stub[Inlining]->nm->name);
yylval->ntyp = tt->lft->ntyp;
yylval->sym = lookup(tt->lft->sym->name);
return NAME;
}
+
+ /* check for occurrence of param as field of struct */
+ { char *ptr = Inline_stub[Inlining]->anms[i];
+ while ((ptr = strstr(ptr, s)) != NULL)
+ { if (*(ptr-1) == '.'
+ || *(ptr+strlen(s)) == '.')
+ { fatal("formal par of %s used in structure name",
+ Inline_stub[Inlining]->nm->name);
+ }
+ ptr++;
+ } }
ReDiRect = Inline_stub[Inlining]->anms[i];
return 0;
} }
@@ -1293,13 +1847,16 @@
if (hold)
{ c = hold;
hold = 0;
+ last_token = c;
} else
{ c = lex();
if (last == ELSE
&& c != SEMI
+ && c != ARROW
&& c != FI)
{ hold = c;
last = 0;
+ last_token = SEMI;
return SEMI;
}
if (last == '}'
@@ -1312,12 +1869,14 @@
&& c != '}'
&& c != UNLESS
&& c != SEMI
+ && c != ARROW
&& c != EOF)
{ hold = c;
last = 0;
+ last_token = SEMI;
return SEMI; /* insert ';' */
}
- if (c == SEMI)
+ if (c == SEMI || c == ARROW)
{ /* if context, we're not in a typedef
* because they're global.
* if owner, we're at the end of a ref
@@ -1328,6 +1887,7 @@
if (context) owner = ZS;
hold = lex(); /* look ahead */
if (hold == '}'
+ || hold == ARROW
|| hold == SEMI)
{ c = hold; /* omit ';' */
hold = 0;
@@ -1346,16 +1906,26 @@
{ IArgno = 0;
IArg_cont[0][0] = '\0';
} else
+ { assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
strcat(IArg_cont[IArgno], yytext);
+ }
} else if (strcmp(yytext, ")") == 0)
{ if (--IArg_nst > 0)
+ { assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
strcat(IArg_cont[IArgno], yytext);
+ }
} else if (c == CONST && yytext[0] == '\'')
{ sprintf(yytext, "'%c'", yylval->val);
+ assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
strcat(IArg_cont[IArgno], yytext);
+ } else if (c == CONST)
+ { sprintf(yytext, "%d", yylval->val);
+ assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
+ strcat(IArg_cont[IArgno], yytext);
} else
{
switch (c) {
+ case ARROW: strcpy(yytext, "->"); break; /* NEW */
case SEP: strcpy(yytext, "::"); break;
case SEMI: strcpy(yytext, ";"); break;
case DECR: strcpy(yytext, "--"); break;
@@ -1376,9 +1946,9 @@
case AND: strcpy(yytext, "&&"); break;
case OR: strcpy(yytext, "||"); break;
}
+ assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
strcat(IArg_cont[IArgno], yytext);
}
}
-
return c;
}
--- a/sys/src/cmd/spin/structs.c
+++ b/sys/src/cmd/spin/structs.c
@@ -1,13 +1,10 @@
/***** spin: structs.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include "spin.h"
#include "y.tab.h"
@@ -19,7 +16,7 @@
} UType;
extern Symbol *Fname;
-extern int lineno, depth, Expand_Ok;
+extern int lineno, depth, Expand_Ok, has_hidden, in_for;
Symbol *owner;
@@ -33,6 +30,9 @@
setuname(Lextok *n)
{ UType *tmp;
+ if (!owner)
+ fatal("illegal reference inside typedef", (char *) 0);
+
for (tmp = Unames; tmp; tmp = tmp->nxt)
if (!strcmp(owner->name, tmp->nm->name))
{ non_fatal("typename %s was defined before",
@@ -39,8 +39,7 @@
tmp->nm->name);
return;
}
- if (!owner) fatal("illegal reference inside typedef",
- (char *) 0);
+
tmp = (UType *) emalloc(sizeof(UType));
tmp->nm = owner;
tmp->cn = n;
@@ -102,21 +101,22 @@
{ lineno = n->ln;
Fname = n->fn;
if (n->sym->type)
- non_fatal("redeclaration of '%s'", n->sym->name);
+ fatal("redeclaration of '%s'", n->sym->name);
if (n->sym->nbits > 0)
- non_fatal("(%s) only an unsigned can have width-field",
- n->sym->name);
+ non_fatal("(%s) only an unsigned can have width-field",
+ n->sym->name);
if (Expand_Ok)
n->sym->hidden |= (4|8|16); /* formal par */
if (vis)
- { if (strncmp(vis->sym->name, ":hide:", 6) == 0)
- n->sym->hidden |= 1;
- else if (strncmp(vis->sym->name, ":show:", 6) == 0)
+ { if (strncmp(vis->sym->name, ":hide:", (size_t) 6) == 0)
+ { n->sym->hidden |= 1;
+ has_hidden++;
+ } else if (strncmp(vis->sym->name, ":show:", (size_t) 6) == 0)
n->sym->hidden |= 2;
- else if (strncmp(vis->sym->name, ":local:", 7) == 0)
+ else if (strncmp(vis->sym->name, ":local:", (size_t) 7) == 0)
n->sym->hidden |= 64;
}
n->sym->type = STRUCT; /* classification */
@@ -196,6 +196,7 @@
fatal("non-zero 'rgt' on non-structure", 0);
ix = eval(tmp->lft);
+/* printf("%d: ix: %d (%d) %d\n", depth, ix, tl->nel, tl->val[ix]); */
if (ix >= tl->nel || ix < 0)
fatal("indexing error \'%s\'", tl->name);
@@ -222,10 +223,12 @@
fatal("indexing error \'%s\'", tl->name);
if (tl->nbits > 0)
- a = (a & ((1<<tl->nbits)-1));
- tl->val[ix] = a;
- tl->setat = depth;
+ a = (a & ((1<<tl->nbits)-1));
+ if (a != tl->val[ix])
+ { tl->val[ix] = a;
+ tl->setat = depth;
+ }
return 1;
}
@@ -246,7 +249,7 @@
for (fp = n; fp; fp = fp->rgt)
for (tl = fp->lft; tl; tl = tl->rgt)
{ if (tl->sym->type == STRUCT)
- { if (tl->sym->nel != 1)
+ { if (tl->sym->nel > 1 || tl->sym->isarray)
fatal("array of structures in param list, %s",
tl->sym->name);
cnt += Cnt_flds(tl->sym->Slst);
@@ -266,9 +269,9 @@
return s->type;
if (!t->rgt
- || !t->rgt->ntyp == '.'
+ || t->rgt->ntyp != '.' /* gh: had ! in wrong place */
|| !t->rgt->lft)
- return STRUCT; /* not a field reference */
+ return STRUCT; /* not a field reference */
return Sym_typ(t->rgt->lft);
}
@@ -315,6 +318,7 @@
if (!s) return ZN;
d = (Lextok *) emalloc(sizeof(Lextok));
+ d->uiid = s->uiid;
d->ntyp = s->ntyp;
d->val = s->val;
d->ln = s->ln;
@@ -353,7 +357,7 @@
goto out;
}
fprintf(fd, ".%s", tl->name);
-out: if (tmp->sym->nel > 1)
+out: if (tmp->sym->nel > 1 || tmp->sym->isarray == 1)
{ fprintf(fd, "[%d]", eval(tmp->lft));
hiddenarrays = 1;
}
@@ -391,7 +395,7 @@
}
sprintf(lbuf, ".%s", tl->name);
strcat(buf, lbuf);
- if (tmp->sym->nel > 1)
+ if (tmp->sym->nel > 1 || tmp->sym->isarray == 1)
{ sprintf(lbuf, "[%d]", eval(tmp->lft));
strcat(buf, lbuf);
}
@@ -405,10 +409,10 @@
extern void Done_case(char *, Symbol *);
ini_struct(z);
- if (z->nel == 1)
+ if (z->nel == 1 && z->isarray == 0)
sprintf(eprefix, "%s%s.", s, z->name);
for (ix = 0; ix < z->nel; ix++)
- { if (z->nel > 1)
+ { if (z->nel > 1 || z->isarray == 1)
sprintf(eprefix, "%s%s[%d].", s, z->name, ix);
for (fp = z->Sval[ix]; fp; fp = fp->rgt)
for (tl = fp->lft; tl; tl = tl->rgt)
@@ -426,10 +430,10 @@
int ix;
ini_struct(z);
- if (z->nel == 1)
+ if (z->nel == 1 && z->isarray == 0)
sprintf(eprefix, "%s%s.", s, z->name);
for (ix = 0; ix < z->nel; ix++)
- { if (z->nel > 1)
+ { if (z->nel > 1 || z->isarray == 1)
sprintf(eprefix, "%s%s[%d].", s, z->name, ix);
for (fp = z->Sval[ix]; fp; fp = fp->rgt)
for (tl = fp->lft; tl; tl = tl->rgt)
@@ -443,7 +447,7 @@
void
c_struct(FILE *fd, char *ipref, Symbol *z)
{ Lextok *fp, *tl;
- char pref[256], eprefix[256];
+ char pref[256], eprefix[300];
int ix;
ini_struct(z);
@@ -452,7 +456,7 @@
for (fp = z->Sval[ix]; fp; fp = fp->rgt)
for (tl = fp->lft; tl; tl = tl->rgt)
{ strcpy(eprefix, ipref);
- if (z->nel > 1)
+ if (z->nel > 1 || z->isarray == 1)
{ /* insert index before last '.' */
eprefix[strlen(eprefix)-1] = '\0';
sprintf(pref, "[ %d ].", ix);
@@ -476,7 +480,7 @@
ini_struct(z);
for (ix = 0; ix < z->nel; ix++)
- { if (z->nel > 1)
+ { if (z->nel > 1 || z->isarray == 1)
sprintf(eprefix, "%s[%d]", prefix, ix);
else
strcpy(eprefix, prefix);
@@ -484,7 +488,7 @@
for (fp = z->Sval[ix]; fp; fp = fp->rgt)
for (tl = fp->lft; tl; tl = tl->rgt)
{ if (tl->sym->type == STRUCT)
- { char pref[256];
+ { char pref[300];
strcpy(pref, eprefix);
strcat(pref, ".");
strcat(pref, tl->sym->name);
@@ -498,7 +502,7 @@
if (r)
printf("%s(%d):", r->n->name, r->pid);
printf("%s.%s", eprefix, tl->sym->name);
- if (tl->sym->nel > 1)
+ if (tl->sym->nel > 1 || tl->sym->isarray == 1)
printf("[%d]", jx);
printf(" = ");
sr_mesg(stdout, tl->sym->val[jx],
@@ -579,8 +583,10 @@
int i, cnt; extern int IArgs;
if (n->sym->type != STRUCT
+ || in_for
|| is_explicit(n))
return n;
+
if (n->rgt
&& n->rgt->ntyp == '.'
--- a/sys/src/cmd/spin/sym.c
+++ b/sys/src/cmd/spin/sym.c
@@ -1,13 +1,10 @@
/***** spin: sym.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include "spin.h"
#include "y.tab.h"
@@ -14,12 +11,17 @@
extern Symbol *Fname, *owner;
extern int lineno, depth, verbose, NamesNotAdded, deadvar;
+extern int has_hidden, m_loss, old_scope_rules;
extern short has_xu;
+extern char CurScope[MAXSCOPESZ];
Symbol *context = ZS;
Ordered *all_names = (Ordered *)0;
int Nid = 0;
+Lextok *Mtype = (Lextok *) 0;
+Lextok *runstmnts = ZN;
+
static Ordered *last_name = (Ordered *)0;
static Symbol *symtab[Nhash+1];
@@ -31,12 +33,12 @@
return !strcmp(a->name, b->name);
}
-int
-hash(char *s)
-{ int h=0;
+unsigned int
+hash(const char *s)
+{ unsigned int h = 0;
while (*s)
- { h += *s++;
+ { h += (unsigned int) *s++;
h <<= 1;
if (h&(Nhash+1))
h |= 1;
@@ -44,31 +46,89 @@
return h&Nhash;
}
+void
+disambiguate(void)
+{ Ordered *walk;
+ Symbol *sp;
+ char *n, *m;
+
+ if (old_scope_rules)
+ return;
+
+ /* prepend the scope_prefix to the names */
+
+ for (walk = all_names; walk; walk = walk->next)
+ { sp = walk->entry;
+ if (sp->type != 0
+ && sp->type != LABEL
+ && strlen((const char *)sp->bscp) > 1)
+ { if (sp->context)
+ { m = (char *) emalloc(strlen((const char *)sp->bscp) + 1);
+ sprintf(m, "_%d_", sp->context->sc);
+ if (strcmp((const char *) m, (const char *) sp->bscp) == 0)
+ { continue;
+ /* 6.2.0: only prepend scope for inner-blocks,
+ not for top-level locals within a proctype
+ this means that you can no longer use the same name
+ for a global and a (top-level) local variable
+ */
+ } }
+
+ n = (char *) emalloc(strlen((const char *)sp->name)
+ + strlen((const char *)sp->bscp) + 1);
+ sprintf(n, "%s%s", sp->bscp, sp->name);
+ sp->name = n; /* discard the old memory */
+ } }
+}
+
Symbol *
lookup(char *s)
{ Symbol *sp; Ordered *no;
- int h = hash(s);
+ unsigned int h = hash(s);
- for (sp = symtab[h]; sp; sp = sp->next)
- if (strcmp(sp->name, s) == 0
- && samename(sp->context, context)
- && samename(sp->owner, owner))
- return sp; /* found */
+ if (old_scope_rules)
+ { /* same scope - global refering to global or local to local */
+ for (sp = symtab[h]; sp; sp = sp->next)
+ { if (strcmp(sp->name, s) == 0
+ && samename(sp->context, context)
+ && samename(sp->owner, owner))
+ { return sp; /* found */
+ } }
+ } else
+ { /* added 6.0.0: more traditional, scope rule */
+ for (sp = symtab[h]; sp; sp = sp->next)
+ { if (strcmp(sp->name, s) == 0
+ && samename(sp->context, context)
+ && (strcmp((const char *)sp->bscp, CurScope) == 0
+ || strncmp((const char *)sp->bscp, CurScope, strlen((const char *)sp->bscp)) == 0)
+ && samename(sp->owner, owner))
+ {
+ if (!samename(sp->owner, owner))
+ { printf("spin: different container %s\n", sp->name);
+ printf(" old: %s\n", sp->owner?sp->owner->name:"--");
+ printf(" new: %s\n", owner?owner->name:"--");
+ /* alldone(1); */
+ }
+ return sp; /* found */
+ } } }
- if (context) /* in proctype */
+ if (context) /* in proctype, refers to global */
for (sp = symtab[h]; sp; sp = sp->next)
- if (strcmp(sp->name, s) == 0
+ { if (strcmp(sp->name, s) == 0
&& !sp->context
&& samename(sp->owner, owner))
- return sp; /* global */
+ { return sp; /* global */
+ } }
sp = (Symbol *) emalloc(sizeof(Symbol));
- sp->name = (char *) emalloc((int) strlen(s) + 1);
+ sp->name = (char *) emalloc(strlen(s) + 1);
strcpy(sp->name, s);
sp->nel = 1;
sp->setat = depth;
sp->context = context;
sp->owner = owner; /* if fld in struct */
+ sp->bscp = (unsigned char *) emalloc(strlen((const char *)CurScope)+1);
+ strcpy((char *)sp->bscp, CurScope);
if (NamesNotAdded == 0)
{ sp->next = symtab[h];
@@ -109,8 +169,6 @@
}
}
-Lextok *runstmnts = ZN;
-
void
trackrun(Lextok *n)
{
@@ -151,11 +209,11 @@
strcpy(buf2, (!(res&4))?"bit":"byte");
sputtype(buf, parnm->type);
i = (int) strlen(buf);
- while (buf[--i] == ' ') buf[i] = '\0';
- if (strcmp(buf, buf2) == 0) return;
+ while (i > 0 && buf[--i] == ' ') buf[i] = '\0';
+ if (i == 0 || strcmp(buf, buf2) == 0) return;
prehint(parnm);
printf("proctype %s, '%s %s' could be declared",
- parnm->context->name, buf, parnm->name);
+ parnm->context?parnm->context->name:"", buf, parnm->name);
printf(" '%s %s'\n", buf2, parnm->name);
}
}
@@ -178,9 +236,9 @@
while (n)
{ if (n->sym->type && !(n->sym->hidden&32))
- { lineno = n->ln; Fname = n->fn;
- non_fatal("redeclaration of '%s'", n->sym->name);
- lineno = oln;
+ { lineno = n->ln; Fname = n->fn;
+ fatal("redeclaration of '%s'", n->sym->name);
+ lineno = oln;
}
n->sym->type = (short) t;
@@ -201,14 +259,15 @@
n->sym->name);
}
if (vis)
- { if (strncmp(vis->sym->name, ":hide:", 6) == 0)
+ { if (strncmp(vis->sym->name, ":hide:", (size_t) 6) == 0)
{ n->sym->hidden |= 1;
+ has_hidden++;
if (t == BIT)
fatal("bit variable (%s) cannot be hidden",
n->sym->name);
- } else if (strncmp(vis->sym->name, ":show:", 6) == 0)
+ } else if (strncmp(vis->sym->name, ":show:", (size_t) 6) == 0)
{ n->sym->hidden |= 2;
- } else if (strncmp(vis->sym->name, ":local:", 7) == 0)
+ } else if (strncmp(vis->sym->name, ":local:", (size_t) 7) == 0)
{ n->sym->hidden |= 64;
}
}
@@ -268,7 +327,13 @@
setxus(Lextok *p, int t)
{ Lextok *m, *n;
- has_xu = 1;
+ has_xu = 1;
+
+ if (m_loss && t == XS)
+ { printf("spin: %s:%d, warning, xs tag not compatible with -m (message loss)\n",
+ (p->fn != NULL) ? p->fn->name : "stdin", p->ln);
+ }
+
if (!context)
{ lineno = p->ln;
Fname = p->fn;
@@ -276,6 +341,7 @@
}
for (m = p; m; m = m->rgt)
{ Lextok *Xu_new = (Lextok *) emalloc(sizeof(Lextok));
+ Xu_new->uiid = p->uiid;
Xu_new->val = t;
Xu_new->lft = m->lft;
Xu_new->sym = context;
@@ -297,8 +363,6 @@
}
}
-Lextok *Mtype = (Lextok *) 0;
-
void
setmtype(Lextok *m)
{ Lextok *n;
@@ -332,7 +396,7 @@
}
lineno = oln;
if (cnt > 256)
- fatal("too many mtype elements (>255)", (char *)0);
+ fatal("too many mtype elements (>255)", (char *)0);
}
int
@@ -389,11 +453,11 @@
printf("\t");
if (sp->owner) printf("%s.", sp->owner->name);
printf("%s", sp->name);
- if (sp->nel > 1) printf("[%d]", sp->nel);
+ if (sp->nel > 1 || sp->isarray == 1) printf("[%d]", sp->nel);
if (sp->type == CHAN)
printf("\t%d", (sp->ini)?sp->ini->val:0);
- else if (sp->type == STRUCT) /* Frank Weil, 2.9.8 */
+ else if (sp->type == STRUCT && sp->Snm != NULL) /* Frank Weil, 2.9.8 */
printf("\t%s", sp->Snm->name);
else
printf("\t%d", eval(sp->ini));
@@ -408,8 +472,13 @@
if (sp->Nid < 0) /* formal parameter */
printf("\t<parameter %d>", -(sp->Nid));
+ else if (sp->type == MTYPE)
+ printf("\t<constant>");
+ else if (sp->isarray)
+ printf("\t<array>");
else
printf("\t<variable>");
+
if (sp->type == CHAN && sp->ini)
{ int i;
for (m = sp->ini->rgt, i = 0; m; m = m->rgt)
@@ -423,6 +492,11 @@
if (m->rgt) printf("\t");
}
}
+
+ if (!old_scope_rules)
+ { printf("\t{scope %s}", sp->bscp);
+ }
+
printf("\n");
}
@@ -440,11 +514,10 @@
if (sp->context) printf("%s-", sp->context->name);
if (sp->owner) printf("%s.", sp->owner->name);
printf("%s", sp->name);
- if (sp->nel > 1) printf("[%d]", sp->nel);
+ if (sp->nel > 1 || sp->isarray == 1) printf("[%d]", sp->nel);
printf("\t");
}
-
static struct X {
int typ; char *nm;
} xx[] = {
@@ -521,7 +594,7 @@
if (!(verbose&32) || has_code) continue;
- printf("spin: warning, %s, ", Fname->name);
+ printf("spin: %s:0, warning, ", Fname->name);
sputtype(buf, walk->entry->type);
if (walk->entry->context)
printf("proctype %s",
@@ -528,7 +601,7 @@
walk->entry->context->name);
else
printf("global");
- printf(", '%s%s' variable is never used\n",
+ printf(", '%s%s' variable is never used (other than in print stmnts)\n",
buf, walk->entry->name);
} }
}
--- a/sys/src/cmd/spin/tl.h
+++ b/sys/src/cmd/spin/tl.h
@@ -1,17 +1,14 @@
/***** tl_spin: tl.h *****/
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
-
#include <stdio.h>
#include <string.h>
@@ -66,6 +63,7 @@
#ifdef NXT
, NEXT /* 269 */
#endif
+ , CEXPR /* 270 */
};
Node *Canonical(Node *);
@@ -82,11 +80,12 @@
Symbol *getsym(Symbol *);
Symbol *DoDump(Node *);
-char *emalloc(int); /* in main.c */
+extern char *emalloc(size_t); /* in main.c */
+extern unsigned int hash(const char *); /* in sym.c */
+
int anywhere(int, Node *, Node *);
int dump_cond(Node *, Node *, int);
-int hash(char *); /* in sym.c */
int isalnum_(int); /* in spinlex.c */
int isequal(Node *, Node *);
int tl_Getchar(void);
@@ -100,6 +99,10 @@
void Fatal(char *, char *);
void fatal(char *, char *);
void fsm_print(void);
+void ini_buchi(void);
+void ini_cache(void);
+void ini_rewrt(void);
+void ini_trans(void);
void releasenode(int, Node *);
void tfree(void *);
void tl_explain(int);
--- a/sys/src/cmd/spin/tl_buchi.c
+++ b/sys/src/cmd/spin/tl_buchi.c
@@ -1,20 +1,18 @@
/***** tl_spin: tl_buchi.c *****/
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
-
#include "tl.h"
extern int tl_verbose, tl_clutter, Total, Max_Red;
+extern char *claim_name;
FILE *tl_out; /* if standalone: = stdout; */
@@ -38,6 +36,13 @@
static State *never = (State *) 0;
static int hitsall;
+void
+ini_buchi(void)
+{
+ never = (State *) 0;
+ hitsall = 0;
+}
+
static int
sametrans(Transition *s, Transition *t)
{
@@ -58,6 +63,7 @@
#ifdef NXT
case NEXT:
#endif
+ case CEXPR:
return p;
case OR:
p->lft = Prune(p->lft);
@@ -545,10 +551,22 @@
rev_trans(t->nxt);
if (t->redundant && !tl_verbose) return;
- fprintf(tl_out, "\t:: (");
- if (dump_cond(t->cond, t->cond, 1))
- fprintf(tl_out, "1");
- fprintf(tl_out, ") -> goto %s\n", t->name->name);
+
+ if (strcmp(t->name->name, "accept_all") == 0) /* 6.2.4 */
+ { /* not d_step because there may be remote refs */
+ fprintf(tl_out, "\t:: atomic { (");
+ if (dump_cond(t->cond, t->cond, 1))
+ fprintf(tl_out, "1");
+ fprintf(tl_out, ") -> assert(!(");
+ if (dump_cond(t->cond, t->cond, 1))
+ fprintf(tl_out, "1");
+ fprintf(tl_out, ")) }\n");
+ } else
+ { fprintf(tl_out, "\t:: (");
+ if (dump_cond(t->cond, t->cond, 1))
+ fprintf(tl_out, "1");
+ fprintf(tl_out, ") -> goto %s\n", t->name->name);
+ }
tcnt++;
}
@@ -570,11 +588,11 @@
&& Max_Red == 0)
fprintf(tl_out, "T0%s:\n", &(b->name->name[6]));
- fprintf(tl_out, "\tif\n");
+ fprintf(tl_out, "\tdo\n");
tcnt = 0;
rev_trans(b->trans);
if (!tcnt) fprintf(tl_out, "\t:: false\n");
- fprintf(tl_out, "\tfi;\n");
+ fprintf(tl_out, "\tod;\n");
Total++;
}
@@ -626,13 +644,13 @@
if (tl_clutter) clutter();
b = findstate("T0_init");
- if (Max_Red == 0)
+ if (b && (Max_Red == 0))
b->accepting = 1;
mergestates(0);
b = findstate("T0_init");
- fprintf(tl_out, "never { /* ");
+ fprintf(tl_out, "never %s { /* ", claim_name?claim_name:"");
put_uform();
fprintf(tl_out, " */\n");
--- a/sys/src/cmd/spin/tl_cache.c
+++ b/sys/src/cmd/spin/tl_cache.c
@@ -1,17 +1,14 @@
/***** tl_spin: tl_cache.c *****/
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
-
#include "tl.h"
typedef struct Cache {
@@ -24,10 +21,19 @@
static Cache *stored = (Cache *) 0;
static unsigned long Caches, CacheHits;
-static int ismatch(Node *, Node *);
+static int ismatch(Node *, Node *);
+static int sameform(Node *, Node *);
+
extern void fatal(char *, char *);
-int sameform(Node *, Node *);
+void
+ini_cache(void)
+{
+ stored = (Cache *) 0;
+ Caches = 0;
+ CacheHits = 0;
+}
+
#if 0
void
cache_dump(void)
@@ -182,7 +188,7 @@
return all_lfts(ntyp, b, a);
}
-int /* a better isequal() */
+static int /* a better isequal() */
sameform(Node *a, Node *b)
{
if (!a && !b) return 1;
@@ -206,6 +212,7 @@
#ifdef NXT
case NEXT:
#endif
+ case CEXPR:
return sameform(a->lft, b->lft);
case U_OPER:
case V_OPER:
--- a/sys/src/cmd/spin/tl_lex.c
+++ b/sys/src/cmd/spin/tl_lex.c
@@ -1,17 +1,14 @@
/***** tl_spin: tl_lex.c *****/
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
-
#include <stdlib.h>
#include <ctype.h>
#include "tl.h"
@@ -18,6 +15,7 @@
static Symbol *symtab[Nhash+1];
static int tl_lex(void);
+extern int tl_peek(int);
extern YYSTYPE tl_yylval;
extern char yytext[];
@@ -26,11 +24,19 @@
static void
tl_getword(int first, int (*tst)(int))
-{ int i=0; char c;
+{ int i=0; int c;
yytext[i++] = (char ) first;
- while (tst(c = tl_Getchar()))
- yytext[i++] = c;
+
+ c = tl_Getchar();
+ while (c != -1 && tst(c))
+ { yytext[i++] = (char) c;
+ c = tl_Getchar();
+ }
+
+/* while (tst(c = tl_Getchar()))
+ * yytext[i++] = c;
+ */
yytext[i] = '\0';
tl_UnGetchar();
}
@@ -54,12 +60,86 @@
tl_yylex(void)
{ int c = tl_lex();
#if 0
- printf("c = %d\n", c);
+ printf("c = %c (%d)\n", c, c);
#endif
return c;
}
static int
+is_predicate(int z)
+{ char c, c_prev = z;
+ char want = (z == '{') ? '}' : ')';
+ int i = 0, j, nesting = 0;
+ char peek_buf[512];
+
+ c = tl_peek(i++); /* look ahead without changing position */
+ while ((c != want || nesting > 0) && c != -1 && i < 2047)
+ { if (islower((int) c) || c == '_')
+ { peek_buf[0] = c;
+ j = 1;
+ while (j < (int) sizeof(peek_buf)
+ && (isalnum((int)(c = tl_peek(i))) || c == '_'))
+ { peek_buf[j++] = c;
+ i++;
+ }
+ c = 0; /* make sure we don't match on z or want on the peekahead */
+ if (j >= (int) sizeof(peek_buf))
+ { peek_buf[j-1] = '\0';
+ fatal("name '%s' in ltl formula too long", peek_buf);
+ }
+ peek_buf[j] = '\0';
+ if (strcmp(peek_buf, "always") == 0
+ || strcmp(peek_buf, "equivalent") == 0
+ || strcmp(peek_buf, "eventually") == 0
+ || strcmp(peek_buf, "until") == 0
+ || strcmp(peek_buf, "next") == 0
+ || strcmp(peek_buf, "c_expr") == 0)
+ { return 0;
+ }
+ } else
+ { int c_nxt = tl_peek(i);
+ if (((c == 'U' || c == 'V' || c == 'X')
+ && !isalnum_(c_prev)
+ && (c_nxt == -1 || !isalnum_(c_nxt)))
+ || (c == '<' && c_nxt == '>')
+ || (c == '<' && c_nxt == '-')
+ || (c == '-' && c_nxt == '>')
+ || (c == '[' && c_nxt == ']'))
+ { return 0;
+ } }
+
+ if (c == z)
+ { nesting++;
+ }
+ if (c == want)
+ { nesting--;
+ }
+ c_prev = c;
+ c = tl_peek(i++);
+ }
+ return 1;
+}
+
+static void
+read_upto_closing(int z)
+{ char c, want = (z == '{') ? '}' : ')';
+ int i = 0, nesting = 0;
+
+ c = tl_Getchar();
+ while ((c != want || nesting > 0) && c != -1 && i < 2047) /* yytext is 2048 */
+ { yytext[i++] = c;
+ if (c == z)
+ { nesting++;
+ }
+ if (c == want)
+ { nesting--;
+ }
+ c = tl_Getchar();
+ }
+ yytext[i] = '\0';
+}
+
+static int
tl_lex(void)
{ int c;
@@ -74,6 +154,20 @@
} while (c == ' '); /* '\t' is removed in tl_main.c */
+ if (c == '{' || c == '(') /* new 6.0.0 */
+ { if (is_predicate(c))
+ { read_upto_closing(c);
+ tl_yylval = tl_nn(PREDICATE,ZN,ZN);
+ if (!tl_yylval)
+ { fatal("unexpected error 4", (char *) 0);
+ }
+ tl_yylval->sym = tl_lookup(yytext);
+ return PREDICATE;
+ } }
+
+ if (c == '}')
+ { tl_yyerror("unexpected '}'");
+ }
if (islower(c))
{ tl_getword(c, isalnum_);
if (strcmp("true", yytext) == 0)
@@ -82,10 +176,34 @@
if (strcmp("false", yytext) == 0)
{ Token(FALSE);
}
+ if (strcmp("always", yytext) == 0)
+ { Token(ALWAYS);
+ }
+ if (strcmp("eventually", yytext) == 0)
+ { Token(EVENTUALLY);
+ }
+ if (strcmp("until", yytext) == 0)
+ { Token(U_OPER);
+ }
+#ifdef NXT
+ if (strcmp("next", yytext) == 0)
+ { Token(NEXT);
+ }
+#endif
+ if (strcmp("c_expr", yytext) == 0)
+ { Token(CEXPR);
+ }
+ if (strcmp("not", yytext) == 0)
+ { Token(NOT);
+ }
tl_yylval = tl_nn(PREDICATE,ZN,ZN);
+ if (!tl_yylval)
+ { fatal("unexpected error 5", (char *) 0);
+ }
tl_yylval->sym = tl_lookup(yytext);
return PREDICATE;
}
+
if (c == '<')
{ c = tl_Getchar();
if (c == '>')
@@ -124,7 +242,7 @@
Symbol *
tl_lookup(char *s)
{ Symbol *sp;
- int h = hash(s);
+ unsigned int h = hash(s);
for (sp = symtab[h]; sp; sp = sp->next)
if (strcmp(sp->name, s) == 0)
--- a/sys/src/cmd/spin/tl_main.c
+++ b/sys/src/cmd/spin/tl_main.c
@@ -1,17 +1,14 @@
/***** tl_spin: tl_main.c *****/
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
-
#include "tl.h"
extern FILE *tl_out;
@@ -21,7 +18,10 @@
int tl_verbose = 0;
int tl_terse = 0;
int tl_clutter = 0;
+int state_cnt = 0;
+
unsigned long All_Mem = 0;
+char *claim_name;
static char uform[4096];
static int hasuform=0, cnt=0;
@@ -38,6 +38,15 @@
return -1;
}
+int
+tl_peek(int n)
+{
+ if (cnt+n < hasuform)
+ { return uform[cnt+n];
+ }
+ return -1;
+}
+
void
tl_balanced(void)
{ int i;
@@ -45,10 +54,21 @@
for (i = 0; i < hasuform; i++)
{ if (uform[i] == '(')
- { k++;
+ { if (i > 0
+ && ((uform[i-1] == '"' && uform[i+1] == '"')
+ || (uform[i-1] == '\'' && uform[i+1] == '\'')))
+ { continue;
+ }
+ k++;
} else if (uform[i] == ')')
- { k--;
+ { if (i > 0
+ && ((uform[i-1] == '"' && uform[i+1] == '"')
+ || (uform[i-1] == '\'' && uform[i+1] == '\'')))
+ { continue;
+ }
+ k--;
} }
+
if (k != 0)
{ tl_errs++;
tl_yyerror("parentheses not balanced");
@@ -79,18 +99,40 @@
int
tl_main(int argc, char *argv[])
{ int i;
- extern int verbose, xspin;
- tl_verbose = verbose;
- tl_clutter = 1-xspin; /* use -X -f to turn off uncluttering */
+ extern int xspin, s_trail;
+ tl_verbose = 0; /* was: tl_verbose = verbose; */
+ if (xspin && s_trail)
+ { tl_clutter = 1;
+ /* generating claims for a replay should
+ be done the same as when generating the
+ pan.c that produced the error-trail */
+ } else
+ { tl_clutter = 1-xspin; /* use -X -f to turn off uncluttering */
+ }
+ newstates = 0;
+ state_cnt = 0;
+ tl_errs = 0;
+ tl_terse = 0;
+ All_Mem = 0;
+ memset(uform, 0, sizeof(uform));
+ hasuform=0;
+ cnt=0;
+ claim_name = (char *) 0;
+
+ ini_buchi();
+ ini_cache();
+ ini_rewrt();
+ ini_trans();
+
while (argc > 1 && argv[1][0] == '-')
- { switch (argv[1][1]) {
+ {
+ switch (argv[1][1]) {
case 'd': newstates = 1; /* debugging mode */
break;
case 'f': argc--; argv++;
- for (i = 0; i < argv[1][i]; i++)
+ for (i = 0; argv[1][i]; i++)
{ if (argv[1][i] == '\t'
- || argv[1][i] == '\"'
|| argv[1][i] == '\n')
argv[1][i] = ' ';
}
@@ -101,6 +143,10 @@
break;
case 'n': tl_terse = 1;
break;
+ case 'c': argc--; argv++;
+ claim_name = (char *) emalloc(strlen(argv[1])+1);
+ strcpy(claim_name, argv[1]);
+ break;
default : printf("spin -f: saw '-%c'\n", argv[1][1]);
goto nogood;
}
@@ -162,6 +208,12 @@
case PREDICATE:
fprintf(tl_out, "(%s)", n->sym->name);
break;
+ case CEXPR:
+ fprintf(tl_out, "c_expr");
+ fprintf(tl_out, " {");
+ dump(n->lft);
+ fprintf(tl_out, "}");
+ break;
case -1:
fprintf(tl_out, " D ");
break;
@@ -189,6 +241,7 @@
#ifdef NXT
case NEXT: printf("X"); break;
#endif
+ case CEXPR: printf("c_expr"); break;
case TRUE: printf("true"); break;
case FALSE: printf("false"); break;
case ';': printf("end of formula"); break;
@@ -202,10 +255,14 @@
int i;
printf("tl_spin: ");
+#if 1
+ printf(s1, s2); /* prevent a compiler warning */
+#else
if (s2)
printf(s1, s2);
else
printf(s1);
+#endif
if (tl_yychar != -1 && tl_yychar != 0)
{ printf(", saw '");
tl_explain(tl_yychar);
--- a/sys/src/cmd/spin/tl_mem.c
+++ b/sys/src/cmd/spin/tl_mem.c
@@ -1,16 +1,13 @@
/***** tl_spin: tl_mem.c *****/
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
-
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
#include "tl.h"
--- a/sys/src/cmd/spin/tl_parse.c
+++ b/sys/src/cmd/spin/tl_parse.c
@@ -1,17 +1,14 @@
/***** tl_spin: tl_parse.c *****/
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
-
#include "tl.h"
extern int tl_yylex(void);
@@ -44,11 +41,13 @@
ptr = tl_yylval;
tl_yychar = tl_yylex();
ptr->lft = tl_factor();
+ if (!ptr->lft)
+ { fatal("malformed expression", (char *) 0);
+ }
ptr = push_negation(ptr);
break;
case ALWAYS:
tl_yychar = tl_yylex();
-
ptr = tl_factor();
#ifndef NO_OPT
if (ptr->ntyp == FALSE
@@ -73,6 +72,14 @@
ptr = tl_nn(NEXT, ptr, ZN);
break;
#endif
+ case CEXPR:
+ tl_yychar = tl_yylex();
+ ptr = tl_factor();
+ if (ptr->ntyp != PREDICATE)
+ { tl_yyerror("expected {...} after c_expr");
+ }
+ ptr = tl_nn(CEXPR, ptr, ZN);
+ break;
case EVENTUALLY:
tl_yychar = tl_yylex();
@@ -385,7 +392,10 @@
void
tl_parse(void)
-{ Node *n = tl_formula();
+{ Node *n;
+
+ /* tl_verbose = 1; */
+ n = tl_formula();
if (tl_verbose)
{ printf("formula: ");
dump(n);
--- a/sys/src/cmd/spin/tl_rewrt.c
+++ b/sys/src/cmd/spin/tl_rewrt.c
@@ -1,17 +1,14 @@
/***** tl_spin: tl_rewrt.c *****/
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
-
#include "tl.h"
extern int tl_verbose;
@@ -18,6 +15,12 @@
static Node *can = ZN;
+void
+ini_rewrt(void)
+{
+ can = ZN;
+}
+
Node *
right_linked(Node *n)
{
@@ -137,6 +140,9 @@
}
s = DoDump(N);
+ if (!s)
+ { fatal("unexpected error 6", (char *) 0);
+ }
if (can->ntyp != tok) /* only one element in list so far */
{ ptr = &can;
goto insert;
@@ -146,7 +152,10 @@
prev = ZN;
for (m = can; m->ntyp == tok && m->rgt; prev = m, m = m->rgt)
{ t = DoDump(m->lft);
- cmp = strcmp(s->name, t->name);
+ if (t != ZS)
+ cmp = strcmp(s->name, t->name);
+ else
+ cmp = 0;
if (cmp == 0) /* duplicate */
return;
if (cmp < 0)
--- a/sys/src/cmd/spin/tl_trans.c
+++ b/sys/src/cmd/spin/tl_trans.c
@@ -1,21 +1,18 @@
/***** tl_spin: tl_trans.c *****/
-/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ *
+ * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
+ * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
+ */
-/* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
-/* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
-
#include "tl.h"
extern FILE *tl_out;
-extern int tl_errs, tl_verbose, tl_terse, newstates;
+extern int tl_errs, tl_verbose, tl_terse, newstates, state_cnt;
int Stack_mx=0, Max_Red=0, Total=0;
@@ -23,7 +20,7 @@
static Graph *Nodes_Set = (Graph *) 0;
static Graph *Nodes_Stack = (Graph *) 0;
-static char dumpbuf[2048];
+static char dumpbuf[4096];
static int Red_cnt = 0;
static int Lab_cnt = 0;
static int Base = 0;
@@ -51,6 +48,24 @@
static void push_stack(Graph *);
static void sdump(Node *);
+void
+ini_trans(void)
+{
+ Stack_mx = 0;
+ Max_Red = 0;
+ Total = 0;
+
+ Mapped = (Mapping *) 0;
+ Nodes_Set = (Graph *) 0;
+ Nodes_Stack = (Graph *) 0;
+
+ memset(dumpbuf, 0, sizeof(dumpbuf));
+ Red_cnt = 0;
+ Lab_cnt = 0;
+ Base = 0;
+ Stack_sz = 0;
+}
+
static void
dump_graph(Graph *g)
{ Node *n1;
@@ -101,9 +116,8 @@
static char *
newname(void)
-{ static int cnt = 0;
- static char buf[32];
- sprintf(buf, "S%d", cnt++);
+{ static char buf[32];
+ sprintf(buf, "S%d", state_cnt++);
return buf;
}
@@ -132,6 +146,8 @@
mk_grn(Node *n)
{ Graph *p;
+ if (!n) return;
+
n = right_linked(n);
more:
for (p = Nodes_Set; p; p = p->nxt)
@@ -152,6 +168,8 @@
mk_red(Node *n)
{ Graph *p;
+ if (!n) return;
+
n = right_linked(n);
for (p = Nodes_Set; p; p = p->nxt)
{ if (p->outgoing
@@ -240,6 +258,15 @@
q = dupnode(pp);
q = rewrite(q);
+ if (q->ntyp == CEXPR)
+ { if (!frst) fprintf(tl_out, " && ");
+ fprintf(tl_out, "c_expr { ");
+ dump_cond(q->lft, r, 1);
+ fprintf(tl_out, " } ");
+ frst = 0;
+ return frst;
+ }
+
if (q->ntyp == PREDICATE
|| q->ntyp == NOT
#ifndef NXT
@@ -342,7 +369,7 @@
fsm_trans(Graph *p, int count, char *curnm)
{ Graph *r;
Symbol *s;
- char prefix[128], nwnm[128];
+ char prefix[128], nwnm[256];
if (!p->outgoing)
addtrans(p, curnm, False, "accept_all");
@@ -452,9 +479,11 @@
ng(tl_lookup("init"), ZS, ZN, ZN, ZN);
p1 = pop_stack();
- p1->nxt = Nodes_Set;
- p1->Other = p1->Old = orig;
- Nodes_Set = p1;
+ if (p1)
+ { p1->nxt = Nodes_Set;
+ p1->Other = p1->Old = orig;
+ Nodes_Set = p1;
+ }
for (g = Nodes_Set; g; g = g->nxt)
{ for (q1 = g->incoming; q1; q1 = q2)
@@ -532,6 +561,10 @@
case NEXT: strcat(dumpbuf, "X");
goto common1;
#endif
+ case CEXPR: strcat(dumpbuf, "c_expr {");
+ sdump(n->lft);
+ strcat(dumpbuf, "}");
+ break;
case NOT: strcat(dumpbuf, "!");
goto common1;
case TRUE: strcat(dumpbuf, "T");
@@ -718,10 +751,13 @@
break;
case PREDICATE:
case NOT:
+ case CEXPR:
if (can_release) releasenode(1, now);
push_stack(g);
break;
case V_OPER:
+ Assert(now->rgt != ZN, now->ntyp);
+ Assert(now->lft != ZN, now->ntyp);
Assert(now->rgt->nxt == ZN, now->ntyp);
Assert(now->lft->nxt == ZN, now->ntyp);
n1 = now->rgt;
@@ -759,6 +795,7 @@
#ifdef NXT
case NEXT:
+ Assert(now->lft != ZN, now->ntyp);
nx = dupnode(now->lft);
nx->nxt = g->Next;
g->Next = nx;
--- a/sys/src/cmd/spin/vars.c
+++ b/sys/src/cmd/spin/vars.c
@@ -1,13 +1,10 @@
/***** spin: vars.c *****/
-/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
-/* All Rights Reserved. This software is for educational purposes only. */
-/* No guarantee whatsoever is expressed or implied by the distribution of */
-/* this code. Permission is given to distribute this code provided that */
-/* this introductory message is not removed and no monies are exchanged. */
-/* Software written by Gerard J. Holzmann. For tool documentation see: */
-/* http://spinroot.com/ */
-/* Send all bug-reports and/or questions to: bugs@spinroot.com */
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
#include "spin.h"
#include "y.tab.h"
@@ -17,7 +14,7 @@
extern Symbol *Fname;
extern char Buf[];
extern int lineno, depth, verbose, xspin, limited_vis;
-extern int analyze, jumpsteps, nproc, nstop, columns;
+extern int analyze, jumpsteps, nproc, nstop, columns, old_priority_rules;
extern short no_arrays, Have_claim;
extern void sr_mesg(FILE *, int, int);
extern void sr_buf(int, int);
@@ -42,16 +39,29 @@
{ if (!X) return 0;
return X->pid - Have_claim;
}
+ if (strcmp(s->name, "_priority") == 0)
+ { if (!X) return 0;
+
+ if (old_priority_rules)
+ { non_fatal("cannot refer to _priority with -o6", (char *) 0);
+ return 1;
+ }
+ return X->priority;
+ }
+
if (strcmp(s->name, "_nr_pr") == 0)
- return nproc-nstop; /* new 3.3.10 */
+ { return nproc-nstop; /* new 3.3.10 */
+ }
if (s->context && s->type)
- return getlocal(sn);
+ { return getlocal(sn);
+ }
if (!s->type) /* not declared locally */
{ s = lookup(s->name); /* try global */
sn->sym = s; /* fix it */
}
+
return getglobal(sn);
}
@@ -58,6 +68,25 @@
int
setval(Lextok *v, int n)
{
+ if (strcmp(v->sym->name, "_last") == 0
+ || strcmp(v->sym->name, "_p") == 0
+ || strcmp(v->sym->name, "_pid") == 0
+ || strcmp(v->sym->name, "_nr_qs") == 0
+ || strcmp(v->sym->name, "_nr_pr") == 0)
+ { non_fatal("illegal assignment to %s", v->sym->name);
+ }
+ if (strcmp(v->sym->name, "_priority") == 0)
+ { if (old_priority_rules)
+ { non_fatal("cannot refer to _priority with -o6", (char *) 0);
+ return 1;
+ }
+ if (!X)
+ { non_fatal("no context for _priority", (char *) 0);
+ return 1;
+ }
+ X->priority = n;
+ }
+
if (v->sym->context && v->sym->type)
return setlocal(v, n);
if (!v->sym->type)
@@ -90,6 +119,7 @@
checkvar(Symbol *s, int n)
{ int i, oln = lineno; /* calls on eval() change it */
Symbol *ofnm = Fname;
+ Lextok *z, *y;
if (!in_bound(s, n))
return 0;
@@ -101,15 +131,23 @@
/* not a STRUCT */
if (s->val == (int *) 0) /* uninitialized */
{ s->val = (int *) emalloc(s->nel*sizeof(int));
+ z = s->ini;
for (i = 0; i < s->nel; i++)
- { if (s->type != CHAN)
- { rm_selfrefs(s, s->ini);
- s->val[i] = eval(s->ini);
+ { if (z && z->ntyp == ',')
+ { y = z->lft;
+ z = z->rgt;
+ } else
+ { y = z;
+ }
+ if (s->type != CHAN)
+ { rm_selfrefs(s, y);
+ s->val[i] = eval(y);
} else if (!analyze)
- s->val[i] = qmake(s);
- } }
+ { s->val[i] = qmake(s);
+ } } }
lineno = oln;
Fname = ofnm;
+
return 1;
}
@@ -118,14 +156,16 @@
{ Symbol *s = sn->sym;
int i, n = eval(sn->lft);
- if (s->type == 0 && X && (i = find_lab(s, X->n, 0)))
+ if (s->type == 0 && X && (i = find_lab(s, X->n, 0))) /* getglobal */
{ printf("findlab through getglobal on %s\n", s->name);
return i; /* can this happen? */
}
if (s->type == STRUCT)
- return Rval_struct(sn, s, 1); /* 1 = check init */
+ { return Rval_struct(sn, s, 1); /* 1 = check init */
+ }
if (checkvar(s, n))
- return cast_val(s->type, s->val[n], s->nbits);
+ { return cast_val(s->type, s->val[n], s->nbits);
+ }
return 0;
}
@@ -145,10 +185,10 @@
}
if (v != i+s+ (int) u)
- { char buf[32]; sprintf(buf, "%d->%d (%d)", v, i+s+u, t);
+ { char buf[64]; sprintf(buf, "%d->%d (%d)", v, i+s+(int)u, t);
non_fatal("value (%s) truncated in assignment", buf);
}
- return (int)(i+s+u);
+ return (int)(i+s+(int)u);
}
static int
@@ -155,13 +195,16 @@
setglobal(Lextok *v, int m)
{
if (v->sym->type == STRUCT)
- (void) Lval_struct(v, v->sym, 1, m);
- else
+ { (void) Lval_struct(v, v->sym, 1, m);
+ } else
{ int n = eval(v->lft);
if (checkvar(v->sym, n))
- { v->sym->val[n] = cast_val(v->sym->type, m, v->sym->nbits);
- v->sym->setat = depth;
- } }
+ { int oval = v->sym->val[n];
+ int nval = cast_val(v->sym->type, m, v->sym->nbits);
+ v->sym->val[n] = nval;
+ if (oval != nval)
+ { v->sym->setat = depth;
+ } } }
return 1;
}
@@ -215,7 +258,12 @@
continue;
if (sp->type == STRUCT)
- { dump_struct(sp, sp->name, 0);
+ { if ((verbose&4) && !(verbose&64)
+ && (sp->setat < depth
+ && jumpsteps != depth))
+ { continue;
+ }
+ dump_struct(sp, sp->name, 0);
continue;
}
for (j = 0; j < sp->nel; j++)
@@ -227,13 +275,15 @@
if ((verbose&4) && !(verbose&64)
&& (sp->setat < depth
&& jumpsteps != depth))
- continue;
+ { continue;
+ }
+
dummy->sym = sp;
dummy->lft->val = j;
/* in case of cast_val warnings, do this first: */
prefetch = getglobal(dummy);
printf("\t\t%s", sp->name);
- if (sp->nel > 1) printf("[%d]", j);
+ if (sp->nel > 1 || sp->isarray) printf("[%d]", j);
printf(" = ");
sr_mesg(stdout, prefetch,
sp->type == MTYPE);
@@ -249,7 +299,7 @@
}
sr_buf(prefetch, sp->type == MTYPE);
if (sp->colnr == 0)
- { sp->colnr = maxcolnr;
+ { sp->colnr = (unsigned char) maxcolnr;
maxcolnr = 1+(maxcolnr%10);
}
colpos = nproc+sp->colnr-1;
@@ -266,7 +316,7 @@
depth, colpos);
printf("(state 0)\t[printf('MSC: globvar\\\\n')]\n");
printf("\t\t%s", sp->name);
- if (sp->nel > 1) printf("[%d]", j);
+ if (sp->nel > 1 || sp->isarray) printf("[%d]", j);
printf(" = %s\n", Buf);
} } }
}
@@ -303,8 +353,8 @@
dummy->lft->val = i;
printf("\t\t%s(%d):%s",
- r->n->name, r->pid, z->name);
- if (z->nel > 1) printf("[%d]", i);
+ r->n->name, r->pid - Have_claim, z->name);
+ if (z->nel > 1 || z->isarray) printf("[%d]", i);
printf(" = ");
sr_mesg(stdout, getval(dummy), z->type == MTYPE);
printf("\n");
@@ -321,7 +371,7 @@
}
sr_buf(getval(dummy), z->type==MTYPE);
if (z->colnr == 0)
- { z->colnr = maxcolnr;
+ { z->colnr = (unsigned char) maxcolnr;
maxcolnr = 1+(maxcolnr%10);
}
colpos = nproc+z->colnr-1;
@@ -341,7 +391,7 @@
printf("(state 0)\t[printf('MSC: locvar\\\\n')]\n");
printf("\t\t%s(%d):%s",
r->n->name, r->pid, z->name);
- if (z->nel > 1) printf("[%d]", i);
+ if (z->nel > 1 || z->isarray) printf("[%d]", i);
printf(" = %s\n", Buf);
} } }
}
--- a/sys/src/cmd/spin/version.h
+++ b/sys/src/cmd/spin/version.h
@@ -1,1 +1,9 @@
-#define Version "Spin Version 4.3.0 -- 22 June 2007"
+/***** spin: version.h *****/
+
+/*
+ * This file is part of the public release of Spin. It is subject to the
+ * terms in the LICENSE file that is included in this source directory.
+ * Tool documentation is available at http://spinroot.com
+ */
+
+#define SpinVersion "Spin Version 6.4.7 -- 19 August 2017"