* [Patch] Update Spin to most recent version.
@ 2017-11-22 8:23 Ori Bernstein
0 siblings, 0 replies; only message in thread
From: Ori Bernstein @ 2017-11-22 8:23 UTC (permalink / raw)
To: 9front
I decided it's time to learn what spin is all about, and saw that
the version shipped with 9front is rather old. It turned out to
be trivial to build newer versions of spin, so I updated it.
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
The diff is attached, if there's interest in updating.
--- a/sys/src/cmd/spin/dstep.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/dstep.c Wed Nov 22 00:21:47 2017 -0800
@@ -1,27 +1,25 @@
/***** 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;
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,17 +183,17 @@
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;
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);
diff -r 51b3bf8bc61b sys/src/cmd/spin/flow.c
--- a/sys/src/cmd/spin/flow.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/flow.c Wed Nov 22 00:21:47 2017 -0800
@@ -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++;
- 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,21 +426,26 @@
&& 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--;
}
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,16 +1088,16 @@
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))
{ 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");
+ }
}
diff -r 51b3bf8bc61b sys/src/cmd/spin/guided.c
--- a/sys/src/cmd/spin/guided.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/guided.c Wed Nov 22 00:21:47 2017 -0800
@@ -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,12 +72,70 @@
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;
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 == -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 (verbose)
+ { 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)
diff -r 51b3bf8bc61b sys/src/cmd/spin/main.c
--- a/sys/src/cmd/spin/main.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/main.c Wed Nov 22 00:21:47 2017 -0800
@@ -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,6 +27,12 @@
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;
@@ -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,34 +859,110 @@
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;
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,65 +975,75 @@
}
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);
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,32 +1058,54 @@
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);
}
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;
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;
}
}
+
+
diff -r 51b3bf8bc61b sys/src/cmd/spin/mesg.c
--- a/sys/src/cmd/spin/mesg.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/mesg.c Wed Nov 22 00:21:47 2017 -0800
@@ -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,6 +701,121 @@
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);
}
diff -r 51b3bf8bc61b sys/src/cmd/spin/mkfile
--- a/sys/src/cmd/spin/mkfile Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/mkfile Wed Nov 22 00:21:47 2017 -0800
@@ -8,14 +8,14 @@
guided.$O\
main.$O\
mesg.$O\
+ msc_tcl.$O\
pangen1.$O\
pangen2.$O\
pangen3.$O\
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
diff -r 51b3bf8bc61b sys/src/cmd/spin/msc_tcl.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/cmd/spin/msc_tcl.c Wed Nov 22 00:21:47 2017 -0800
@@ -0,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);
+ }
+}
diff -r 51b3bf8bc61b sys/src/cmd/spin/pangen1.c
--- a/sys/src/cmd/spin/pangen1.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/pangen1.c Wed Nov 22 00:21:47 2017 -0800
@@ -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,7 +52,22 @@
{
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
@@ -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, "#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,63 +336,89 @@
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 */
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,34 +681,40 @@
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);
} 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,28 +856,37 @@
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
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,77 +918,86 @@
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;
}
}
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);
-}
-
-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;
+ { putstmnt(ofd, sp->ini, 0);
+ }
}
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 (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);
+ 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);
+ }
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", nrRdy);
+ if (separate == 1)
+ { fprintf(tc, "\t\tini_claim(%d, h);\n", nrRdy);
+ } else
+ { 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, "\tcase %d: /* np_ */\n", i);
- if (separate == 1)
- { fprintf(tc, "\t\tini_claim(%d, h);\n", i);
- } 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, "#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,29 +1108,36 @@
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);
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);
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);
@@ -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");
diff -r 51b3bf8bc61b sys/src/cmd/spin/pangen1.h
--- a/sys/src/cmd/spin/pangen1.h Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/pangen1.h Wed Nov 22 00:21:47 2017 -0800
@@ -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 */
-
-static char *Code2a[] = { /* the tail of procedure run() */
- "#if defined(VERI) && !defined(NOREDUCE) && !defined(NP)",
+/*
+ * 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 *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));",
- "#endif",
- " stack = ( Stack *) emalloc(sizeof(Stack));",
+ " LL = (uchar *) emalloc(ONE_L<<(ssize-3));",
+ "#endif",
+ " 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));",
- "#endif",
- "#ifdef VERI",
- " Addproc(VERI); /* never - pid = 0 */",
+ " (void) write(svfd, (uchar *) &vprefix, sizeof(int));",
+ "#endif",
+ "#ifdef VERI",
+ " 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));",
- "#endif",
- "#if defined(FULLSTACK)",
+ " 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",
+ "#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,8 +125,157 @@
" }",
"#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
@@ -132,7 +320,7 @@
"static int stackread;",
"static Trail frameptr;",
"Trail *",
- "getframe(int d)",
+ "getframe(long d)",
"{",
" if (CNT1 == CNT2)",
" return &trail[d];",
@@ -153,63 +341,103 @@
" 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;",
- "}",
- "#endif",
- "#endif",
-
+ "#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",
"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",
+ "#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++;",
" 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);",
- " break;",
- " }",
- " strcat(buf[1-toggle], w);",
+ " strcat(tbuf[1-toggle], code_lookup[i].t);",
+ " break;",
+ " }",
+ " 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,14 +481,15 @@
"",
" 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) \",",
" 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];",
- "",
- " strcpy(MyFile, TrailFile);", /* avoid problem with non-writable strings */
- "",
+ " char MyFile[512];", /* avoid using a non-writable string */
+ " char MySuffix[16];",
+ " int try_core;",
+ " int candidate_files;",
+ "",
+ " 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,56 +635,122 @@
" 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);",
" 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;",
" } }",
" 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,38 +806,39 @@
" }",
" 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)",
" { 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;",
" }",
" 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);",
- "#endif",
- "",
- "#ifdef BITSTATE",
-#ifndef POWOW
+ "",
+ "#if NCORE>1 && !defined(GLOB_HEAP)",
+ " #define SEP_HEAP /* version 5.1.2 */",
+ "#endif",
+ "",
+ "#ifdef BITSTATE",
"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;",
- "#endif",
- " int *qo;",
- " uchar *ps, *qs;",
- " struct EV_Hold *nxt;",
- "} EV_Hold;",
- "",
- "typedef struct BFS_Trail {",
- " Trail *frame;",
- " SV_Hold *onow;",
- " EV_Hold *omask;",
- "#ifdef Q_PROVISO",
- " struct H_el *lstate;",
- "#endif",
- " short boq;",
- " struct BFS_Trail *nxt;",
- "} BFS_Trail;",
- "",
- "BFS_Trail *bfs_trail, *bfs_bot, *bfs_free;",
- "",
- "SV_Hold *svhold, *svfree;",
+ "",
+ "#ifndef FREQ",
+ "#define FREQ (1000000)",
+ "#endif",
+ "double freq = (double) FREQ;\n",
+
+ "#ifdef TRIX",
+ "void sv_populate(void);",
+ "",
+ "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",
+ " 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",
+ "",
+ " 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",
"",
"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;",
- "",
- " 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)",
+ "{ SV_Hold *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)",
- " break;",
- "",
+ " { if (p->sz >= h->sz)",
+ " break;",
+ " }",
" if (!oh)",
" { p->nxt = svfree;",
" svfree = p;",
@@ -736,171 +1216,239 @@
" }",
"}",
"",
- "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;",
- " } else",
- " { t = (BFS_Trail *) emalloc(sizeof(BFS_Trail));",
+ " t->nxt = (BFS_State *) 0;",
+ " } else",
+ " { 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));",
" 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",
" { 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;",
"}",
"",
"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;",
"",
" 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 */
- "",
- "#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",
+ " #endif", /* VERI */
+ "",
+ " #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",
- " }",
- "#ifdef VERI",
+ " #endif",
+ " #endif",
+ " }",
+ " #ifdef VERI",
" ((P0 *)this)->_p = tt; /* reset claim */",
" if (t2)",
" do_reverse(t2, 0, 0);",
@@ -936,10 +1487,8 @@
" } }",
" this = othis;",
" trpt->o_pm = o_opm;",
- "#endif",
- "}",
- "",
- "Trail *ntrpt;", /* 4.2.8 */
+ " #endif",
+ "}",
"",
"void",
"bfs(void)",
@@ -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,81 +1507,74 @@
"",
" 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;",
" 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;",
- "",
- " /* ptr to pred: */ ntrpt->ostate = (struct H_el *) otrpt;",
+ " #endif",
+ " #endif",
+ " if (t->st > 0)",
+ " { ((P0 *)this)->_p = t->st;",
+ " }",
+ "",
+ " /* 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",
- " }",
- "#ifdef VERBOSE",
- " else printf(\"failed rv, tau at parent: %%d\\n\", x->tau);",
- "#endif",
+ " #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,40 +1816,178 @@
"}",
"",
"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 */
" { 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 */
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;",
@@ -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,20 +2023,20 @@
" }",
"#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[] */",
- " }",
- "#endif",
+ " #ifndef NOFAIR",
+ " if (!fairness)",
+ " { int j = 0;",
+ " i = &(now._cnt[0]) - (uchar *) &now;",
+ " while (j++ < NFAIR)",
+ " Mask[i++] = 1; /* _cnt[] */",
+ " }",
+ " #endif",
"#endif",
"#ifndef NOFAIR",
" if (fairness",
@@ -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();",
- "#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 */",
+ " #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",
+
+ " #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",
- " break;",
- " }",
- "#endif",
+ " #endif",
+ " break;",
+ " }",
+ " #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",
- " }",
- "#ifdef NEGATED_TRACE",
+ " #endif",
+ " }",
+ " #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",
+ "}",
+ "#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);",
- "#endif",
- " printf(\"Memory= %%-6.3f\\n\", memcnt/1000000.);",
+ " printf(\"Nodes= %%7lu \", nr_states);",
+ "#endif",
+ " 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,126 +2640,233 @@
"#if defined(FULLSTACK) && defined(MA)",
" trpt->proviso = 0;",
"#endif",
+ "#ifdef NSUCC",
+ " trpt->n_succ = 0;",
+ "#endif",
+ "#if NCORE>1",
+ " if (mem_hand_off())",
+ " {",
+ "#if SYNC",
+ " (trpt+1)->o_n = 1; /* not a deadlock: as below */",
+ "#endif",
+ "#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)",
- " { truncs++;",
+ " { if (!warned)",
+ " { warned = 1;",
+ " printf(\"error: max search depth too small\\n\");",
+ " }",
+ " if (bounded)",
+ " { uerror(\"depth limit reached\");",
+ " }",
+ " truncs++;",
"#if SYNC",
" (trpt+1)->o_n = 1; /* not a deadlock */",
"#endif",
- " if (!warned)",
- " { warned = 1;",
- " printf(\"error: max search depth too small\\n\");",
- " }",
- " if (bounded) uerror(\"depth limit reached\");",
- " (trpt-1)->tau |= 16; /* worstcase guess */",
+ "#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))",
"#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))",
- " {",
- " depthfound = A_depth;",
- "#ifdef CHECK",
- " printf(\"matches seed\\n\");",
- "#endif",
- "#ifdef NP",
- " uerror(\"non-progress cycle\");",
- "#else",
- " uerror(\"acceptance cycle\");",
- "#endif",
- " goto Up;",
- " }",
- "#ifdef CHECK",
- " printf(\"not seed\\n\");",
- "#endif",
+ " { int delta = S_A + 2;",
+ " if (!memcmp((char *)&A_Root + delta, ",
+ " (char *)&now + delta, vsize - delta))",
+ " {",
+ "#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\");",
+ " }",
+ " #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];",
- "#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 */
+ " #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", /* 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",
" 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",
"#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\");",
"#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,47 +2880,114 @@
"#else",
" uerror(\"acceptance cycle\");",
"#endif",
+ "#if NCORE>1 && defined(FULL_TRAIL)",
+ " if (upto > 0)",
+ " { Pop_Stack_Tree();",
+ " }",
+ "#endif",
" goto Up;",
" }",
" }",
"#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 */",
+ " #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;",
- " truncs2++;",
- " }",
- "#else",
+ " } 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,9 +2999,12 @@
" printf(\"%%d: putting\\n\", depth);",
"#endif",
"#endif",
- "#endif",
- " } }",
-
+ "#else",
+ " #if NCORE>1",
+ " trpt->ostate = Lstate;",
+ " #endif",
+ "#endif",
+ " } }",
" if (depth > mreached)",
" mreached = depth;",
@@ -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",
- " }",
- "#endif",
-
+ " (int) depth, now._a_t);",
+ "#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,63 +3077,58 @@
"#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)",
"#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;",
- "#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;",
- " }",
- " }",
+ " t->om = 0;",
+ "#endif",
+ " 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;",
- "#endif",
+ " 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,16 +3312,26 @@
" 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",
" trpt->o_pm |= (32|64);",
" }",
"#endif",
- "#ifdef HAS_PROVIDED",
- " if (!provided(II, ot, tt, t)) continue;",
- "#endif",
+
+ "#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,49 +3381,83 @@
" 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);",
- "#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 \\n\", depth, II, t->t_id);",
+ "#else",
+ " 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",
+ " (boq != -1)?\"rendez-vous\":\"\",",
+ " (trpt->o_pm&2)?\"\":\"non-\", trpt->tau);",
+ "#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);",
- "#endif",
- "#ifdef RANDOMIZE",
- " printf(\" randomizer %%d\\n\", ooi);",
+ " cpu_printf(\"\\t(escape to state %%d)\\n\", t->st);",
+ "#endif",
+ "#endif",
+ "#ifdef T_RAND",
+ " cpu_printf(\"\\t(randomizer %%d)\\n\", ooi);",
"#endif",
"#endif",
@@ -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,30 +3548,76 @@
" 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\");",
- "#endif",
- "#ifdef MA",
- " 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);",
- " }",
+ " cpu_printf(\"%%d: Up - %%s\\n\", depth,",
+ " (trpt->tau&4)?\"claim\":\"program\");",
+ "#endif",
+ "#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)", /* 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",
@@ -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,61 +3649,63 @@
"#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",
+ " #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",
" /* 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,18 +3716,18 @@
" ((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;",
- " }",
- "#ifdef VERBOSE",
+ " #endif",
+ " goto domore;",
+ " }",
+ " #ifdef VERBOSE",
" else",
" printf(\"randomizer: done\\n\");",
- "#endif",
+ " #endif",
"#endif",
"#ifndef NOFAIR",
@@ -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 */",
- "#endif",
- " } /* all processes */",
+ "#ifdef VERI",
+ " if (II == 0)",
+ " { break; /* never claim */",
+ " }",
+ "#endif",
+ " 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,27 +3938,26 @@
" 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",
" 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;",
- "#ifdef DEBUG",
- " printf(\"%%3d: atomic step proc %%d \", depth, II+1);",
- " printf(\"unexecutable\\n\");",
+ " From = FROM_P; To = UPTO_P;",
+ "#ifdef DEBUG",
+ " 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,54 +4136,23 @@
" 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();",
- " }",
- "#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",
- " }",
- " if (depth > 0) goto Up;",
+ " }",
+ " if (depth > 0)",
+ " {",
+ "#if NCORE>1 && defined(FULL_TRAIL)",
+ " if (upto > 0)",
+ " { Pop_Stack_Tree();",
+ " }",
+ "#endif",
+ " goto Up;",
+ " }",
"}\n",
"#else",
"void new_state(void) { /* place holder */ }",
"#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",
- " printf(\"%%8g states, matched\\n\", truncs);",
+ " #endif",
+ "#endif",
+ " 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",
+ " if (udmem)",
" printf(\"\\nhash factor: %%4g (best if > 100.)\\n\\n\",",
- " (double)(1<<(ssize-8)) / (double) nstates * 256.0);",
+ " (double)(((double) udmem) * 8.0) / (double) nstates);",
+ " else",
+ " 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 0",
-#ifndef POWOW
- " if (udmem)",
- " printf(\"total bits available: %%8g (-M%%ld)\\n\",",
- " ((double) udmem) * 8.0, udmem/(1024L*1024L));",
- " else",
-#endif
- " printf(\"total bits available: %%8g (-w%%d)\\n\",",
- " ((double) (1L << (ssize-4)) * 16.0), ssize);",
- "#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",
- "#endif",
- "}",
+ " 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",
+ "#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;",
- "#endif",
- "#endif",
-
+ "{ 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\");",
- "#endif",
-#endif
+ "#ifdef PERMUTED",
+ " printf(\" + Process Scheduling Permutation\\n\");",
+ "#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);",
- "#endif",
+ " #ifdef R_XPT",
+ " printf(\" Restarted from checkpoint %%s.xpt\\n\", PanSource);",
+ " #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",
-
- "#ifndef BITSTATE",
+ " #endif",
+
+ " #ifndef BITSTATE",
"#if !defined(MA) || defined(COLLAPSE)",
- " nr3 = (double) (1L<<ssize)*sizeof(struct H_el *);",
- "#endif",
- "#else",
-#ifndef POWOW
+ " nr3 = (double) (ONE_L<<ssize)*sizeof(H_el *);",
+ "#endif",
+ " #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 *));",
- "#endif",
- "#endif",
+ " nr5 = (double) (maxdepth*sizeof(H_el *));",
+ "#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));",
- " }",
- "#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.);",
- " }",
- "#ifndef MA",
- " else",
- "#endif",
- "#endif",
- "#ifndef MA",
- " printf(\"%%-6.3f\tmemory usage (Mbyte)\\n\\n\",",
- " memcnt/1000000.);",
- "#endif",
+ " #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.);",
+ " }",
+ " 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",
+ " else",
+ " #endif",
+ "#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",
" */",
- "",
-"#if defined(HASH64) || defined(WIN64)",
- /* 64-bit Jenkins hash: http://burtleburtle.net/bob/c/lookup8.c */
+ "#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",
+ "",
+ "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,66 +4758,242 @@
" 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); \\",
- "}",
-"#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;",
- "",
+ "{ 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; \\",
+ "}",
+ "",
+ "#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;",
- " }",
- " c += length;",
- " switch (len) {",
+ " 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);",
- " j1 = c&nmask; j3 = a&7;", /* 1st bit */
- " j2 = b&nmask; j4 = (a>>3)&7;", /* 2nd bit */
- " K1 = c; K2 = b;", /* no nmask */
- "}",
- "void",
- "s_hash(uchar *cp, int om)",
- "{ d_hash(cp, om); /* sets K1 and K2 */",
+ "#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",
+ "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;",
- " else",
- "#endif", /* if (S_Tab != H_Tab) */
- " if (ssize < 8*WS)",
- " j1 = K1&mask;",
- " else",
- " j1 = K1;",
+ " j1_spin = K1 %% omaxdepth;",
+ " else",
+ "#endif",
+ " if (ssize < 8*WS)",
+ " j1_spin = K1&mask;",
+ " else",
+ " j1_spin = K1;",
"}",
"#ifndef RANDSTOR",
"int *prerand;",
"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 */",
- "#ifdef BITSTATE",
- " bstore = bstore_reg; /* 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",
+ " 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]);",
- " 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;",
- "#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;",
+ " else if (argc > 2 && argv[2][0] != '-') /* check next arg */",
+ " { trailfilename = argv[2];",
+ " argc--; argv++; /* skip next arg */",
+ " }",
+ " break;",
+ " case 'S': silent = 1; goto samething;",
+ "#else",
+ " fprintf(efd, \"options -r is for models with embedded C code\\n\");",
+ " break;",
+ "#endif",
+ " 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;",
- " else",
- " TMODE = _S_IREAD;",
- "#endif",
- "#ifdef OHASH",
- " fprintf(efd, \"warning: -DOHASH no longer supported (directive ignored)\\n\");",
- "#endif",
- "#ifdef JHASH",
- " fprintf(efd, \"warning: -DJHASH no longer supported (directive ignored)\\n\");",
- "#endif",
- "#ifdef HYBRID_HASH",
- " fprintf(efd, \"warning: -DHYBRID_HASH no longer supported (directive ignored)\\n\");",
- "#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",
+ " TMODE = S_IWRITE | S_IREAD;",
+ " else",
+ " TMODE = S_IREAD;",
+ "#endif",
+ "#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",
+ " #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",
+ "#if defined(T_RAND) && defined(ELSE_IN_GUARD)",
+ " #error cannot hide 'else' as guard in d_step, when using -DT_RAND",
+ "#endif",
+ "#ifdef BITSTATE",
" 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,69 +5714,97 @@
"#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)",
" 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);",
- "#endif",
- "#if defined(HAS_LAST)",
- " fprintf(efd, \"error: -DBFS not compatible with _last\\n\");",
- " exit(1);",
- "#endif",
- "#if defined(REACH)",
- " fprintf(efd, \"warning: -DREACH redundant when -DBFS is used\\n\");",
- "#endif",
- "#if defined(HAS_STACK)",
- " fprintf(efd, \"error: cannot use UnMatched qualifier on c_track with BFS\\n\");",
- " exit(1);",
- "#endif",
+ " #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",
+
+ "#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",
+
+ "#ifdef BFS_PAR",
+ " #ifdef NP",
+ " #error cannot combine -DBFS_PAR and -DNP",
+ " #undef NP",
+ " #endif",
+ "#endif",
+
+ "#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);",
- "#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",
+ " #error to use -DPEG use: spin -o3 -a",
+ "#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);",
- "#endif",
- " if (MA <= 0)",
- " { fprintf(efd, \"usage: -DMA=N with N > 0 and < VECTORSZ\\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",
"#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,202 +5817,147 @@
" }",
"#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",
- "#endif",
-
- "#ifndef BITSTATE",
- " if (Nrun > 1) HASH_NR = Nrun - 1;",
- "#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",
- "#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",
+ "#ifdef MEMLIM",
+ " memlim = ((double) MEMLIM) * (double) (1<<20); /* size in Mbyte */",
+ "#endif",
+ "#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",
+ "#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 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 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",
+ "#ifndef SAFETY",
+ " #if 0",
" if (!a_cycles",
- "#ifdef HAS_CODE",
+ " #ifdef HAS_CODE",
" && !readtrail",
- "#endif",
+ " #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 (",
- "#ifdef HAS_CODE",
- " !readtrail",
- "#endif",
- " && !state_tables)",
- " { fprintf(efd, \"warning: verification in BFS mode \");",
- " fprintf(efd, \"is restricted to safety properties\\n\");",
- " }",
- "#endif",
- "#endif",
- "#endif",
- "#ifndef SAFETY",
- " if (!a_cycles",
- "#ifdef HAS_CODE",
- " && !readtrail",
- "#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",
" 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,13 +5997,18 @@
"#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\");",
"#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",
- "#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-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 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;",
- "#endif",
-"#if 1",
+ "#ifdef MEMLIM",
+ " if (memcnt + (double) n > memlim)",
+ " { printf(\"pan: reached -DMEMLIM bound\\n\");",
+ " goto err;",
+ " }",
+ "#endif",
" 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)",
+ " {",
+ "#ifdef BFS_PAR",
+ " Uerror(\"out of non-shared memory\");",
+ "#endif",
+ " printf(\"pan: out of memory\\n\");",
+ "#ifdef MEMLIM",
"err:",
- "#endif",
- " printf(\"pan: out of memory\\n\");",
- "#if defined(MEMCNT) || defined(MEMLIM)",
" 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);",
- " break;",
- " }",
+ " { 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));",
- "#endif",
- " for (i = 1; i <= depth; i++)",
+ " if (write(fd, snap, strlen(snap)) < 0) return;",
+ "#endif",
+ "#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,13 +6549,16 @@
"#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)",
" 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\");",
- "#endif",
- "}\n",
+ " cpu_printf(\" sv_restor\\n\");",
+ "#endif",
+ "}",
+ "",
"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;",
+ " #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;",
+ " #ifdef BFS_PAR",
+ " bfs_fixmask(1); /* p_restor */",
+ " #endif",
+ "#endif",
+ " now._nr_pr += 1;",
"#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 (BASE > 0 && h > 0)",
- " ((P0 *)pptr(h))->_pid = h-BASE;",
- " else",
- " ((P0 *)pptr(h))->_pid = h;",
" i = stack->o_delqs;",
- " now._nr_pr += 1;",
- " if (!stack->lst) /* debugging */",
+ " 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;",
- "#endif",
- "#endif",
- " for ( ; k < k_end; k++)",
- " Mask[k] = 1;",
- "#endif",
- " if (!stack->lst) /* debugging */",
+ "#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",
+ " 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",
- "#ifndef XUSAFE",
+ " #endif",
+ "#endif",
+ " #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;",
+ " 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);",
- " vsize -= (int) q_skip[h];",
+ "#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 *));",
- "}",
- "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",
+ "{ S_Tab = (H_el **) emalloc(maxdepth*sizeof(H_el *));",
+ "}",
+ "#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\");",
- "#endif",
- " H_tab = tmp;",
- " trpt->ostate = Lstate;",
- " PUT++;",
- "}",
- "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 BITSTATE",
+ "done:",
+ "#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)",
+ " now._last = was_last;",
+ "#endif",
+ " return;",
+ "}",
+ "",
+ "#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 */
+
+ "#ifdef BITSTATE",
+ "void init_SS(ulong);",
+ "",
+ "void",
+ "sinit(void)",
+ "{",
+ " 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",
+ " #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));",
- "#endif",
-"#endif",
-"#if !defined(MA) || defined(COLLAPSE)",
- " H_tab = (struct H_el **)",
- " emalloc((1L<<ssize)*sizeof(struct H_el *));",
-"#endif",
+ " #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,22 +7700,36 @@
" 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\");",
" 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",
- "#ifdef VERBOSE",
- " printf(\"old state\\n\");",
- "#endif",
- " return 1; /* old state */",
+ " #endif",
+ " }",
+ " goto done;",
+ " }",
+ "#endif",
+ " ret_val = 1;",
+ "#ifdef VERBOSE",
+ " printf(\"old state\\n\");",
+ "#endif",
+ "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,34 +7803,140 @@
"}",
"#endif",
- "int",
- "hstore(char *vin, int nin) /* hash table storage */",
- "{ struct H_el *tmp, *ntmp, *olst = (struct H_el *) 0;",
+ "#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",
+ "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);",
" } 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 */
- " #endif",
+ " 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",
-
- "#ifndef SAFETY",
- "#ifndef NOCOMP",
+ " #endif",
+
+ " #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,41 +8091,110 @@
" 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",
" 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,54 +8202,86 @@
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;",
" 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",
" 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);",
- "#endif",
- " Lstate = (struct H_el *) tmp;",
- "#else",
- "#ifdef DEBUG",
- " dumpstate(-1, v, n, 0);",
- "#endif",
- "#endif",
+ " dumpstate(-1, v, n, tmp->tagged);",
+ "#endif",
+ " 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;",
- "}",
- "#endif",
+ "}", /* 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",
+ " ohash_hv = (volatile uint32_t *) sh_pre_malloc(x * (ulong) sizeof(uint32_t));",
+ "#endif",
+ " 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",
+ " 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",
+ "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",
- "void",
- "do_reach(void)",
- "{",
0,
};
diff -r 51b3bf8bc61b sys/src/cmd/spin/pangen2.c
--- a/sys/src/cmd/spin/pangen2.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/pangen2.c Wed Nov 22 00:21:47 2017 -0800
@@ -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,12 +126,33 @@
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
@@ -111,13 +160,14 @@
{
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, "#endif\n");
- fprintf(th, "#ifndef XUSAFE\n");
- fprintf(th, "#define XUSAFE\n");
- fprintf(th, "#endif\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 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,18 +358,33 @@
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)
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,24 +584,47 @@
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();
@@ -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,17 +1690,17 @@
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;
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,29 +2398,57 @@
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);
}
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:
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,31 +2550,37 @@
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");
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");
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,48 +3211,67 @@
{ 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;
}
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;
diff -r 51b3bf8bc61b sys/src/cmd/spin/pangen2.h
--- a/sys/src/cmd/spin/pangen2.h Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/pangen2.h Wed Nov 22 00:21:47 2017 -0800
@@ -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,6 +1038,47 @@
"#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",
@@ -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])",
@@ -788,6 +1120,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",
"#define BYTESIZE 32 /* 2^8 : 2^3 = 256:8 = 32 */",
diff -r 51b3bf8bc61b sys/src/cmd/spin/pangen3.c
--- a/sys/src/cmd/spin/pangen3.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/pangen3.c Wed Nov 22 00:21:47 2017 -0800
@@ -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,16 +26,18 @@
static SRC *frst = (SRC *) 0;
static SRC *skip = (SRC *) 0;
+extern int ltl_mode;
+
extern void sr_mesg(FILE *, int, int);
static void
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,73 +59,118 @@
putfnm_flush(int j)
{
if (lastfnm)
- fprintf(th, "{ %s, %d, %d }\n",
+ fprintf(tc, "{ \"%s\", %d, %d }\n", /* was th */
lastfnm->name,
lastfrom, j);
}
+static SRC *
+newsrc(int m, SRC *n)
+{ SRC *tmp;
+ tmp = (SRC *) emalloc(sizeof(SRC));
+ tmp->st = m;
+ tmp->nxt = n;
+ return tmp;
+}
+
void
putskip(int m) /* states that need not be reached */
-{ 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;
+{ 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;
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(tz, "};\n");
+
+ if (pid_is_claim(m) && !did_claim)
+ { fprintf(tz, "short *src_claim;\n");
+ did_claim++;
}
- putfnm_flush(j);
- fprintf(th, "};\n");
-
- if (m == claimnr)
- fprintf(th, "#define src_claim src_ln%d\n", m);
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;
diff -r 51b3bf8bc61b sys/src/cmd/spin/pangen3.h
--- a/sys/src/cmd/spin/pangen3.h Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/pangen3.h Wed Nov 22 00:21:47 2017 -0800
@@ -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 *) &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",
- " write(svfd, (uchar *) &now, vprefix-4*sizeof(int)); /* padd */",
+
+ " 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",
- " now._nr_pr += 1;",
" 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,78 +311,134 @@
" 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;",
+ " vsize += j;",
+ " #ifdef BFS_PAR",
+ " bfs_fixmask(2); /* addqueue */",
+ " #endif",
+ "#endif",
+
" now._nr_qs += 1;",
- " vsize += j;",
"#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",
0,
};
-static char *Addq11[] = {
+static const char *Addq11[] = {
"{ int j; uchar *z;\n",
"#ifdef HAS_SORTED",
" int k;",
@@ -362,13 +447,26 @@
" 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) {",
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,151 +678,311 @@
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);",
- 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 *R00[] = {
+ " NrStates[%d] = _nstates%d;",
0,
};
-static char *Code1[] = {
+static const char *R0a[] = {
+ " retrans(%d, _nstates%d, _start%d, src_ln%d, reached%d, loopstate%d);",
+ 0,
+};
+
+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) {",
" 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;",
" 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;",
" 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,13 +991,27 @@
"#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;",
" switch (((Q0 *)qptr(into))->_t) {",
0,
};
-char *R14[] = {
+const char *R14[] = {
" default: Uerror(\"bad queue - unsend\");",
" }",
" return _m;",
@@ -725,40 +1021,53 @@
"{ 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;",
" 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,65 +1075,353 @@
"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);",
"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,20 +1464,8 @@
"#ifdef VAR_RANGES",
" strcat(ctd, \"-DVAR_RANGES \");",
"#endif",
- "#ifdef HC0",
- " strcat(ctd, \"-DHC0 \");",
- "#endif",
- "#ifdef HC1",
- " strcat(ctd, \"-DHC1 \");",
- "#endif",
- "#ifdef HC2",
- " strcat(ctd, \"-DHC2 \");",
- "#endif",
- "#ifdef HC3",
- " strcat(ctd, \"-DHC3 \");",
- "#endif",
- "#ifdef HC4",
- " strcat(ctd, \"-DHC4 \");",
+ "#ifdef HC",
+ " strcat(ctd, \"-DHC \");",
"#endif",
"#ifdef CHECK",
" strcat(ctd, \"-DCHECK \");",
@@ -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);",
"}",
diff -r 51b3bf8bc61b sys/src/cmd/spin/pangen4.c
--- a/sys/src/cmd/spin/pangen4.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/pangen4.c Wed Nov 22 00:21:47 2017 -0800
@@ -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;
}
diff -r 51b3bf8bc61b sys/src/cmd/spin/pangen4.h
--- a/sys/src/cmd/spin/pangen4.h Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/pangen4.h Wed Nov 22 00:21:47 2017 -0800
@@ -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);",
"}",
"",
diff -r 51b3bf8bc61b sys/src/cmd/spin/pangen5.c
--- a/sys/src/cmd/spin/pangen5.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/pangen5.c Wed Nov 22 00:21:47 2017 -0800
@@ -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,14 +282,14 @@
continue;
g = fsm_tbl[t->to];
- if (!eligible(g->t))
+ if (!g || !eligible(g->t))
{
#define SINGLES
#ifdef SINGLES
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;
diff -r 51b3bf8bc61b sys/src/cmd/spin/pangen5.h
--- a/sys/src/cmd/spin/pangen5.h Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/pangen5.h Wed Nov 22 00:21:47 2017 -0800
@@ -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",
diff -r 51b3bf8bc61b sys/src/cmd/spin/pangen6.c
--- a/sys/src/cmd/spin/pangen6.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/pangen6.c Wed Nov 22 00:21:47 2017 -0800
@@ -1,20 +1,10 @@
/***** 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 */
-
-/* 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 */
+/*
+ * 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"
@@ -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)",
+ printf(" %s:%d (state %d)",
+ e->n?e->n->fn->name:"-",
e->n?e->n->ln:-1,
- e->n?e->n->fn->name:"-",
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
diff -r 51b3bf8bc61b sys/src/cmd/spin/pangen6.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/cmd/spin/pangen6.h Wed Nov 22 00:21:47 2017 -0800
@@ -0,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 64 892k 64 576k 0 0 576k 0 0:00:01 --:--:-- 0:00:01 622kmode:\\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,
+};
diff -r 51b3bf8bc61b sys/src/cmd/spin/pangen7.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/cmd/spin/pangen7.c Wed Nov 22 00:21:47 2017 -0800
@@ -0,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;
+ }
+}
diff -r 51b3bf8bc61b sys/src/cmd/spin/pangen7.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/cmd/spin/pangen7.h Wed Nov 22 00:21:47 2017 -0800
@@ -0,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,
+};
diff -r 51b3bf8bc61b sys/src/cmd/spin/reprosrc.c
--- a/sys/src/cmd/spin/reprosrc.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/reprosrc.c Wed Nov 22 00:21:47 2017 -0800
@@ -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 { ");
@@ -134,3 +133,252 @@
{
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);
+}
diff -r 51b3bf8bc61b sys/src/cmd/spin/run.c
--- a/sys/src/cmd/spin/run.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/run.c Wed Nov 22 00:21:47 2017 -0800
@@ -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,15 +13,18 @@
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;
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,24 +42,23 @@
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 *
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,13 +120,21 @@
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
@@ -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);
+ } }
+}
diff -r 51b3bf8bc61b sys/src/cmd/spin/sched.c
--- a/sys/src/cmd/spin/sched.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/sched.c Wed Nov 22 00:21:47 2017 -0800
@@ -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,19 +580,33 @@
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 ");
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,25 +797,33 @@
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));
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));
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,17 +1138,20 @@
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;
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);
diff -r 51b3bf8bc61b sys/src/cmd/spin/spin.h
--- a/sys/src/cmd/spin/spin.h Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/spin.h Wed Nov 22 00:21:47 2017 -0800
@@ -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,6 +12,15 @@
#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 */
@@ -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,12 +310,14 @@
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 *);
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
diff -r 51b3bf8bc61b sys/src/cmd/spin/spin.y
--- a/sys/src/cmd/spin/spin.y Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/spin.y Wed Nov 22 00:21:47 2017 -0800
@@ -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,20 +133,29 @@
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);
}
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,41 +189,84 @@
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;
}
;
-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);
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,23 +324,37 @@
s->type = CODE_DECL;
$$ = nn(ZN, C_CODE, ZN, ZN);
$$->sym = s;
+ $$->ln = $1->ln;
+ $$->fn = $1->fn;
has_code = 1;
}
;
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,21 +697,40 @@
| 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();
}
| '{' { 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,28 +794,25 @@
| '-' 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, $$);
}
| 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,18 +841,51 @@
{ $$ = 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; }
+ ;
+
+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; }
+ | 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 OR Expr { $$ = nn(ZN, OR, $1, $3); }
+ ;
+
+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 '(' full_expr ')' { if (!proper_enabler($3))
+ | PROVIDED l_par full_expr r_par { if (!proper_enabler($3))
{ non_fatal("invalid PROVIDED clause",
(char *)0);
$$ = ZN;
@@ -615,23 +898,6 @@
}
;
- /* an Expr cannot be negated - to protect Probe expressions */
-Expr : Probe { $$ = $1; }
- | '(' Expr ')' { $$ = $2; }
- | 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); }
- ;
-
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);
@@ -715,6 +984,138 @@
;
%%
+#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, ...)
{
diff -r 51b3bf8bc61b sys/src/cmd/spin/spinlex.c
--- a/sys/src/cmd/spin/spinlex.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/spinlex.c Wed Nov 22 00:21:47 2017 -0800
@@ -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 *);
-
-#if 1
-#define Token(y) { if (in_comment) goto again; \
- yylval = nn(ZN,0,ZN,ZN); return y; }
+static int last_token = 0;
#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);
-
-#if 1
-#define Getchar() ((Inlining<0)?getc(yyin):getinline())
-#define Ungetch(c) {if (Inlining<0) ungetc(c,yyin); else uninline(); }
-
-#else
+static void
+push_back(char *s)
+{
+ if (PushedBack + strlen(s) > 4094)
+ { fatal("select statement too large", 0);
+ }
+ strcat(pushedback, s);
+ PushedBack += strlen(s);
+}
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,15 +126,25 @@
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)
@@ -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_stack_size(FILE *fd)
+{ C_Added *r;
+ int cnt = 0;
+
+ 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");
+ }
+}
+
+void
c_add_stack(FILE *fd)
{ C_Added *r;
int cnt = 0;
- if ((!c_added && !c_tracked) || !has_stack) return;
-
+ if ((!c_added && !c_tracked) || !has_stack)
+ { return;
+ }
for (r = c_tracked; r; r = r->nxt)
if (r->ival != ZS)
- cnt++;
+ { cnt++;
+ }
- if (cnt == 0) return;
-
- fprintf(fd, " uchar c_stack[");
-
- cnt = 0;
- for (r = c_tracked; r; r = r->nxt)
- { if (r->ival == ZS) continue;
-
- 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,41 +1153,44 @@
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) {
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,20 +1534,104 @@
}
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 == '_')
{ 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;
}
diff -r 51b3bf8bc61b sys/src/cmd/spin/structs.c
--- a/sys/src/cmd/spin/structs.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/structs.c Wed Nov 22 00:21:47 2017 -0800
@@ -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,14 +30,16 @@
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",
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,9 +583,11 @@
int i, cnt; extern int IArgs;
if (n->sym->type != STRUCT
+ || in_for
|| is_explicit(n))
return n;
+
if (n->rgt
&& n->rgt->ntyp == '.'
&& n->rgt->lft
diff -r 51b3bf8bc61b sys/src/cmd/spin/sym.c
--- a/sys/src/cmd/spin/sym.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/sym.c Wed Nov 22 00:21:47 2017 -0800
@@ -1,25 +1,27 @@
/***** 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"
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);
+ 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, refers to global */
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 (context) /* in proctype */
- 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,14 +594,14 @@
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",
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);
} }
}
diff -r 51b3bf8bc61b sys/src/cmd/spin/tl.h
--- a/sys/src/cmd/spin/tl.h Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/tl.h Wed Nov 22 00:21:47 2017 -0800
@@ -1,16 +1,13 @@
/***** 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 */
-
-/* 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 <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);
diff -r 51b3bf8bc61b sys/src/cmd/spin/tl_buchi.c
--- a/sys/src/cmd/spin/tl_buchi.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/tl_buchi.c Wed Nov 22 00:21:47 2017 -0800
@@ -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 */
-
-/* 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"
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");
diff -r 51b3bf8bc61b sys/src/cmd/spin/tl_cache.c
--- a/sys/src/cmd/spin/tl_cache.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/tl_cache.c Wed Nov 22 00:21:47 2017 -0800
@@ -1,16 +1,13 @@
/***** 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 */
-
-/* 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"
@@ -24,9 +21,18 @@
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
@@ -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:
diff -r 51b3bf8bc61b sys/src/cmd/spin/tl_lex.c
--- a/sys/src/cmd/spin/tl_lex.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/tl_lex.c Wed Nov 22 00:21:47 2017 -0800
@@ -1,16 +1,13 @@
/***** 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 */
-
-/* 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 <stdlib.h>
#include <ctype.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)
diff -r 51b3bf8bc61b sys/src/cmd/spin/tl_main.c
--- a/sys/src/cmd/spin/tl_main.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/tl_main.c Wed Nov 22 00:21:47 2017 -0800
@@ -1,16 +1,13 @@
/***** 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 */
-
-/* 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"
@@ -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);
diff -r 51b3bf8bc61b sys/src/cmd/spin/tl_mem.c
--- a/sys/src/cmd/spin/tl_mem.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/tl_mem.c Wed Nov 22 00:21:47 2017 -0800
@@ -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"
diff -r 51b3bf8bc61b sys/src/cmd/spin/tl_parse.c
--- a/sys/src/cmd/spin/tl_parse.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/tl_parse.c Wed Nov 22 00:21:47 2017 -0800
@@ -1,16 +1,13 @@
/***** 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 */
-
-/* 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"
@@ -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);
diff -r 51b3bf8bc61b sys/src/cmd/spin/tl_rewrt.c
--- a/sys/src/cmd/spin/tl_rewrt.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/tl_rewrt.c Wed Nov 22 00:21:47 2017 -0800
@@ -1,16 +1,13 @@
/***** 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 */
-
-/* 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"
@@ -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)
diff -r 51b3bf8bc61b sys/src/cmd/spin/tl_trans.c
--- a/sys/src/cmd/spin/tl_trans.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/tl_trans.c Wed Nov 22 00:21:47 2017 -0800
@@ -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 */
-
-/* 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"
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;
diff -r 51b3bf8bc61b sys/src/cmd/spin/vars.c
--- a/sys/src/cmd/spin/vars.c Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/vars.c Wed Nov 22 00:21:47 2017 -0800
@@ -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,22 +39,54 @@
{ 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);
}
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,23 +185,26 @@
}
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
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;
maxcol100 892k 100 892k 0 0 892k 0 0:00:01 0:00:01 --:--:-- 659k
nr = 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);
} } }
}
diff -r 51b3bf8bc61b sys/src/cmd/spin/version.h
--- a/sys/src/cmd/spin/version.h Mon Nov 20 00:10:35 2017 +0100
+++ b/sys/src/cmd/spin/version.h Wed Nov 22 00:21:47 2017 -0800
@@ -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"
--
Ori Bernstein
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2017-11-22 8:23 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-22 8:23 [Patch] Update Spin to most recent version Ori Bernstein
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).