+++ /dev/null
-/*** Generated by Spin Version 5.1.6 -- 9 May 2008 ***/
-/*** From source: buffer.spin ***/
-
-#ifdef SC
-#define _FILE_OFFSET_BITS 64
-#endif
-#include <stdio.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#if defined(WIN32) || defined(WIN64)
-#include <time.h>
-#else
-#include <unistd.h>
-#include <sys/times.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#define Offsetof(X, Y) ((unsigned long)(&(((X *)0)->Y)))
-#ifndef max
-#define max(a,b) (((a)<(b)) ? (b) : (a))
-#endif
-#ifndef PRINTF
-int Printf(const char *fmt, ...); /* prototype only */
-#endif
-#include "pan.h"
-#ifdef LOOPSTATE
-double cnt_loops;
-#endif
-State A_Root; /* seed-state for cycles */
-State now; /* the full state-vector */
-#undef C_States
-#if defined(C_States) && defined(HAS_TRACK)
-void
-c_update(uchar *p_t_r)
-{
-#ifdef VERBOSE
- printf("c_update %u\n", p_t_r);
-#endif
-}
-void
-c_revert(uchar *p_t_r)
-{
-#ifdef VERBOSE
- printf("c_revert %u\n", p_t_r);
-#endif
-}
-#endif
-void
-globinit(void)
-{
-}
-void
-locinit4(int h)
-{
-}
-void
-locinit3(int h)
-{
-}
-void
-locinit2(int h)
-{
-}
-void
-locinit1(int h)
-{
-}
-void
-locinit0(int h)
-{
-}
-#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]--
-#endif
-#if !defined(SAFETY) && !defined(NOCOMP)
-#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
-#endif
-#ifdef MA
-#undef onstack_now
-#undef onstack_put
-#undef onstack_zap
-#define onstack_put() ;
-#define onstack_zap() gstore((char *) &now, vsize, 4)
-#else
-#if defined(FULLSTACK) && !defined(BITSTATE)
-#define onstack_put() trpt->ostate = Lstate
-#define onstack_zap() { \
- if (trpt->ostate) \
- trpt->ostate->tagged = \
- (S_A)? (trpt->ostate->tagged&~V_A) : 0; \
- }
-#endif
-#endif
-#ifndef NO_V_PROVISO
-#define V_PROVISO
-#endif
-#if !defined(NO_RESIZE) && !defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(SPACE) && NCORE==1
- #define AUTO_RESIZE
-#endif
-
-struct H_el {
- struct H_el *nxt;
-#ifdef FULLSTACK
- unsigned int tagged;
- #if defined(BITSTATE) && !defined(NOREDUCE) && !defined(SAFETY)
- unsigned int proviso;
- #endif
-#endif
-#if defined(CHECK) || (defined(COLLAPSE) && !defined(FULLSTACK))
- unsigned long st_id;
-#endif
-#if !defined(SAFETY) || defined(REACH)
- unsigned int D;
-#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
- unsigned short ln;
- #else
- unsigned long ln;
- #endif
-#endif
-#if defined(AUTO_RESIZE) && !defined(BITSTATE)
- unsigned long m_K1;
-#endif
- unsigned long state;
-} **H_tab, **S_Tab;
-
-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
-#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
- 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) || (NCORE>1)
- struct H_el *ostate; /* pointer to stored state */
-#endif
-#if defined(CNTRSTACK) && !defined(BFS)
- long j6, j7;
-#endif
- Trans *o_t;
-#ifdef SCHED
- /* based on Qadeer&Rehof, Tacas 2005, LNCS 3440, pp. 93-107 */
- #if NCORE>1
- #error "-DSCHED cannot be combined with -DNCORE (yet)"
- #endif
- int sched_limit;
-#endif
-#ifdef HAS_SORTED
- short ipt;
-#endif
- union {
- int oval;
- int *ovals;
- } bup;
-} Trail;
-Trail *trail, *trpt;
-FILE *efd;
-uchar *this;
-long maxdepth=10000;
-long omaxdepth=10000;
-#ifdef SCHED
-int sched_max = 10;
-#endif
-#ifdef PERMUTED
- uchar permuted = 1;
-#else
- uchar permuted = 0;
-#endif
-double quota; /* time limit */
-#if NCORE>1
-long z_handoff = -1;
-#endif
-#ifdef SC
-char *stackfile;
-#endif
-uchar *SS, *LL;
-uchar HASH_NR = 0;
-
-double memcnt = (double) 0;
-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;
-
-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
-};
-#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;
-#if defined(ZAPH) && defined(BITSTATE)
-double zstates = 0;
-#endif
-int c_init_run;
-#ifdef BFS
-double midrv=0, failedrv=0, revrv=0;
-#endif
-unsigned long 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;
-int whichtrail = 0, onlyproc = -1, silent = 0;
-#endif
-int state_tables=0, fairness=0, no_rck=0, Nr_Trails=0;
-char simvals[128];
-#ifndef INLINE
-int TstOnly=0;
-#endif
-unsigned long mask, nmask;
-#ifdef BITSTATE
-int ssize=23; /* 1 Mb */
-#else
-int ssize=19; /* 512K slots */
-#endif
-int hmax=0, svmax=0, smax=0;
-int Maxbody=0, XX;
-uchar *noptr; /* used by macro Pptr(x) */
-#ifdef VAR_RANGES
-void logval(char *, int);
-void dumpranges(void);
-#endif
-#ifdef MA
-#define INLINE_REV
-extern void dfa_init(unsigned short);
-extern int dfa_member(unsigned long);
-extern int dfa_store(uchar *);
-unsigned int maxgs = 0;
-#endif
-
-#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
-
-State comp_msk;
-uchar *Mask = (uchar *) &comp_msk;
-#ifdef COLLAPSE
-State comp_tmp;
-static char *scratch = (char *) &comp_tmp;
-#endif
-Stack *stack; /* for queues, processes */
-Svtack *svtack; /* for old state vectors */
-#ifdef BITSTATE
-static unsigned int hfns = 3; /* new default */
-#endif
-static unsigned long j1;
-static unsigned long K1, K2;
-static unsigned long j2, j3, j4;
-#ifdef BITSTATE
-static long udmem;
-#endif
-static long A_depth = 0;
-long depth = 0;
-#if NCORE>1
-long nr_handoffs = 0;
-#endif
-static uchar warned = 0, iterative = 0, exclusive = 0, like_java = 0, every_error = 0;
-static uchar noasserts = 0, noends = 0, bounded = 0;
-#if SYNC>0 && ASYNC==0
-void set_recvs(void);
-int no_recvs(int);
-#endif
-#if SYNC
-#define IfNotBlocked if (boq != -1) continue;
-#define UnBlock boq = -1
-#else
-#define IfNotBlocked /* cannot block */
-#define UnBlock /* don't bother */
-#endif
-
-#ifdef BITSTATE
-int (*bstore)(char *, int);
-int bstore_reg(char *, int);
-int bstore_mod(char *, int);
-#endif
-void active_procs(void);
-void cleanup(void);
-void do_the_search(void);
-void find_shorter(int);
-void iniglobals(void);
-void stopped(int);
-void wrapup(void);
-int *grab_ints(int);
-void ungrab_ints(int *, int);
-#ifndef NOBOUNDCHECK
-#define Index(x, y) Boundcheck(x, y, II, tt, t)
-#else
-#define Index(x, y) x
-#endif
-short Air[] = { (short) Air0, (short) Air1, (short) Air2, (short) Air3, (short) Air4, (short) Air5 };
-int
-addproc(int n)
-{ int j, h = now._nr_pr;
-#ifndef NOCOMP
- int k;
-#endif
- uchar *o_this = this;
-
-#ifndef INLINE
- 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)
-#endif
- if (h >= MAXPROC)
- Uerror("too many processes");
- switch (n) {
- case 0: j = sizeof(P0); break;
- case 1: j = sizeof(P1); break;
- case 2: j = sizeof(P2); break;
- case 3: j = sizeof(P3); break;
- case 4: j = sizeof(P4); break;
- case 5: j = sizeof(P5); break;
- default: Uerror("bad proc - addproc");
- }
- 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
- vsize += (int) proc_skip[h];
- proc_offset[h] = vsize;
-#ifdef SVDUMP
- 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
- write(svfd, (uchar *) &proc_offset[h], sizeof(int));
-#else
- write(svfd, (uchar *) &proc_offset[h], sizeof(short));
-#endif
- write(svfd, (uchar *) &now, vprefix-4*sizeof(int)); /* padd */
- }
-#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",
- (8*NFAIR)/2 - 2, NFAIR);
- printf("\trecompile with -DNFAIR=%d\n",
- 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);
- if (vsize >= VECTORSZ)
- { printf("pan: error, VECTORSZ too small, recompile pan.c");
- printf(" with -DVECTORSZ=N with N>%d\n", (int) vsize);
- Uerror("aborting");
- }
- memset((char *)pptr(h), 0, j);
- this = pptr(h);
- if (BASE > 0 && h > 0)
- ((P0 *)this)->_pid = h-BASE;
- else
- ((P0 *)this)->_pid = h;
- switch (n) {
- case 5: /* np_ */
- ((P5 *)pptr(h))->_t = 5;
- ((P5 *)pptr(h))->_p = 0;
- reached5[0] = 1;
- accpstate[5][1] = 1;
- break;
- case 4: /* :init: */
- ((P4 *)pptr(h))->_t = 4;
- ((P4 *)pptr(h))->_p = 41; reached4[41]=1;
- /* params: */
- /* locals: */
- ((P4 *)pptr(h))->i = 0;
- ((P4 *)pptr(h))->j = 0;
- ((P4 *)pptr(h))->sum = 0;
- ((P4 *)pptr(h))->commit_sum = 0;
-#ifdef VAR_RANGES
- logval(":init::i", ((P4 *)pptr(h))->i);
- logval(":init::j", ((P4 *)pptr(h))->j);
- logval(":init::sum", ((P4 *)pptr(h))->sum);
- logval(":init::commit_sum", ((P4 *)pptr(h))->commit_sum);
-#endif
-#ifdef HAS_CODE
- locinit4(h);
-#endif
- break;
- case 3: /* cleaner */
- ((P3 *)pptr(h))->_t = 3;
- ((P3 *)pptr(h))->_p = 8; reached3[8]=1;
- /* params: */
- /* locals: */
-#ifdef VAR_RANGES
-#endif
-#ifdef HAS_CODE
- locinit3(h);
-#endif
- break;
- case 2: /* reader */
- ((P2 *)pptr(h))->_t = 2;
- ((P2 *)pptr(h))->_p = 26; reached2[26]=1;
- /* params: */
- /* locals: */
- ((P2 *)pptr(h))->i = 0;
- ((P2 *)pptr(h))->j = 0;
-#ifdef VAR_RANGES
- logval("reader:i", ((P2 *)pptr(h))->i);
- logval("reader:j", ((P2 *)pptr(h))->j);
-#endif
-#ifdef HAS_CODE
- locinit2(h);
-#endif
- break;
- case 1: /* tracer */
- ((P1 *)pptr(h))->_t = 1;
- ((P1 *)pptr(h))->_p = 3; reached1[3]=1;
- /* params: */
- /* locals: */
- ((P1 *)pptr(h))->size = 1;
- ((P1 *)pptr(h))->prev_off = 0;
- ((P1 *)pptr(h))->new_off = 0;
- ((P1 *)pptr(h))->tmp_commit = 0;
- ((P1 *)pptr(h))->i = 0;
- ((P1 *)pptr(h))->j = 0;
-#ifdef VAR_RANGES
- logval("tracer:size", ((P1 *)pptr(h))->size);
- logval("tracer:prev_off", ((P1 *)pptr(h))->prev_off);
- logval("tracer:new_off", ((P1 *)pptr(h))->new_off);
- logval("tracer:tmp_commit", ((P1 *)pptr(h))->tmp_commit);
- logval("tracer:i", ((P1 *)pptr(h))->i);
- logval("tracer:j", ((P1 *)pptr(h))->j);
-#endif
-#ifdef HAS_CODE
- locinit1(h);
-#endif
- break;
- case 0: /* switcher */
- ((P0 *)pptr(h))->_t = 0;
- ((P0 *)pptr(h))->_p = 11; reached0[11]=1;
- /* params: */
- /* locals: */
- ((P0 *)pptr(h))->prev_off = 0;
- ((P0 *)pptr(h))->new_off = 0;
- ((P0 *)pptr(h))->tmp_commit = 0;
- ((P0 *)pptr(h))->size = 0;
-#ifdef VAR_RANGES
- logval("switcher:prev_off", ((P0 *)pptr(h))->prev_off);
- logval("switcher:new_off", ((P0 *)pptr(h))->new_off);
- logval("switcher:tmp_commit", ((P0 *)pptr(h))->tmp_commit);
- logval("switcher:size", ((P0 *)pptr(h))->size);
-#endif
-#ifdef HAS_CODE
- locinit0(h);
-#endif
- break;
- }
- this = o_this;
- return h-BASE;
-#ifndef NOBOUNDCHECK
-#undef Index
-#define Index(x, y) Boundcheck(x, y, II, tt, t)
-#endif
-}
-
-#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; }
-#endif
-#ifndef BITSTATE
-#ifdef COLLAPSE
-long
-col_p(int i, char *z)
-{ int j, k; unsigned long ordinal(char *, long, short);
- char *x, *y;
- P0 *ptr = (P0 *) pptr(i);
- switch (ptr->_t) {
- case 0: j = sizeof(P0); break;
- case 1: j = sizeof(P1); break;
- case 2: j = sizeof(P2); break;
- case 3: j = sizeof(P3); break;
- case 4: j = sizeof(P4); break;
- case 5: j = sizeof(P5); break;
- default: Uerror("bad proctype - collapse");
- }
- if (z) x = z; else x = scratch;
- y = (char *) ptr; k = proc_offset[i];
- for ( ; j > 0; j--, y++)
- if (!Mask[k++]) *x++ = *y;
- 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
-void
-run(void)
-{ /* int i; */
- memset((char *)&now, 0, sizeof(State));
- vsize = (unsigned long) (sizeof(State) - VECTORSZ);
-#ifndef NOVSZ
- now._vsz = vsize;
-#endif
-/* optional provisioning statements, e.g. to */
-/* set hidden variables, used as constants */
-#ifdef PROV
-#include PROV
-#endif
- settable();
- Maxbody = max(Maxbody, ((int) sizeof(P0)));
- Maxbody = max(Maxbody, ((int) sizeof(P1)));
- Maxbody = max(Maxbody, ((int) sizeof(P2)));
- Maxbody = max(Maxbody, ((int) sizeof(P3)));
- Maxbody = max(Maxbody, ((int) sizeof(P4)));
- Maxbody = max(Maxbody, ((int) sizeof(P5)));
- reached[0] = reached0;
- reached[1] = reached1;
- reached[2] = reached2;
- reached[3] = reached3;
- reached[4] = reached4;
- reached[5] = reached5;
- accpstate[0] = (uchar *) emalloc(nstates0);
- accpstate[1] = (uchar *) emalloc(nstates1);
- accpstate[2] = (uchar *) emalloc(nstates2);
- accpstate[3] = (uchar *) emalloc(nstates3);
- accpstate[4] = (uchar *) emalloc(nstates4);
- accpstate[5] = (uchar *) emalloc(nstates5);
- progstate[0] = (uchar *) emalloc(nstates0);
- progstate[1] = (uchar *) emalloc(nstates1);
- progstate[2] = (uchar *) emalloc(nstates2);
- progstate[3] = (uchar *) emalloc(nstates3);
- progstate[4] = (uchar *) emalloc(nstates4);
- progstate[5] = (uchar *) emalloc(nstates5);
- loopstate0 = loopstate[0] = (uchar *) emalloc(nstates0);
- loopstate1 = loopstate[1] = (uchar *) emalloc(nstates1);
- loopstate2 = loopstate[2] = (uchar *) emalloc(nstates2);
- loopstate3 = loopstate[3] = (uchar *) emalloc(nstates3);
- loopstate4 = loopstate[4] = (uchar *) emalloc(nstates4);
- loopstate5 = loopstate[5] = (uchar *) emalloc(nstates5);
- stopstate[0] = (uchar *) emalloc(nstates0);
- stopstate[1] = (uchar *) emalloc(nstates1);
- stopstate[2] = (uchar *) emalloc(nstates2);
- stopstate[3] = (uchar *) emalloc(nstates3);
- stopstate[4] = (uchar *) emalloc(nstates4);
- stopstate[5] = (uchar *) emalloc(nstates5);
- visstate[0] = (uchar *) emalloc(nstates0);
- visstate[1] = (uchar *) emalloc(nstates1);
- visstate[2] = (uchar *) emalloc(nstates2);
- visstate[3] = (uchar *) emalloc(nstates3);
- visstate[4] = (uchar *) emalloc(nstates4);
- visstate[5] = (uchar *) emalloc(nstates5);
- mapstate[0] = (short *) emalloc(nstates0 * sizeof(short));
- mapstate[1] = (short *) emalloc(nstates1 * sizeof(short));
- mapstate[2] = (short *) emalloc(nstates2 * sizeof(short));
- mapstate[3] = (short *) emalloc(nstates3 * sizeof(short));
- mapstate[4] = (short *) emalloc(nstates4 * sizeof(short));
- mapstate[5] = (short *) emalloc(nstates5 * sizeof(short));
-#ifdef HAS_CODE
-#ifdef HAS_CODE
-#ifdef HAS_CODE
-#ifdef HAS_CODE
-#ifdef HAS_CODE
-#ifdef HAS_CODE
- NrStates[0] = nstates0;
- NrStates[1] = nstates1;
- NrStates[2] = nstates2;
- NrStates[3] = nstates3;
- NrStates[4] = nstates4;
- NrStates[5] = nstates5;
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
- stopstate[0][endstate0] = 1;
- stopstate[1][endstate1] = 1;
- stopstate[2][endstate2] = 1;
- stopstate[3][endstate3] = 1;
- stopstate[4][endstate4] = 1;
- stopstate[5][endstate5] = 1;
- stopstate[1][48] = 1;
- retrans(0, nstates0, start0, src_ln0, reached0, loopstate0);
- retrans(1, nstates1, start1, src_ln1, reached1, loopstate1);
- retrans(2, nstates2, start2, src_ln2, reached2, loopstate2);
- retrans(3, nstates3, start3, src_ln3, reached3, loopstate3);
- retrans(4, nstates4, start4, src_ln4, reached4, loopstate4);
- 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);
- }
- iniglobals();
-#if defined(VERI) && !defined(NOREDUCE) && !defined(NP)
- if (!state_tables
-#ifdef HAS_CODE
- && !readtrail
-#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");
- printf("(never claims generated from LTL ");
- printf("formulae are stutter-invariant)\n");
- }
-#endif
- UnBlock; /* disable rendez-vous */
-#ifdef BITSTATE
- if (udmem)
- { udmem *= 1024L*1024L;
- #if NCORE>1
- if (!readtrail)
- { void init_SS(unsigned long);
- init_SS((unsigned long) udmem);
- } else
- #endif
- SS = (uchar *) emalloc(udmem);
- bstore = bstore_mod;
- } else
- #if NCORE>1
- { void init_SS(unsigned long);
- init_SS(ONE_L<<(ssize-3));
- }
- #else
- SS = (uchar *) emalloc(ONE_L<<(ssize-3));
- #endif
-#else
- hinit();
-#endif
-#if defined(FULLSTACK) && defined(BITSTATE)
- onstack_init();
-#endif
-#if defined(CNTRSTACK) && !defined(BFS)
- 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
- if (vprefix > 0)
- write(svfd, (uchar *) &vprefix, sizeof(int));
-#endif
-#ifdef VERI
- Addproc(VERI); /* never - pid = 0 */
-#endif
- active_procs(); /* started after never */
-#ifdef EVENT_TRACE
- now._event = start_event;
- reached[EVENT_TRACE][start_event] = 1;
-#endif
-#ifdef HAS_CODE
- globinit();
-#endif
-#ifdef BITSTATE
-go_again:
-#endif
- do_the_search();
-#ifdef BITSTATE
- if (--Nrun > 0 && HASH_CONST[++HASH_NR])
- { printf("Run %d:\n", HASH_NR);
- wrap_stats();
- printf("\n");
- 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 *));
-#endif
- nstates=nlinks=truncs=truncs2=ngrabs = 0;
- nlost=nShadow=hcmp = 0;
- Fa=Fh=Zh=Zn = 0;
- PUT=PROBE=ZAPS=Ccheck=Cholds = 0;
- goto go_again;
- }
-#endif
-}
-#ifdef HAS_PROVIDED
-int provided(int, uchar, int, Trans *);
-#endif
-#if NCORE>1
-#define GLOBAL_LOCK (0)
-#ifndef CS_N
-#define CS_N (256*NCORE)
-#endif
-#ifdef NGQ
-#define NR_QS (NCORE)
-#define CS_NR (CS_N+1) /* 2^N + 1, nr critical sections */
-#define GQ_RD GLOBAL_LOCK
-#define GQ_WR GLOBAL_LOCK
-#define CS_ID (1 + (int) (j1 & (CS_N-1))) /* mask: 2^N - 1, zero reserved */
-#define QLOCK(n) (1+n)
-#else
-#define NR_QS (NCORE+1)
-#define CS_NR (CS_N+3)
-#define GQ_RD (1)
-#define GQ_WR (2)
-#define CS_ID (3 + (int) (j1 & (CS_N-1)))
-#define QLOCK(n) (3+n)
-#endif
-
-void e_critical(int);
-void x_critical(int);
-
-#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, ...)
-{ 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
-int
-cpu_printf(const char *fmt, ...)
-{ va_list args;
- va_start(args, fmt);
- vprintf(fmt, args);
- va_end(args);
- return 1;
-}
-#endif
-int
-Printf(const char *fmt, ...)
-{ /* Make sure the args to Printf
- * are always evaluated (e.g., they
- * could contain a run stmnt)
- * but do not generate the output
- * during verification runs
- * unless explicitly wanted
- * If this fails on your system
- * compile SPIN itself -DPRINTF
- * and this code is not generated
- */
-#ifdef HAS_CODE
- if (readtrail)
- { va_list args;
- va_start(args, fmt);
- vprintf(fmt, args);
- va_end(args);
- return 1;
- }
-#endif
-#ifdef PRINTF
- va_list args;
- va_start(args, fmt);
- vprintf(fmt, args);
- va_end(args);
-#endif
- return 1;
-}
-extern void printm(int);
-#ifndef SC
-#define getframe(i) &trail[i];
-#else
-static long HHH, DDD, hiwater;
-static long CNT1, CNT2;
-static int stackwrite;
-static int stackread;
-static Trail frameptr;
-Trail *
-getframe(int d)
-{
- if (CNT1 == CNT2)
- return &trail[d];
-
- if (d >= (CNT1-CNT2)*DDD)
- return &trail[d - (CNT1-CNT2)*DDD];
-
- if (!stackread
- && (stackread = open(stackfile, 0)) < 0)
- { printf("getframe: cannot open %s\n", stackfile);
- wrapup();
- }
- if (lseek(stackread, d* (off_t) sizeof(Trail), SEEK_SET) == -1
- || read(stackread, &frameptr, sizeof(Trail)) != sizeof(Trail))
- { printf("getframe: frame read error\n");
- wrapup();
- }
- 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 unsigned int *search_terminated; /* to signal early termination */
-#endif
-void
-pan_exit(int val)
-{ void stop_timer(void);
- 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
- if (val == 2)
- { val = 0;
- } else
- { stop_timer();
- }
- exit(val);
-}
-#ifdef HAS_CODE
-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")))
- { *v = '\0'; v++;
- strcpy(buf[1-toggle], buf[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])
- + strlen(code_lookup[i].t)
- + strlen(w) > 2047)
- return s;
- strcat(buf[1-toggle], code_lookup[i].t);
- break;
- }
- strcat(buf[1-toggle], w);
- toggle = 1 - toggle;
- }
- buf[toggle][2047] = '\0';
- return buf[toggle];
-}
-#else
-char * transmognify(char *s) { return s; }
-#endif
-#ifdef HAS_CODE
-void
-add_src_txt(int ot, int tt)
-{ Trans *t;
- char *q;
-
- for (t = trans[ot][tt]; t; t = t->nxt)
- { printf("\t\t");
- q = transmognify(t->tp);
- for ( ; q && *q; q++)
- if (*q == '\n')
- printf("\\n");
- else
- putchar(*q);
- printf("\n");
- }
-}
-void
-wrap_trail(void)
-{ static int wrap_in_progress = 0;
- int i; short II;
- P0 *z;
-
- if (wrap_in_progress++) return;
-
- printf("spin: trail ends after %ld steps\n", depth);
- if (onlyproc >= 0)
- { if (onlyproc >= now._nr_pr) { pan_exit(0); }
- II = onlyproc;
- z = (P0 *)pptr(II);
- printf("%3ld: proc %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",
- src_all[i].src[z->_p]);
- break;
- }
- printf(" (state %2d)", z->_p);
- if (!stopstate[z->_t][z->_p])
- printf(" (invalid end state)");
- printf("\n");
- add_src_txt(z->_t, z->_p);
- pan_exit(0);
- }
- printf("#processes %d:\n", now._nr_pr);
- if (depth < 0) depth = 0;
- for (II = 0; II < now._nr_pr; II++)
- { z = (P0 *)pptr(II);
- printf("%3ld: proc %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",
- src_all[i].src[z->_p]);
- break;
- }
- printf(" (state %2d)", z->_p);
- if (!stopstate[z->_t][z->_p])
- printf(" (invalid end state)");
- printf("\n");
- add_src_txt(z->_t, z->_p);
- }
- c_globals();
- for (II = 0; II < now._nr_pr; II++)
- { z = (P0 *)pptr(II);
- c_locals(II, z->_t);
- }
-#ifdef ON_EXIT
- ON_EXIT;
-#endif
- pan_exit(0);
-}
-FILE *
-findtrail(void)
-{ FILE *fd;
- char fnm[512], *q;
- char MyFile[512];
- 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';
- 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';
- 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';
- sprintf(fnm, "%s%d.%s",
- MyFile, whichtrail, tprefix);
- *q = '.';
- fd = fopen(fnm, "r");
- }
- } else
- { sprintf(fnm, "%s.%s", MyFile, tprefix);
- fd = fopen(fnm, "r");
- if (fd == NULL && (q = strchr(MyFile, '.')))
- { *q = '\0';
- sprintf(fnm, "%s.%s", MyFile, tprefix);
- *q = '.';
- fd = fopen(fnm, "r");
- } }
- if (fd == NULL)
- { 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);
-
-void
-getrail(void)
-{ FILE *fd;
- char *q;
- int i, t_id, lastnever=-1; short II;
- Trans *t;
- P0 *z;
-
- 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");
- if (depth < 0)
- continue;
- 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) 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) 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);
- break; /* pan_exit(1); */
- }
-recovered:
- q = transmognify(t->tp);
- if (gui) simvals[0] = '\0';
- this = pptr(II);
- trpt->tau |= 1;
- if (!do_transit(t, II))
- { if (onlyproc >= 0 && II != onlyproc)
- goto moveon;
- 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");
- }
- if (onlyproc >= 0 && II != onlyproc)
- goto moveon;
- if (verbose)
- { printf("%3ld: proc %2d (%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 \"%s\" ",
- src_all[i].src[z->_p], PanSource);
- 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)
- { if (lastnever != (int) z->_p)
- { for (i = 0; src_all[i].src; i++)
- if (src_all[i].tp == (int) z->_t)
- { printf("MSC: ~G %d\n",
- src_all[i].src[z->_p]);
- break;
- }
- if (!src_all[i].src)
- printf("MSC: ~R %d\n", z->_p);
- }
- lastnever = z->_p;
- goto sameas;
- } else
- if (strcmp(procname[z->_t], ":np_:") != 0)
- {
-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]\n", q?q:"");
- } else if (!silent)
- { if (strlen(simvals) > 0) {
- printf("%3ld: proc %2d (%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 \"%s\" ",
- src_all[i].src[z->_p], PanSource);
- break;
- }
- printf("(state %d) [values: %s]\n", z->_p, simvals);
- }
- printf("%3ld: proc %2d (%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 \"%s\" ",
- src_all[i].src[z->_p], PanSource);
- break;
- }
- printf("(state %d) [%s]\n", z->_p, q?q:"");
- /* printf("\n"); */
- } }
-moveon: z->_p = t->st;
- }
- wrap_trail();
-}
-#endif
-int
-f_pid(int pt)
-{ int i;
- P0 *z;
- for (i = 0; i < now._nr_pr; i++)
- { z = (P0 *)pptr(i);
- if (z->_t == (unsigned) pt)
- return BASE+z->_pid;
- }
- return -1;
-}
-#ifdef VERI
-void check_claim(int);
-#endif
-
-#if !defined(HASH64) && !defined(HASH32)
- #define HASH32
-#endif
-#if defined(HASH32) && defined(SAFETY) && !defined(SFH) && !defined(SPACE)
- #define SFH
-#endif
-#if defined(SFH) && (defined(BITSTATE) || defined(COLLAPSE) || defined(HC) || defined(HASH64))
- #undef SFH
-#endif
-#if defined(SFH) && !defined(NOCOMP)
- #define NOCOMP /* go for speed */
-#endif
-#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 = K1; y = j3;
- for (;;)
- { if (!(SS[x%udmem]&(1<<y))) break;
- if (i == hfns) {
-#ifdef DEBUG
- printf("Old bitstate\n");
-#endif
- return 1;
- }
- x = (x + K2 + i);
- y = (y + j4) & 7;
- i++;
- }
-#ifdef RANDSTOR
- if (rand()%100 > RANDSTOR) return 0;
-#endif
- for (;;)
- { SS[x%udmem] |= (1<<y);
- if (i == hfns) break;
- x = (x + K2 + i);
- y = (y + j4) & 7;
- i++;
- }
-#ifdef DEBUG
- printf("New bitstate\n");
-#endif
- if (now._a_t&1)
- { nShadow++;
- }
- return 0;
-}
-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;
- for (;;)
- { if (!(SS[x]&(1<<y))) break;
- if (i == hfns) {
-#ifdef DEBUG
- printf("Old bitstate\n");
-#endif
- return 1;
- }
- x = (x + j1 + i) & nmask;
- y = (y + j4) & 7;
- i++;
- }
-#ifdef RANDSTOR
- if (rand()%100 > RANDSTOR) return 0;
-#endif
- for (;;)
- { SS[x] |= (1<<y);
- if (i == hfns) break;
- x = (x + j1 + i) & nmask;
- y = (y + j4) & 7;
- i++;
- }
-#ifdef DEBUG
- printf("New bitstate\n");
-#endif
- if (now._a_t&1)
- { nShadow++;
- }
- return 0;
-}
-#endif
-unsigned long TMODE = 0666; /* file permission bits for trail files */
-
-int trcnt=1;
-char snap[64], fnm[512];
-
-int
-make_trail(void)
-{ 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)
- { sprintf(fnm, "%s%d.%s",
- MyFile, Nr_Trails-1, tprefix);
- } else
- {
-#ifdef PUTPID
- sprintf(fnm, "%s%d.%s", MyFile, getpid(), tprefix);
-#else
- sprintf(fnm, "%s.%s", MyFile, tprefix);
-#endif
- }
- if ((fd = open(fnm, w_flags, TMODE)) < 0)
- { if ((q = strchr(MyFile, '.')))
- { *q = '\0';
- if (iterative == 0 && Nr_Trails-1 > 0)
- sprintf(fnm, "%s%d.%s",
- MyFile, Nr_Trails-1, tprefix);
- else
- sprintf(fnm, "%s.%s", MyFile, tprefix);
- *q = '.';
- fd = open(fnm, w_flags, TMODE);
- } }
- if (fd < 0)
- { printf("pan: cannot create %s\n", fnm);
- perror("cause");
- } else
- {
-#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;
-}
-
-#ifndef FREQ
-#define FREQ (1000000)
-#endif
-#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;
- int sz;
- int nrpr;
- int nrqs;
- char *po;
- char *qo;
- char *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;
-
-#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)
-#else
- #define RFLAGS (O_RDONLY)
- #define WFLAGS (O_CREAT|O_WRONLY|O_TRUNC)
-#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);
-
-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)
- { 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 */
- }
- bfs_size_limit++;
-#endif
- h->sv = (State *) emalloc(sizeof(State) - VECTORSZ + n);
- }
-
- memcpy((char *)h->sv, (char *)&now, n);
- return h;
-}
-
-EV_Hold *
-getsv_mask(int n)
-{ EV_Hold *h;
- static EV_Hold *kept = (EV_Hold *) 0;
-
- for (h = kept; h; h = h->nxt)
- if (n == h->sz
- && (memcmp((char *) Mask, (char *) h->sv, n) == 0)
- && (now._nr_pr == h->nrpr)
- && (now._nr_qs == h->nrqs)
-#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))
- break;
- if (!h)
- { h = (EV_Hold *) emalloc(sizeof(EV_Hold));
- h->sz = n;
- h->nrpr = now._nr_pr;
- h->nrqs = now._nr_qs;
-
- h->sv = (char *) emalloc(n * sizeof(char));
- memcpy((char *) h->sv, (char *) Mask, n);
-
- if (now._nr_pr > 0)
- { 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
- h->po = (char *) emalloc(now._nr_pr * sizeof(short));
- memcpy((char *) h->po, (char *) proc_offset, now._nr_pr * sizeof(short));
-#endif
- }
- if (now._nr_qs > 0)
- { 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
- h->qo = (char *) emalloc(now._nr_qs * sizeof(short));
- memcpy((char *) h->qo, (char *) q_offset, now._nr_qs * sizeof(short));
-#endif
- }
-
- h->nxt = kept;
- kept = h;
- }
- return h;
-}
-
-void
-freesv(SV_Hold *p)
-{ SV_Hold *h, *oh;
-
- oh = (SV_Hold *) 0;
- for (h = svfree; h; oh = h, h = h->nxt)
- if (h->sz >= p->sz)
- break;
-
- if (!oh)
- { p->nxt = svfree;
- svfree = p;
- } else
- { p->nxt = h;
- oh->nxt = p;
- }
-}
-
-BFS_Trail *
-get_bfs_frame(void)
-{ BFS_Trail *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->frame = (Trail *) emalloc(sizeof(Trail));
- return t;
-}
-
-void
-push_bfs(Trail *f, int d)
-{ BFS_Trail *t;
-
- t = get_bfs_frame();
- memcpy((char *)t->frame, (char *)f, sizeof(Trail));
- t->frame->o_tt = d; /* depth */
-
- t->boq = boq;
- t->onow = getsv(vsize);
- t->omask = getsv_mask(vsize);
-#if defined(FULLSTACK) && defined(Q_PROVISO)
- t->lstate = Lstate;
-#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
-}
-
-Trail *
-pop_bfs(void)
-{ BFS_Trail *t;
-
- if (!bfs_trail)
- 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
-
- t->nxt = bfs_free;
- bfs_free = t;
-
- vsize = t->onow->sz;
- boq = t->boq;
-#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);
- memcpy((uchar *) Mask, (uchar *) t->omask->sv, vsize);
- if (now._nr_pr > 0)
-#if VECTORSZ>32000
- { memcpy((char *)proc_offset, (char *)t->omask->po, now._nr_pr * sizeof(int));
-#else
- { memcpy((char *)proc_offset, (char *)t->omask->po, now._nr_pr * sizeof(short));
-#endif
- memcpy((char *)proc_skip, (char *)t->omask->ps, now._nr_pr * sizeof(uchar));
- }
- if (now._nr_qs > 0)
-#if VECTORSZ>32000
- { memcpy((uchar *)q_offset, (uchar *)t->omask->qo, now._nr_qs * sizeof(int));
-#else
- { memcpy((uchar *)q_offset, (uchar *)t->omask->qo, now._nr_qs * sizeof(short));
-#endif
- memcpy((uchar *)q_skip, (uchar *)t->omask->qs, now._nr_qs * sizeof(uchar));
- }
-#ifdef BFS_DISK
- if (t->onow->sv != (State *) 0)
-#endif
- freesv(t->onow); /* omask not freed */
-#ifdef CHECK
- printf("POP %u (%d)\n", t->frame, t->frame->o_tt);
-#endif
- return t->frame;
-}
-
-void
-store_state(Trail *ntrpt, int shortcut, short oboq)
-{
-#ifdef VERI
- Trans *t2 = (Trans *) 0;
- uchar ot; int tt, E_state;
- uchar o_opm = trpt->o_pm, *othis = this;
-
- if (shortcut)
- {
-#ifdef VERBOSE
- printf("claim: shortcut\n");
-#endif
- goto store_it; /* no claim move */
- }
-
- this = (((uchar *)&now)+proc_offset[0]); /* 0 = never claim */
- trpt->o_pm = 0;
-
- tt = (int) ((P0 *)this)->_p;
- ot = (uchar) ((P0 *)this)->_t;
-
-#ifdef HAS_UNLESS
- E_state = 0;
-#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
- if (do_transit(t2, 0))
- {
-#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
- E_state = t2->e_trans;
-#endif
- if (t2->st > 0)
- { ((P0 *)this)->_p = t2->st;
- reached[ot][t2->st] = 1;
-#ifndef NOCLAIM
- check_claim(t2->st);
-#endif
- }
- if (now._nr_pr == 0) /* claim terminated */
- uerror("end state in claim reached");
-
-#ifdef PEG
- peg[t2->forw]++;
-#endif
- trpt->o_pm |= 1;
- if (t2->atom&2)
- Uerror("atomic in claim not supported in BFS mode");
-store_it:
-
-#endif
-
-#ifdef BITSTATE
- if (!bstore((char *)&now, vsize))
-#else
-#ifdef MA
- if (!gstore((char *)&now, vsize, 0))
-#else
- if (!hstore((char *)&now, vsize))
-#endif
-#endif
- { static long sdone = (long) 0; long ndone;
- nstates++;
-#ifndef NOREDUCE
- trpt->tau |= 64;
-#endif
- ndone = (unsigned long) (nstates/((double) 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)
- { Trail *x;
- x = (Trail *) trpt->ostate; /* pre-rv state */
- if (x) x->o_pm |= 4; /* mark success */
- }
-#endif
- push_bfs(ntrpt, trpt->o_tt+1);
- } else
- { truncs++;
-#if !defined(NOREDUCE) && defined(FULLSTACK) && defined(Q_PROVISO)
-#if !defined(BITSTATE)
- if (Lstate && Lstate->tagged) trpt->tau |= 64;
-#else
- if (trpt->tau&32)
- { BFS_Trail *tprov;
- for (tprov = bfs_trail; tprov; tprov = tprov->nxt)
- 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
- ((P0 *)this)->_p = tt; /* reset claim */
- if (t2)
- do_reverse(t2, 0, 0);
- else
- break;
- } }
- this = othis;
- trpt->o_pm = o_opm;
-#endif
-}
-
-Trail *ntrpt;
-
-void
-bfs(void)
-{ Trans *t; Trail *otrpt, *x;
- uchar _n, _m, ot, nps = 0;
- int tt, E_state;
- short II, From = (short) (now._nr_pr-1), To = BASE;
- short oboq = boq;
-
- ntrpt = (Trail *) emalloc(sizeof(Trail));
- trpt->ostate = (struct H_el *) 0;
- trpt->tau = 0;
-
- trpt->o_tt = -1;
- store_state(ntrpt, 0, oboq); /* initial state */
-
- while ((otrpt = pop_bfs())) /* also restores now */
- { memcpy((char *) trpt, (char *) otrpt, sizeof(Trail));
-#if defined(C_States) && (HAS_TRACK==1)
- c_revert((uchar *) &(now.c_state[0]));
-#endif
- if (trpt->o_pm & 4)
- {
-#ifdef VERBOSE
- printf("Revisit of atomic not needed (%d)\n",
- trpt->o_pm);
-#endif
- continue;
- }
-#ifndef NOREDUCE
- nps = 0;
-#endif
- if (trpt->o_pm == 8)
- { revrv++;
- if (trpt->tau&8)
- {
-#ifdef VERBOSE
- printf("Break atomic (pm:%d,tau:%d)\n",
- trpt->o_pm, trpt->tau);
-#endif
- trpt->tau &= ~8;
- }
-#ifndef NOREDUCE
- else if (trpt->tau&32)
- {
-#ifdef VERBOSE
- printf("Void preselection (pm:%d,tau:%d)\n",
- trpt->o_pm, trpt->tau);
-#endif
- trpt->tau &= ~32;
- nps = 1; /* no preselection in repeat */
- }
-#endif
- }
- trpt->o_pm &= ~(4|8);
- if (trpt->o_tt > mreached)
- { mreached = trpt->o_tt;
- if (mreached%10 == 0)
- { snapshot();
- } }
- depth = trpt->o_tt;
- if (depth >= maxdepth)
- {
-#if SYNC
- Trail *x;
- if (boq != -1)
- { x = (Trail *) trpt->ostate;
- if (x) x->o_pm |= 4; /* not failing */
- }
-#endif
- truncs++;
- if (!warned)
- { warned = 1;
- printf("error: max search depth too small\n");
- }
- if (bounded)
- uerror("depth limit reached");
- continue;
- }
-#ifndef NOREDUCE
- if (boq == -1 && !(trpt->tau&8) && 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)
- { Ccheck++;
- if (!q_cond(II, t))
- continue;
- Cholds++;
- }
- From = To = II;
- trpt->tau |= 32; /* preselect marker */
-#ifdef DEBUG
- printf("%3d: proc %d PreSelected (tau=%d)\n",
- depth, II, trpt->tau);
-#endif
- goto MainLoop;
- } }
- trpt->tau &= ~32;
-#endif
-Repeat:
- if (trpt->tau&8) /* atomic */
- { From = To = (short ) trpt->pr;
- nlinks++;
- } else
- { From = now._nr_pr-1;
- To = BASE;
- }
-MainLoop:
- _n = _m = 0;
- for (II = From; II >= To; II -= 1)
- {
- this = (((uchar *)&now)+proc_offset[II]);
- tt = (int) ((P0 *)this)->_p;
- ot = (uchar) ((P0 *)this)->_t;
-#if SYNC
- /* no rendezvous with same proc */
- 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_event = now._event;
-#endif
-#ifdef HAS_PROVIDED
- if (!provided(II, ot, tt, t)) continue;
-#endif
-#ifdef HAS_UNLESS
- E_state = 0;
-#endif
- for (t = trans[ot][tt]; t; t = t->nxt)
- {
-#ifdef HAS_UNLESS
- if (E_state > 0
- && E_state != t->e_trans)
- break;
-#endif
- 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 CHECK
- printf("%3d: 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);
-#endif
-#ifdef HAS_UNLESS
- E_state = t->e_trans;
-#if SYNC>0
- if (t->e_trans > 0 && (boq != -1 /* || oboq != -1 */))
- { fprintf(efd, "error: the use of rendezvous stmnt in the escape clause\n");
- fprintf(efd, " of 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;
- 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
- now._event = trpt->o_event;
-#endif
-
- /* undo move and continue */
- trpt++; /* this is where ovals and ipt are set */
- do_reverse(t, II, _m); /* restore now. */
- trpt--;
-#ifdef CHECK
- #if NCORE>1
- enter_critical(GLOBAL_LOCK); /* in verbose mode only */
- printf("cpu%d: ", core_id);
- #endif
- 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);
- #if NCORE>1
- leave_critical(GLOBAL_LOCK);
- #endif
-#endif
- reached[ot][t->st] = 1;
- reached[ot][tt] = 1;
-
- ((P0 *)this)->_p = tt;
- _n |= _m;
- } }
-#ifndef NOREDUCE
- /* preselected - no succ definitely outside stack */
- if ((trpt->tau&32) && !(trpt->tau&64))
- { From = now._nr_pr-1; To = BASE;
-#ifdef DEBUG
- cpu_printf("%3d: 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 MainLoop;
- }
- trpt->tau &= ~(32|64);
-#endif
- if (_n != 0)
- continue;
-#ifdef DEBUG
- printf("%3d: no move [II=%d, tau=%d, boq=%d, _nr_pr=%d]\n",
- depth, II, trpt->tau, boq, now._nr_pr);
-#endif
- if (boq != -1)
- { failedrv++;
- 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
- printf("\treset state of %d from %d to %d\n",
- otrpt->pr, ((P0 *)this)->_p, otrpt->st);
-#endif
- ((P0 *)this)->_p = otrpt->st;
- unsend(boq); /* retract rv offer */
- boq = -1;
- push_bfs(x, x->o_tt);
-#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
- } 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",
- depth, II+1);
-#endif
- goto Repeat;
- }
-
- if (!(trpt->tau&1)) /* didn't try timeout yet */
- { trpt->tau |= 1;
-#ifdef DEBUG
- printf("%d: timeout\n", depth);
-#endif
- goto MainLoop;
- }
-#ifndef VERI
- if (!noends && !a_cycles && !endstate())
- uerror("invalid end state");
-#endif
- } }
-}
-
-void
-putter(Trail *trpt, int fd)
-{ long j;
-
- if (!trpt) return;
-
- if (trpt != (Trail *) trpt->ostate)
- putter((Trail *) trpt->ostate, fd);
-
- if (trpt->o_t)
- { sprintf(snap, "%d:%d:%d\n",
- trcnt++, trpt->pr, trpt->o_t->t_id);
- j = strlen(snap);
- if (write(fd, snap, j) != j)
- { printf("pan: error writing %s\n", fnm);
- pan_exit(1);
- } }
-}
-
-void
-nuerror(char *str)
-{ 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
- trcnt = 1;
- putter(trpt, fd);
- if (ntrpt->o_t)
- { 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);
- } }
- close(fd);
- if (errors >= upto && upto != 0)
- { wrapup();
- }
-}
-#endif
-#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 usefule -- 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)
-#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];
- volatile char m_Mask [(VMAX + 7)/8];
- 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];
-#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
-#endif
-
-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;
-volatile int *prfull;
-volatile int *prcnt;
-volatile int *prmax;
-
-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 *);
-#if 0
-void enter_critical(int);
-void leave_critical(int);
-#endif
-
-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, (int) (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", 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, *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 */
- {
-#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",
- worker_pids[i], (dwExitCode == STILL_ACTIVE));
-#else
- sprintf(b, "kill -%d %d", SIGKILL, worker_pids[i]);
- 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)
- { sprintf(b, "kill -%d %d", SIGINT, worker_pids[0]);
- system(b); /* warn the root process */
- printf("cpu%d: %s\n", core_id, b);
- issued_kill++;
- } }
-}
-
-#define iam_alive() is_alive[core_id]++
-
-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>%d)\n", z_handoff);
- #else
- { printf("hint: this search may be faster if compiled without -DNGQ, with -DUSE_DISK, ");
- printf("or with a larger -zN (N>%d)\n", z_handoff);
- #endif
- }
- leave_critical(GLOBAL_LOCK);
-}
-
-#ifndef MAX_DSK_FILE
- #define MAX_DSK_FILE 1000000 /* default is max 1M states per file */
-#endif
-
-void
-multi_usage(FILE *fd)
-{ static int warned = 0;
- if (warned > 0) { return; } else { warned++; }
- fprintf(fd, "\n");
- fprintf(fd, "Defining multi-core mode:\n\n");
- fprintf(fd, " -DDUAL_CORE --> same as -DNCORE=2\n");
- fprintf(fd, " -DQUAD_CORE --> same as -DNCORE=4\n");
- fprintf(fd, " -DNCORE=N --> enables multi_core verification if N>1\n");
- fprintf(fd, "\n");
- fprintf(fd, "Additional directives supported in multi-core mode:\n\n");
- fprintf(fd, " -DSEP_STATE --> forces separate statespaces instead of a single shared state space\n");
- fprintf(fd, " -DNUSE_DISK --> use disk for storing states when a work queue overflows\n");
- fprintf(fd, " -DMAX_DSK_FILE --> max nr of states per diskfile (%d)\n", MAX_DSK_FILE);
- fprintf(fd, " -DFULL_TRAIL --> support full error trails (increases memory use)\n");
- fprintf(fd, "\n");
- fprintf(fd, "More advanced use (should rarely need changing):\n\n");
- fprintf(fd, " To change the nr of states that can be stored in the global queue\n");
- fprintf(fd, " (lower numbers allow for more states to be stored, prefer multiples of 8):\n");
- fprintf(fd, " -DVMAX=N --> upperbound on statevector for handoffs (N=%d)\n", VMAX);
- fprintf(fd, " -DPMAX=N --> upperbound on nr of procs (default: N=%d)\n", PMAX);
- fprintf(fd, " -DQMAX=N --> upperbound on nr of channels (default: N=%d)\n", QMAX);
- fprintf(fd, "\n");
- 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");
- 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;
-
-struct 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 %d)\n",
- core_id, depth);
- }
-}
-#endif
-
-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;
- 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);
- 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
- if (memcnt + (double) n > memlim)
- { printf("cpu0: S %8g + %d Kb exceeds memory limit of %8g Mb\n",
- memcnt/1024., 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",
- 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++;
- 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");
- }
- #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)
- { 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 *);
-
- 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 = (struct H_el **) emalloc(n);
- #endif
-#else
- #ifndef MEMLIM
- #warning MEMLIM not set
- #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 = (struct 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 0.000000\n", SEG_SIZE);
- }
- if (SEG_SIZE >= 1024.)
- { goto shm_more;
- }
- 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 *);
-
- 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
-}
-
- /* 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;
- }
- #else
- #error missing definition of test and set operation for this platform
- #endif
-
-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 %d 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 BFS is not supported with multi-core
-#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)
- { 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 */
- }
- if (verbose)
- { cpu_printf("starting core_id %d -- pid %d\n", core_id, getpid());
- }
-#if defined(SEP_HEAP) && !defined(SEP_STATE)
- { 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
-
-struct 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 (struct 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
- 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 (struct H_el *) rval;
-#else
- return (struct 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)
- { 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;
- *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);
- } }
- return rval;
-}
-#endif
-
-int
-unpack_state(SM_frame *f, int from_q)
-{ int i, j;
- static struct 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);
- for (i = j = 0; i < VMAX; i++, j = (j+1)%8)
- { Mask[i] = (f->m_Mask[i/8] & (1<<j)) ? 1 : 0;
- }
- 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];
- 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(" line %3d \"%s\" ",
- src_all[j].src[z->_p], PanSource);
- 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)
-{ 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)
-#define TargetQ_NotFull(n) (m_workq[n][prfree[n]].m_vsize == 0)
-
-int
-AllQueuesEmpty(void)
-{ int q;
-#ifndef NGQ
- if (*grcnt != 0)
- { return 0;
- }
-#endif
- for (q = 0; q < NCORE; q++)
- { if (prcnt[q] != 0)
- { 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", 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);
- 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);
- } }
-
- 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);
- 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);
- } }
-
- 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)
- #else
- if (TargetQ_NotFull(q)
- && (dfs_phase2 == 0 || prcnt[core_id] > 0))
- #endif
- { mem_put(q);
- 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)
-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)
- { 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 *);
- #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 = (struct H_el **) emalloc(n);
- #endif
-#else
- #ifndef MEMLIM
- #warning MEMLIM not set
- #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 = (struct 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)
-{ 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 BFS is not supported in multi-core mode
-#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
-
-#ifdef BITSTATE
-void
-init_SS(unsigned long n)
-{
- SS = (uchar *) prep_shmid_S((size_t) n);
- init_HT(0L);
-}
-#endif
-
-#endif
-clock_t start_time;
-#if NCORE>1
-clock_t crash_stamp;
-#endif
-#if !defined(WIN32) && !defined(WIN64)
-struct tms start_tm;
-#endif
-
-void
-start_timer(void)
-{
-#if defined(WIN32) || defined(WIN64)
- start_time = clock();
-#else
- start_time = times(&start_tm);
-#endif
-}
-
-void
-stop_timer(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 (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
- 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));
- } }
-#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
-
-void
-do_the_search(void)
-{ int i;
- depth = mreached = 0;
- trpt = &trail[0];
-#ifdef VERI
- trpt->tau |= 4; /* the claim moves first */
-#endif
- for (i = 0; i < (int) now._nr_pr; i++)
- { P0 *ptr = (P0 *) pptr(i);
-#ifndef NP
- if (!(trpt->o_pm&2)
- && accpstate[ptr->_t][ptr->_p])
- { trpt->o_pm |= 2;
- }
-#else
- if (!(trpt->o_pm&4)
- && 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
-#ifndef NOCOMP
- 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
-#endif
-#ifndef NOFAIR
- if (fairness
- && (a_cycles && (trpt->o_pm&2)))
- { now._a_t = 2; /* set the A-bit */
- now._cnt[0] = now._nr_pr + 1;
-#ifdef VERBOSE
- printf("%3d: 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]));
-#endif
-#ifdef HAS_CODE
- if (readtrail) getrail(); /* no return */
-#endif
- start_timer();
-#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
- #if RANDOMIZE>0
- srand(RANDOMIZE);
- #else
- srand(123);
- #endif
-#endif
-#if NCORE>1
- mem_get();
-#else
- new_state(); /* start 1st DFS */
-#endif
-#endif
-}
-#ifdef INLINE_REV
-uchar
-do_reverse(Trans *t, short II, uchar M)
-{ uchar _m = M;
- int tt = (int) ((P0 *)this)->_p;
-#include REVERSE_MOVES
-R999: return _m;
-}
-#endif
-#ifndef INLINE
-#ifdef EVENT_TRACE
-static char _tp = 'n'; static int _qid = 0;
-#endif
-uchar
-do_transit(Trans *t, short II)
-{ uchar _m = 0;
- int tt = (int) ((P0 *)this)->_p;
-#ifdef M_LOSS
- uchar delta_m = 0;
-#endif
-#ifdef EVENT_TRACE
- short oboq = boq;
- uchar ot = (uchar) ((P0 *)this)->_t;
- if (ot == EVENT_TRACE) boq = -1;
-#define continue { boq = oboq; return 0; }
-#else
-#define continue return 0
-#ifdef SEPARATE
- uchar ot = (uchar) ((P0 *)this)->_t;
-#endif
-#endif
-#include FORWARD_MOVES
-P999:
-#ifdef EVENT_TRACE
- if (ot == EVENT_TRACE) boq = oboq;
-#endif
- return _m;
-#undef continue
-}
-#ifdef EVENT_TRACE
-void
-require(char tp, int qid)
-{ Trans *t;
- _tp = tp; _qid = qid;
-
- if (now._event != endevent)
- for (t = trans[EVENT_TRACE][now._event]; t; t = t->nxt)
- { if (do_transit(t, EVENT_TRACE))
- { now._event = t->st;
- reached[EVENT_TRACE][t->st] = 1;
-#ifdef VERBOSE
- printf(" event_trace move to -> %d\n", t->st);
-#endif
-#ifndef BFS
-#ifndef NP
- if (accpstate[EVENT_TRACE][now._event])
- (trpt+1)->o_pm |= 2;
-#else
- if (progstate[EVENT_TRACE][now._event])
- (trpt+1)->o_pm |= 4;
-#endif
-#endif
-#ifdef NEGATED_TRACE
- if (now._event == endevent)
- {
-#ifndef BFS
- depth++; trpt++;
-#endif
- uerror("event_trace error (all events matched)");
-#ifndef BFS
- trpt--; depth--;
-#endif
- break;
- }
-#endif
- for (t = t->nxt; t; t = t->nxt)
- { if (do_transit(t, EVENT_TRACE))
- Uerror("non-determinism in event-trace");
- }
- return;
- }
-#ifdef VERBOSE
- else
- printf(" event_trace miss '%c' -- %d, %d, %d\n",
- tp, qid, now._event, t->forw);
-#endif
- }
-#ifdef NEGATED_TRACE
- now._event = endevent; /* only 1st try will count -- fixed 4.2.6 */
-#else
-#ifndef BFS
- depth++; trpt++;
-#endif
- uerror("event_trace error (no matching event)");
-#ifndef BFS
- trpt--; depth--;
-#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
- if (pid == iam)
- Uerror("used: enabled(pid=thisproc)");
- if (pid < 0 || pid >= (int) now._nr_pr)
- return 0;
- this = pptr(pid);
- TstOnly = 1;
- tt = (int) ((P0 *)this)->_p;
- ot = (uchar) ((P0 *)this)->_t;
- for (t = trans[ot][tt]; t; t = t->nxt)
- if (do_transit(t, (short) pid))
- { res = 1;
- break;
- }
- TstOnly = 0;
- this = othis;
- return res;
-}
-#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= %6.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)
-{
-#if NCORE>1
- enter_critical(GLOBAL_LOCK); /* 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= %9.3f\t", memcnt/1048576.);
- snap_time();
- fflush(stdout);
-#if NCORE>1
- leave_critical(GLOBAL_LOCK);
-#endif
-}
-#ifdef SC
-void
-stack2disk(void)
-{
- if (!stackwrite
- && (stackwrite = creat(stackfile, TMODE)) < 0)
- Uerror("cannot create stackfile");
-
- if (write(stackwrite, trail, DDD*sizeof(Trail))
- != DDD*sizeof(Trail))
- Uerror("stackfile write error -- disk is full?");
-
- memmove(trail, &trail[DDD], (HHH-DDD+2)*sizeof(Trail));
- memset(&trail[HHH-DDD+2], 0, (omaxdepth - HHH + DDD - 2)*sizeof(Trail));
- CNT1++;
-}
-void
-disk2stack(void)
-{ long have;
-
- CNT2++;
- memmove(&trail[DDD], trail, (HHH-DDD+2)*sizeof(Trail));
-
- if (!stackwrite
- || lseek(stackwrite, -DDD* (off_t) sizeof(Trail), SEEK_CUR) == -1)
- Uerror("disk2stack lseek error");
-
- if (!stackread
- && (stackread = open(stackfile, 0)) < 0)
- Uerror("cannot open stackfile");
-
- if (lseek(stackread, (CNT1-CNT2)*DDD* (off_t) sizeof(Trail), SEEK_SET) == -1)
- Uerror("disk2stack lseek error");
-
- have = read(stackread, trail, DDD*sizeof(Trail));
- if (have != DDD*sizeof(Trail))
- Uerror("stackfile read error");
-}
-#endif
-uchar *
-Pptr(int x)
-{ if (x < 0 || x >= MAXPROC || !proc_offset[x])
- return noptr;
- else
- return (uchar *) pptr(x);
-}
-int qs_empty(void);
-/*
- * 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
- * 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
- */
-#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 %10d (%.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
-
-void
-new_state(void)
-{ Trans *t;
- uchar _n, _m, ot;
-#ifdef RANDOMIZE
- short ooi, eoi;
-#endif
-#ifdef M_LOSS
- uchar delta_m = 0;
-#endif
- short II, JJ = 0, kk;
- int tt;
-#ifdef REVERSE
- short From = BASE, To = now._nr_pr-1;
-#else
- short From = now._nr_pr-1, To = BASE;
-#endif
-Down:
-#ifdef CHECK
- 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 SCHED
- if (depth > 0)
- { trpt->sched_limit = (trpt-1)->sched_limit;
- } else
- { trpt->sched_limit = 0;
- }
-#endif
-#ifdef SC
- if (depth > hiwater)
- { stack2disk();
- maxdepth += DDD;
- hiwater += DDD;
- trpt -= DDD;
- if(verbose)
- printf("zap %d: %d (maxdepth now %d)\n",
- CNT1, hiwater, maxdepth);
- }
-#endif
- trpt->tau &= ~(16|32|64); /* make sure these are off */
-#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)
- { 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
-#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)) || NCORE>1
- /* if atomic or rv move, carry forward previous state */
- 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 ((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
-#if NCORE>1 && defined(FULL_TRAIL)
- if (upto > 0)
- { Pop_Stack_Tree();
- }
-#endif
- goto Up;
- }
-#ifdef CHECK
- printf("not seed\n");
-#endif
- }
-#endif
- if (!(trpt->tau&8)) /* if no atomic move */
- {
-#ifdef BITSTATE
-#ifdef CNTRSTACK
- II = bstore((char *)&now, vsize);
- trpt->j6 = j1; trpt->j7 = j2;
- JJ = LL[j1] && LL[j2];
-#else
-#ifdef FULLSTACK
- JJ = onstack_now();
-#else
-#ifndef NOREDUCE
- JJ = II; /* worstcase guess for p.o. */
-#endif
-#endif
- II = bstore((char *)&now, vsize);
-#endif
-#else
-#ifdef MA
- II = gstore((char *)&now, vsize, 0);
-#ifndef FULLSTACK
- JJ = II;
-#else
- JJ = (II == 2)?1:0;
-#endif
-#else
- II = hstore((char *)&now, vsize);
-#ifdef FULLSTACK
- JJ = (II == 2)?1:0;
-#endif
-#endif
-#endif
- kk = (II == 1 || II == 2);
-#ifndef SAFETY
-#if NCORE==1 || defined (SEP_STATE)
- if (II == 2 && ((trpt->o_pm&2) || ((trpt-1)->o_pm&2)))
- #ifndef NOFAIR
-#if 0
- if (!fairness || ((now._a_t&1) && now._cnt[1] == 1)) /* 5.1.4 */
-#else
- if (a_cycles && !fairness) /* 5.1.6 -- example by Hirofumi Watanabe */
-#endif
- #endif
- {
- II = 3; /* Schwoon & Esparza 2005, Gastin&Moro 2004 */
-#ifdef VERBOSE
- printf("state match on dfs stack\n");
-#endif
- goto same_case;
- }
-#endif
-#if defined(FULLSTACK) && defined(BITSTATE)
- if (!JJ && (now._a_t&1) && depth > A_depth)
- { int oj1 = j1;
- uchar o_a_t = now._a_t;
- now._a_t &= ~(1|16|32);
- if (onstack_now())
- { II = 3;
-#ifdef VERBOSE
- printf("state match on 1st dfs stack\n");
-#endif
- }
- now._a_t = o_a_t;
- j1 = oj1;
- }
-#endif
- if (II == 3 && a_cycles && (now._a_t&1))
- {
-#ifndef NOFAIR
- if (fairness && now._cnt[1] > 1) /* was != 0 */
- {
-#ifdef VERBOSE
- printf(" fairness count non-zero\n");
-#endif
- II = 0;
- } else
-#endif
- {
-#ifndef BITSTATE
- nShadow--;
-#endif
-same_case: if (Lstate) depthfound = Lstate->D;
-#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;
- }
- }
-#endif
-#ifndef NOREDUCE
-#ifndef SAFETY
-#if NCORE>1 && !defined(SEP_STATE) && defined(V_PROVISO)
- if (II != 0 && (!Lstate || Lstate->cpu_id < core_id))
- { (trpt-1)->tau |= 16;
- }
-#endif
- if ((II && JJ) || (II == 3))
- { /* marker for liveness proviso */
-#ifndef LOOPSTATE
- (trpt-1)->tau |= 16;
-#endif
- truncs2++;
- }
-#else
-#if NCORE>1 && !defined(SEP_STATE) && defined(V_PROVISO)
- if (!(II != 0 && (!Lstate || Lstate->cpu_id < core_id)))
- { /* treat as stack state */
- (trpt-1)->tau |= 16;
- } else
- { /* treat as non-stack state */
- (trpt-1)->tau |= 64;
- }
-#endif
- if (!II || !JJ)
- { /* successor outside stack */
- (trpt-1)->tau |= 64;
- }
-#endif
-#endif
- if (II)
- { truncs++;
-#if NCORE>1 && defined(FULL_TRAIL)
- if (upto > 0)
- { Pop_Stack_Tree();
- if (depth == 0)
- { return;
- } }
-#endif
- goto Up;
- }
- if (!kk)
- { static long sdone = (long) 0; long ndone;
- nstates++;
-#if defined(ZAPH) && defined(BITSTATE)
- zstates += (double) hfns;
-#endif
- ndone = (unsigned long) (nstates/((double) 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)
- if (write(svfd, (uchar *) &now, vprefix) != vprefix)
- { fprintf(efd, "writing %s.svd failed\n", PanSource);
- wrapup();
- }
-#endif
-#if defined(MA) && defined(W_XPT)
- if ((unsigned long) nstates%W_XPT == 0)
- { void w_xpoint(void);
- w_xpoint();
- }
-#endif
- }
-#if defined(FULLSTACK) || defined(CNTRSTACK)
- onstack_put();
-#ifdef DEBUG2
-#if defined(FULLSTACK) && !defined(MA)
- printf("%d: putting %u (%d)\n", depth,
- trpt->ostate,
- (trpt->ostate)?trpt->ostate->tagged:0);
-#else
- printf("%d: putting\n", depth);
-#endif
-#endif
-#else
- #if NCORE>1
- trpt->ostate = Lstate;
- #endif
-#endif
- } }
- if (depth > mreached)
- mreached = depth;
-#ifdef VERI
- if (trpt->tau&4)
-#endif
- trpt->tau &= ~(1|2); /* timeout and -request off */
- _n = 0;
-#if SYNC
- (trpt+1)->o_n = 0;
-#endif
-#ifdef VERI
- if (now._nr_pr == 0) /* claim terminated */
- uerror("end state in claim reached");
- check_claim(((P0 *)pptr(0))->_p);
-Stutter:
- if (trpt->tau&4) /* must make a claimmove */
- {
-#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
- printf("%3d: fairness Rule 3.: _a_t = %d\n",
- depth, now._a_t);
-#endif
- }
-#endif
- II = 0; /* never */
- goto Veri0;
- }
-#endif
-#ifndef NOREDUCE
- /* Look for a process with only safe transitions */
- /* (special rules apply in the 2nd dfs) */
- if (boq == -1 && From != To
-
-#ifdef SAFETY
- #if NCORE>1
- && (depth < z_handoff)
- #endif
- )
-#else
- #if NCORE>1
- && ((a_cycles) || (!a_cycles && depth < z_handoff))
- #endif
- && (!(now._a_t&1)
- || (a_cycles &&
- #ifndef BITSTATE
-#ifdef MA
-#ifdef VERI
- !((trpt-1)->proviso))
-#else
- !(trpt->proviso))
-#endif
-#else
-#ifdef VERI
- (trpt-1)->ostate &&
- !(((char *)&((trpt-1)->ostate->state))[0] & 128))
-#else
- !(((char *)&(trpt->ostate->state))[0] & 128))
-#endif
-#endif
- #else
-#ifdef VERI
- (trpt-1)->ostate &&
- (trpt-1)->ostate->proviso == 0)
-#else
- trpt->ostate->proviso == 0)
-#endif
- #endif
- ))
-#endif
-
-#ifdef REVERSE
- for (II = From; II <= To; II++)
-#else
- for (II = From; II >= To; II--)
-#endif
- {
-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; /* the process preselected */
-#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;
- }
- }
- 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 */
-#ifndef NOFAIR
- if (fairness && boq == -1
-#ifdef VERI
- && (!(trpt->tau&4) && !((trpt-1)->tau&128))
-#endif
- && !(trpt->tau&8))
- { /* A_bit = 1; Cnt = N in acc states with A_bit 0 */
- if (!(now._a_t&2))
- {
- if (a_cycles && (trpt->o_pm&2))
- { /* Accepting state */
- now._a_t |= 2;
- 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",
- depth, now._cnt[now._a_t&1], now._a_t);
-#endif
- }
- } else
- { /* A_bit = 0 when Cnt 0 */
- if (now._cnt[now._a_t&1] == 1)
- { now._a_t &= ~2;
- now._cnt[now._a_t&1] = 0;
- trpt->o_pm |= 16;
-#ifdef DEBUG
- printf("%3d: fairness Rule 3: _a_t = %d\n",
- depth, now._a_t);
-#endif
- } } }
-#endif
-
-#ifdef REVERSE
- for (II = From; II <= To; II++)
-#else
- for (II = From; II >= To; II--)
-#endif
- {
-#if SYNC
- /* no rendezvous with same proc */
- if (boq != -1 && trpt->pr == II) continue;
-#endif
-#ifdef SCHED
- /* limit max nr of interleavings */
- if (From != To
- && depth > 0
- #ifdef VERI
- && II != 0
- #endif
- && (trpt-1)->pr != II
- && trpt->sched_limit >= sched_max)
- { continue;
- }
-#endif
-#ifdef VERI
-Veri0:
-#endif
- this = pptr(II);
- tt = (int) ((P0 *)this)->_p;
- ot = (uchar) ((P0 *)this)->_t;
-#ifdef NIBIS
- /* don't repeat a previous preselected expansion */
- /* could hit this if reduction proviso was false */
- t = trans[ot][tt];
- if (!(trpt->tau&4)
- && !(trpt->tau&1)
- && !(trpt->tau&32)
- && (t->atom & 8)
- && boq == -1
- && From != To)
- { if (t->qu[0] == 0
- || q_cond(II, t))
- { _m = t->om;
- if (_m>_n||(_n>3&&_m!=0)) _n=_m;
- continue; /* did it before */
- } }
-#endif
- trpt->o_pm &= ~1; /* no move in this pid yet */
-#ifdef EVENT_TRACE
- (trpt+1)->o_event = now._event;
-#endif
- /* Fairness: Cnt++ when Cnt == II */
-#ifndef NOFAIR
- trpt->o_pm &= ~64; /* didn't apply rule 2 */
- if (fairness
- && boq == -1
- && !(trpt->o_pm&32)
- && (now._a_t&2)
- && now._cnt[now._a_t&1] == II+2)
- { now._cnt[now._a_t&1] -= 1;
-#ifdef VERI
- /* claim need not participate */
- if (II == 1)
- now._cnt[now._a_t&1] = 1;
-#endif
-#ifdef DEBUG
- printf("%3d: 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
- /* check all trans of proc II - escapes first */
-#ifdef HAS_UNLESS
- trpt->e_state = 0;
-#endif
- (trpt+1)->pr = (uchar) II;
- (trpt+1)->st = tt;
-#ifdef RANDOMIZE
- for (ooi = eoi = 0, t = trans[ot][tt]; t; t = t->nxt, ooi++)
- { if (strcmp(t->tp, "else") == 0)
- { eoi++;
- break;
- } }
- if (eoi > 0)
- { t = trans[ot][tt];
- #ifdef VERBOSE
- printf("randomizer: suppressed, saw else\n");
- #endif
- } else
- { eoi = rand()%ooi;
- #ifdef VERBOSE
- printf("randomizer: skip %d in %d\n", eoi, ooi);
- #endif
- for (t = trans[ot][tt]; t; t = t->nxt)
- if (eoi-- <= 0) break;
- }
-domore:
- for ( ; t && ooi > 0; t = t->nxt, ooi--)
-#else
- for (t = trans[ot][tt]; t; t = t->nxt)
-#endif
- {
-#ifdef HAS_UNLESS
- /* exploring all transitions from
- * a single escape state suffices
- */
- if (trpt->e_state > 0
- && trpt->e_state != t->e_trans)
- {
-#ifdef DEBUG
- printf("skip 2nd escape %d (did %d before)\n",
- t->e_trans, trpt->e_state);
-#endif
- break;
- }
-#endif
- (trpt+1)->o_t = t;
-#ifdef INLINE
-#include FORWARD_MOVES
-P999: /* jumps here when move succeeds */
-#else
- if (!(_m = do_transit(t, II))) continue;
-#endif
-#ifdef SCHED
- if (depth > 0
- #ifdef VERI
- && II != 0
- #endif
- && (trpt-1)->pr != II)
- { trpt->sched_limit = 1 + (trpt-1)->sched_limit;
- }
-#endif
- if (boq == -1)
-#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->o_pm |= 1; /* we moved */
- }
-#else
- trpt->o_pm |= 1; /* we moved */
-#endif
-#ifdef LOOPSTATE
- if (loopstate[ot][tt])
- {
-#ifdef VERBOSE
- printf("exiting from loopstate:\n");
-#endif
- trpt->tau |= 16;
- cnt_loops++;
- }
-#endif
-#ifdef PEG
- peg[t->forw]++;
-#endif
-#if defined(VERBOSE) || defined(CHECK)
-#if defined(SVDUMP)
- cpu_printf("%3d: proc %d exec %d \n", depth, II, t->t_id);
-#else
- cpu_printf("%3d: 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":"",
- (trpt->o_pm&2)?"":"non-", trpt->tau);
-#ifdef HAS_UNLESS
- if (t->e_trans)
- cpu_printf("\t(escape to state %d)\n", t->st);
-#endif
-#endif
-#ifdef RANDOMIZE
- cpu_printf("\t(randomizer %d)\n", ooi);
-#endif
-#endif
-#ifdef HAS_LAST
-#ifdef VERI
- if (II != 0)
-#endif
- now._last = II - BASE;
-#endif
-#ifdef HAS_UNLESS
- trpt->e_state = t->e_trans;
-#endif
- depth++; trpt++;
- trpt->pr = (uchar) II;
- trpt->st = tt;
- trpt->o_pm &= ~(2|4);
- if (t->st > 0)
- { ((P0 *)this)->_p = t->st;
-/* moved down reached[ot][t->st] = 1; */
- }
-#ifndef SAFETY
- if (a_cycles)
- {
-#if (ACCEPT_LAB>0 && !defined(NP)) || (PROG_LAB>0 && defined(HAS_NP))
- int ii;
-#endif
-#define P__Q ((P0 *)pptr(ii))
-#if ACCEPT_LAB>0
-#ifdef NP
- /* state 1 of np_ claim is accepting */
- if (((P0 *)pptr(0))->_p == 1)
- trpt->o_pm |= 2;
-#else
- for (ii = 0; ii < (int) now._nr_pr; ii++)
- { if (accpstate[P__Q->_t][P__Q->_p])
- { trpt->o_pm |= 2;
- break;
- } }
-#endif
-#endif
-#if defined(HAS_NP) && PROG_LAB>0
- for (ii = 0; ii < (int) now._nr_pr; ii++)
- { if (progstate[P__Q->_t][P__Q->_p])
- { trpt->o_pm |= 4;
- break;
- } }
-#endif
-#undef P__Q
- }
-#endif
- trpt->o_t = t; trpt->o_n = _n;
- trpt->o_ot = ot; trpt->o_tt = tt;
- trpt->o_To = To; trpt->o_m = _m;
- trpt->tau = 0;
-#ifdef RANDOMIZE
- trpt->oo_i = ooi;
-#endif
- if (boq != -1 || (t->atom&2))
- { trpt->tau |= 8;
-#ifdef VERI
- /* atomic sequence in claim */
- if((trpt-1)->tau&4)
- trpt->tau |= 4;
- else
- trpt->tau &= ~4;
- } else
- { if ((trpt-1)->tau&4)
- trpt->tau &= ~4;
- else
- trpt->tau |= 4;
- }
- /* if claim allowed timeout, so */
- /* does the next program-step: */
- if (((trpt-1)->tau&1) && !(trpt->tau&4))
- trpt->tau |= 1;
-#else
- } else
- trpt->tau &= ~8;
-#endif
- if (boq == -1 && (t->atom&2))
- { From = To = II; nlinks++;
- } else
-#ifdef REVERSE
- { From = BASE; To = now._nr_pr-1;
-#else
- { From = now._nr_pr-1; To = BASE;
-#endif
- }
-#if NCORE>1 && defined(FULL_TRAIL)
- if (upto > 0)
- { Push_Stack_Tree(II, t->t_id);
- }
-#endif
- goto Down; /* pseudo-recursion */
-Up:
-#ifdef CHECK
- 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)
- {
- trpt += DDD;
- disk2stack();
- maxdepth -= DDD;
- hiwater -= DDD;
- if(verbose)
- printf("unzap %d: %d\n", CNT2, hiwater);
- }
-#endif
-#ifndef NOFAIR
- if (trpt->o_pm&128) /* fairness alg */
- { now._cnt[now._a_t&1] = trpt->bup.oval;
- _n = 1; trpt->o_pm &= ~128;
- depth--; trpt--;
-#if defined(VERBOSE) || defined(CHECK)
- printf("%3d: reversed fairness default move\n", depth);
-#endif
- goto Q999;
- }
-#endif
-#ifdef HAS_LAST
-#ifdef VERI
- { int d; Trail *trl;
- now._last = 0;
- for (d = 1; d < depth; d++)
- { trl = getframe(depth-d); /* was (trpt-d) */
- if (trl->pr != 0)
- { now._last = trl->pr - BASE;
- break;
- } } }
-#else
- now._last = (depth<1)?0:(trpt-1)->pr;
-#endif
-#endif
-#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);
- To = trpt->o_To; _m = trpt->o_m;
-#ifdef RANDOMIZE
- ooi = trpt->oo_i;
-#endif
-#ifdef INLINE_REV
- _m = do_reverse(t, II, _m);
-#else
-#include REVERSE_MOVES
-R999: /* jumps here when done */
-#endif
-#ifdef VERBOSE
- cpu_printf("%3d: proc %d reverses %d, %d to %d\n",
- depth, II, t->forw, tt, t->st);
- cpu_printf("\t%s [abit=%d,adepth=%d,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
- if ((trpt->tau&8) /* rv or atomic */
- && (trpt->tau&64))
- (trpt-1)->tau |= 64;
-#endif
-#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][tt] = 1;
- }
-#ifdef HAS_UNLESS
- else trpt->e_state = 0; /* undo */
-#endif
- if (_m>_n||(_n>3&&_m!=0)) _n=_m;
- ((P0 *)this)->_p = tt;
- } /* all options */
-#ifdef RANDOMIZE
- if (!t && ooi > 0)
- { t = trans[ot][tt];
- #ifdef VERBOSE
- printf("randomizer: continue for %d more\n", ooi);
- #endif
- goto domore;
- }
- #ifdef VERBOSE
- else
- printf("randomizer: done\n");
- #endif
-#endif
-#ifndef NOFAIR
- /* Fairness: undo Rule 2 */
- if ((trpt->o_pm&32)
- && (trpt->o_pm&64))
- { if (trpt->o_pm&1)
- {
-#ifdef VERI
- 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("undo Rule 2, cnt=%d, _a_t=%d\n",
- now._cnt[now._a_t&1], now._a_t);
-#endif
- trpt->o_pm &= ~(32|64);
- } else
- { if (_n > 0)
- {
- trpt->o_pm &= ~64;
-#ifdef REVERSE
- II = From-1;
-#else
- II = From+1;
-#endif
- } } }
-#endif
-#ifdef VERI
- if (II == 0) break; /* never claim */
-#endif
- } /* all processes */
-#ifdef NSUCC
- tally_succ(trpt->n_succ);
-#endif
-#ifdef SCHED
- if (_n == 0 /* no process could move */
- #ifdef VERI
- && II != 0
- #endif
- && depth > 0
- && trpt->sched_limit >= sched_max)
- { _n = 1; /* not a deadlock */
- }
-#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)
- now._cnt[now._a_t&1] = 2;
-#endif
- now._cnt[now._a_t&1] += 1;
-#ifdef VERBOSE
- printf("%3d: 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
- if (fairness
- && _n == 0 /* nobody moved */
-#ifdef VERI
- && !(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
-#endif
-#ifndef NOREDUCE
- /* see below */
- && !((trpt->tau&32) && (_n == 0 || (trpt->tau&16)))
-#endif
- && now._cnt[now._a_t&1] > 0) /* needed more procs */
- { depth++; trpt++;
- trpt->o_pm |= 128 | ((trpt-1)->o_pm&(2|4));
- trpt->bup.oval = now._cnt[now._a_t&1];
- now._cnt[now._a_t&1] = 1;
-#ifdef VERI
- trpt->tau = 4;
-#else
- trpt->tau = 0;
-#endif
-#ifdef REVERSE
- From = BASE; To = now._nr_pr-1;
-#else
- From = now._nr_pr-1; To = BASE;
-#endif
-#if defined(VERBOSE) || defined(CHECK)
- printf("%3d: fairness default move ", depth);
- printf("(all procs block)\n");
-#endif
- goto Down;
- }
-#endif
-Q999: /* returns here with _n>0 when done */;
- if (trpt->o_pm&8)
- { now._a_t &= ~2;
- now._cnt[now._a_t&1] = 0;
- trpt->o_pm &= ~8;
-#ifdef VERBOSE
- printf("%3d: fairness undo Rule 1, _a_t=%d\n",
- depth, now._a_t);
-#endif
- }
- if (trpt->o_pm&16)
- { now._a_t |= 2;
- now._cnt[now._a_t&1] = 1;
- trpt->o_pm &= ~16;
-#ifdef VERBOSE
- printf("%3d: fairness undo Rule 3, _a_t=%d\n",
- depth, now._a_t);
-#endif
- }
-#endif
-#ifndef NOREDUCE
-#ifdef SAFETY
-#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
-#ifdef REVERSE
- { From = BASE; To = now._nr_pr-1;
-#else
- { From = now._nr_pr-1; To = BASE;
-#endif
-#ifdef DEBUG
- printf("%3d: proc %d UnSelected (_n=%d, tau=%d)\n",
- depth, II+1, _n, trpt->tau);
-#endif
- _n = 0; trpt->tau &= ~(16|32|64);
-#ifdef REVERSE
- if (II <= To) /* II already decremented */
-#else
- if (II >= BASE) /* II already decremented */
-#endif
- 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
- if (a_cycles && (trpt->tau&16))
- { if (!(now._a_t&1))
- {
-#ifdef DEBUG
- printf("%3d: setting proviso bit\n", depth);
-#endif
-#ifndef BITSTATE
-#ifdef MA
-#ifdef VERI
- (trpt-1)->proviso = 1;
-#else
- trpt->proviso = 1;
-#endif
-#else
-#ifdef VERI
- if ((trpt-1)->ostate)
- ((char *)&((trpt-1)->ostate->state))[0] |= 128;
-#else
- ((char *)&(trpt->ostate->state))[0] |= 128;
-#endif
-#endif
-#else
-#ifdef VERI
- if ((trpt-1)->ostate)
- (trpt-1)->ostate->proviso = 1;
-#else
- trpt->ostate->proviso = 1;
-#endif
-#endif
-#ifdef REVERSE
- From = BASE; To = now._nr_pr-1;
-#else
- From = now._nr_pr-1; To = BASE;
-#endif
- _n = 0; trpt->tau &= ~(16|32|64);
- goto Again; /* do full search */
- } /* else accept reduction */
- } else
-#ifdef REVERSE
- { From = BASE; To = now._nr_pr-1;
-#else
- { From = now._nr_pr-1; To = BASE;
-#endif
- _n = 0; trpt->tau &= ~(16|32|64);
-#ifdef REVERSE
- if (II <= To) /* already decremented */
-#else
- if (II >= BASE) /* already decremented */
-#endif
- goto Resume;
- else
- goto Again;
- } }
-/* #endif */
-#endif
-#endif
- if (_n == 0 || ((trpt->tau&4) && (trpt->tau&2)))
- {
-#ifdef DEBUG
- cpu_printf("%3d: no move [II=%d, tau=%d, boq=%d]\n",
- depth, II, trpt->tau, boq);
-#endif
-#if SYNC
- /* ok if a rendez-vous fails: */
- if (boq != -1) goto Done;
-#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;
- if ((trpt->tau&8) && !(trpt->tau&4))
- { trpt->tau &= ~(1|8);
- /* 1=timeout, 8=atomic */
-#ifdef REVERSE
- From = BASE; To = now._nr_pr-1;
-#else
- From = now._nr_pr-1; To = BASE;
-#endif
-#ifdef DEBUG
- cpu_printf("%3d: atomic step proc %d unexecutable\n", depth, II+1);
-#endif
-#ifdef VERI
- trpt->tau |= 4; /* switch to claim */
-#endif
- goto AllOver;
- }
-#ifdef ETIM
- if (!(trpt->tau&1)) /* didn't try timeout yet */
- {
-#ifdef VERI
- if (trpt->tau&4)
- {
-#ifndef NTIM
- if (trpt->tau&2) /* requested */
-#endif
- { trpt->tau |= 1;
- trpt->tau &= ~2;
-#ifdef DEBUG
- cpu_printf("%d: timeout\n", depth);
-#endif
- goto Stutter;
- } }
- else
- { /* only claim can enable timeout */
- if ((trpt->tau&8)
- && !((trpt-1)->tau&4))
-/* blocks inside an atomic */ goto BreakOut;
-#ifdef DEBUG
- cpu_printf("%d: req timeout\n",
- depth);
-#endif
- (trpt-1)->tau |= 2; /* request */
-#if NCORE>1 && defined(FULL_TRAIL)
- if (upto > 0)
- { Pop_Stack_Tree();
- }
-#endif
- goto Up;
- }
-#else
-#ifdef DEBUG
- cpu_printf("%d: timeout\n", depth);
-#endif
- trpt->tau |= 1;
- goto Again;
-#endif
- }
-#endif
-#ifdef VERI
-BreakOut:
-#ifndef NOSTUTTER
- if (!(trpt->tau&4))
- { trpt->tau |= 4; /* claim stuttering */
- trpt->tau |= 128; /* stutter mark */
-#ifdef DEBUG
- cpu_printf("%d: claim stutter\n", depth);
-#endif
- goto Stutter;
- }
-#else
- ;
-#endif
-#else
- if (!noends && !a_cycles && !endstate())
- { depth--; trpt--; /* new 4.2.3 */
- uerror("invalid end state");
- depth++; trpt++;
- }
-#ifndef NOSTUTTER
- else if (a_cycles && (trpt->o_pm&2)) /* new 4.2.4 */
- { depth--; trpt--;
- uerror("accept stutter");
- depth++; trpt++;
- }
-#endif
-#endif
- }
-Done:
- if (!(trpt->tau&8)) /* not in atomic seqs */
- {
-#ifndef SAFETY
- if (_n != 0
-#ifdef VERI
- /* --after-- a program-step, i.e., */
- /* after backtracking a claim-step */
- && (trpt->tau&4)
- /* with at least one running process */
- /* unless in a stuttered accept state */
- && ((now._nr_pr > 1) || (trpt->o_pm&2))
-#endif
- && !(now._a_t&1))
- {
-#ifndef NOFAIR
- if (fairness)
- {
-#ifdef VERBOSE
- cpu_printf("Consider check %d %d...\n",
- now._a_t, now._cnt[0]);
-#endif
- if ((now._a_t&2) /* A-bit */
- && (now._cnt[0] == 1))
- checkcycles();
- } else
-#endif
- if (a_cycles && (trpt->o_pm&2))
- 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)
- {
-#if NCORE>1 && defined(FULL_TRAIL)
- if (upto > 0)
- { Pop_Stack_Tree();
- }
-#endif
- goto Up;
- }
-}
-
-#else
-void new_state(void) { /* place holder */ }
-#endif
-
-void
-assert(int a, char *s, int ii, int tt, Trans *t)
-{
- if (!a && !noasserts)
- { char bad[1024];
- strcpy(bad, "assertion violated ");
- if (strlen(s) > 1000)
- { strncpy(&bad[19], (const char *) s, 1000);
- bad[1019] = '\0';
- } else
- strcpy(&bad[19], s);
- uerror(bad);
- }
-}
-#ifndef NOBOUNDCHECK
-int
-Boundcheck(int x, int y, int a1, int a2, Trans *a3)
-{
- assert((x >= 0 && x < y), "- invalid array index",
- a1, a2, a3);
- return x;
-}
-#endif
-void
-wrap_stats(void)
-{
- if (nShadow>0)
- printf("%9.8g states, stored (%g visited)\n",
- nstates - nShadow, nstates);
- else
- printf("%9.8g states, stored\n", nstates);
-#ifdef BFS
-#if SYNC
- printf(" %8g nominal states (- rv and atomic)\n", nstates-midrv-nlinks+revrv);
- printf(" %8g rvs succeeded\n", midrv-failedrv);
-#else
- printf(" %8g nominal states (stored-atomic)\n", nstates-nlinks);
-#endif
-#ifdef DEBUG
- printf(" %8g midrv\n", midrv);
- printf(" %8g failedrv\n", failedrv);
- printf(" %8g revrv\n", revrv);
-#endif
-#endif
- printf("%9.8g states, matched\n", truncs);
-#ifdef CHECK
- printf("%9.8g matches within stack\n",truncs2);
-#endif
- if (nShadow>0)
- printf("%9.8g transitions (= visited+matched)\n",
- nstates+truncs);
- else
- printf("%9.8g transitions (= stored+matched)\n",
- nstates+truncs);
- printf("%9.8g atomic steps\n", nlinks);
- if (nlost) printf("%g lost messages\n", (double) nlost);
-
-#ifndef BITSTATE
- printf("hash conflicts: %9.8g (resolved)\n", hcmp);
- #ifndef AUTO_RESIZE
- if (hcmp > (double) (1<<ssize))
- { printf("hint: increase hashtable-size (-w) to reduce runtime\n");
- } /* in multi-core: also reduces lock delays on access to hashtable */
- #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)(((double) udmem) * 8.0) / (double) nstates);
- else
- printf("\nhash factor: %4g (best if > 100.)\n\n",
- (double)(1<<(ssize-8)) / (double) nstates * 256.0);
- printf("bits set per state: %u (-k%u)\n", hfns, hfns);
- #if 0
- if (udmem)
- { printf("total bits available: %8g (-M%ld)\n",
- ((double) udmem) * 8.0, udmem/(1024L*1024L));
- } else
- printf("total bits available: %8g (-w%d)\n",
- ((double) (ONE_L << (ssize-4)) * 16.0), ssize);
- #endif
-#endif
-#ifdef BFS_DISK
- 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
-#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);
-#endif
- printf("\n(%s)\n", SpinVersion);
- if (!done) printf("Warning: Search not completed\n");
-#ifdef SC
- (void) unlink((const char *)stackfile);
-#endif
-#if NCORE>1
- if (a_cycles)
- { printf(" + Multi-Core (NCORE=%d)\n", NCORE);
- } else
- { printf(" + Multi-Core (NCORE=%d -z%d)\n", NCORE, z_handoff);
- }
-#endif
-#ifdef BFS
- printf(" + Using Breadth-First Search\n");
-#endif
-#ifndef NOREDUCE
- printf(" + Partial Order Reduction\n");
-#endif
-#ifdef REVERSE
- printf(" + Reverse Depth-First Search Order\n");
-#endif
-#ifdef T_REVERSE
- printf(" + Reverse Transition Ordering\n");
-#endif
-#ifdef RANDOMIZE
- printf(" + Randomized Transition Ordering\n");
-#endif
-#ifdef SCHED
- printf(" + Scheduling Restriction (-DSCHED=%d)\n", sched_max);
-#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", PanSource);
- #endif
-#endif
-#ifdef CHECK
- #ifdef FULLSTACK
- printf(" + FullStack Matching\n");
- #endif
- #ifdef CNTRSTACK
- printf(" + CntrStack Matching\n");
- #endif
-#endif
-#ifdef BITSTATE
- printf("\nBit statespace search for:\n");
-#else
-#ifdef HC
- printf("\nHash-Compact %d search for:\n", HC);
-#else
- printf("\nFull statespace search for:\n");
-#endif
-#endif
-#ifdef EVENT_TRACE
-#ifdef NEGATED_TRACE
- printf(" notrace assertion +\n");
-#else
- printf(" trace assertion +\n");
-#endif
-#endif
-#ifdef VERI
- printf(" never claim +\n");
- printf(" assertion violations ");
- if (noasserts)
- printf("- (disabled by -A flag)\n");
- else
- printf("+ (if within scope of claim)\n");
-#else
-#ifdef NOCLAIM
- printf(" never claim - (not selected)\n");
-#else
- printf(" never claim - (none specified)\n");
-#endif
- printf(" assertion violations ");
- if (noasserts)
- printf("- (disabled by -A flag)\n");
- else
- printf("+\n");
-#endif
-#ifndef SAFETY
-#ifdef NP
- printf(" non-progress cycles ");
-#else
- printf(" acceptance cycles ");
-#endif
- if (a_cycles)
- printf("+ (fairness %sabled)\n",
- fairness?"en":"dis");
- else printf("- (not selected)\n");
-#else
- printf(" cycle checks - (disabled by -DSAFETY)\n");
-#endif
-#ifdef VERI
- printf(" invalid end states - ");
- printf("(disabled by ");
- if (noends)
- printf("-E flag)\n\n");
- else
- printf("never claim)\n\n");
-#else
- printf(" invalid end states ");
- if (noends)
- printf("- (disabled by -E flag)\n\n");
- else
- printf("+\n\n");
-#endif
- 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);
- if (maxgs+a_cycles+2 < MA)
- printf("MA stats: -DMA=%d is sufficient\n",
- maxgs+a_cycles+2);
- dfa_stats();
- }
-#endif
- wrap_stats();
-#ifdef CHECK
- printf("stackframes: %d/%d\n\n", smax, svmax);
- printf("stats: fa %d, fh %d, zh %d, zn %d - ",
- Fa, Fh, Zh, Zn);
- printf("check %d holds %d\n", Ccheck, Cholds);
- printf("stack stats: puts %d, probes %d, zaps %d\n",
- PUT, PROBE, ZAPS);
-#else
- printf("\n");
-#endif
-
-#if defined(BITSTATE) || !defined(NOCOMP)
- nr1 = (nstates-nShadow)*
- (double)(hmax+sizeof(struct H_el)-sizeof(unsigned));
-#ifdef BFS
- nr2 = 0.0;
-#else
- nr2 = (double) ((maxdepth+3)*sizeof(Trail));
-#endif
-#ifndef BITSTATE
-#if !defined(MA) || defined(COLLAPSE)
- nr3 = (double) (ONE_L<<ssize)*sizeof(struct H_el *);
-#endif
-#else
- if (udmem)
- nr3 = (double) (udmem);
- else
- nr3 = (double) (ONE_L<<(ssize-3));
-#ifdef CNTRSTACK
- nr5 = (double) (ONE_L<<(ssize-3));
-#endif
-#ifdef FULLSTACK
- nr5 = (double) (maxdepth*sizeof(struct H_el *));
-#endif
-#endif
- nr4 = (double) (svmax * (sizeof(Svtack) + hmax))
- + (double) (smax * (sizeof(Stack) + Maxbody));
-#ifndef MA
- if (mverbose || 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("%9.3f equivalent memory usage for states",
- nr1/1048576.); /* 1024*1024=1048576 */
- printf(" (stored*(State-vector + overhead))\n");
- #if NCORE>1 && !defined(WIN32) && !defined(WIN64)
- printf("%9.3f shared memory reserved for state storage\n",
- mem_reserved/1048576.);
- #ifdef SEP_HEAP
- printf(" in %d local heaps of %7.3f MB each\n",
- NCORE, mem_reserved/(NCORE*1048576.));
- #endif
- printf("\n");
- #endif
-#ifdef BITSTATE
- if (udmem)
- printf("%9.3f memory used for hash array (-M%ld)\n",
- nr3/1048576., udmem/(1024L*1024L));
- else
- printf("%9.3f memory used for hash array (-w%d)\n",
- nr3/1048576., ssize);
- if (nr5 > 0.0)
- printf("%9.3f memory used for bit stack\n",
- nr5/1048576.);
- remainder = remainder - nr3 - nr5;
-#else
- printf("%9.3f actual memory usage for states",
- tmp_nr/1048576.);
- 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(" state-vector as stored = %.0f byte",
- (tmp_nr)/(nstates-nShadow) -
- (double) (sizeof(struct H_el) - sizeof(unsigned)));
- printf(" + %ld byte overhead\n",
- (long int) sizeof(struct H_el)-sizeof(unsigned));
- }
-#endif
-#if !defined(MA) || defined(COLLAPSE)
- printf("%9.3f memory used for hash table (-w%d)\n",
- nr3/1048576., ssize);
- remainder -= nr3;
-#endif
-#endif
-#ifndef BFS
- printf("%9.3f memory 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 shared memory used for work-queues\n",
- (GWQ_SIZE + (double) NCORE * LWQ_SIZE) /1048576.);
- printf(" in %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 other (proc and chan stacks)\n",
- (remainder-fragment)/1048576.);
- if (fragment > 1048576.)
- printf("%9.3f memory lost to fragmentation\n",
- fragment/1048576.);
- printf("%9.3f total actual memory usage\n\n",
- memcnt/1048576.);
- }
-#ifndef MA
- else
-#endif
-#endif
-#ifndef MA
- printf("%9.3f memory usage (Mbyte)\n\n",
- memcnt/1048576.);
-#endif
-#ifdef COLLAPSE
- printf("nr of templates: [ globals chans procs ]\n");
- printf("collapse counts: [ ");
- { int i; for (i = 0; i < 256+2; i++)
- if (ncomps[i] != 0)
- printf("%d ", ncomps[i]);
- printf("]\n");
- }
-#endif
- if ((done || verbose) && !no_rck) do_reach();
-#ifdef PEG
- { int i;
- printf("\nPeg Counts (transitions executed):\n");
- for (i = 1; i < NTRANS; i++)
- { if (peg[i]) putpeg(i, peg[i]);
- } }
-#endif
-#ifdef VAR_RANGES
- dumpranges();
-#endif
-#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
- pan_exit(0);
-}
-
-void
-stopped(int arg)
-{ printf("Interrupted\n");
-#if NCORE>1
- was_interrupted = 1;
-#endif
- wrapup();
- pan_exit(0);
-}
-
-#ifdef SFH
-/*
- * super fast hash, based on Paul Hsieh's function
- * http://www.azillionmonkeys.com/qed/hash.html
- */
-#include <stdint.h>
- #undef get16bits
- #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
- || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
- #define get16bits(d) (*((const uint16_t *) (d)))
- #endif
-
- #ifndef get16bits
- #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
- +(uint32_t)(((const uint8_t *)(d))[0]) )
- #endif
-
-void
-d_sfh(const char *s, int len)
-{ 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;
-}
-#endif
-
-#include <stdint.h>
-#if defined(HASH64) || defined(WIN64)
-/* 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); \
- c -= a; c -= b; c ^= (b>>8); \
- a -= b; a -= c; a ^= (c>>38); \
- b -= c; b -= a; b ^= (a<<23); \
- c -= a; c -= b; c ^= (b>>5); \
- a -= b; a -= c; a ^= (c>>35); \
- b -= c; b -= a; b ^= (a<<49); \
- c -= a; c -= b; c ^= (b>>11); \
- a -= b; a -= c; a ^= (c>>12); \
- b -= c; b -= a; b ^= (a<<18); \
- c -= a; c -= b; c ^= (b>>22); \
-}
-#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 -= 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)
-{ uint8_t *bp;
-#if defined(HASH64) || defined(WIN64)
- uint64_t a = 0, b, c, n;
- uint64_t *k = (uint64_t *) kb;
-#else
- uint32_t a, b, c, n;
- uint32_t *k = (uint32_t *) kb;
-#endif
- /* extend to multiple of words, if needed */
- n = nbytes/WS; /* nr of words */
- a = nbytes - (n*WS);
- if (a > 0)
- { n++;
- bp = kb + nbytes;
- switch (a) {
- case 3: *bp++ = 0; /* fall thru */
- case 2: *bp++ = 0; /* fall thru */
- case 1: *bp = 0;
- case 0: break;
- } }
-#if defined(HASH64) || defined(WIN64)
- b = HASH_CONST[HASH_NR];
- c = 0x9e3779b97f4a7c13LL; /* arbitrary value */
- 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);
-#else
- 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];
- case 0: break;
- }
- final(a,b,c);
-#endif
- j1 = c&nmask; j3 = a&7; /* 1st bit */
- j2 = b&nmask; j4 = (a>>3)&7; /* 2nd bit */
- K1 = c; K2 = b;
-}
-
-void
-s_hash(uchar *cp, int om)
-{
-#if defined(SFH)
- d_sfh((const char *) cp, om); /* sets K1 */
-#else
- d_hash(cp, om); /* sets K1 etc */
-#endif
-#ifdef BITSTATE
- if (S_Tab == H_tab)
- j1 = K1 % omaxdepth;
- else
-#endif
- if (ssize < 8*WS)
- j1 = K1&mask;
- else
- j1 = K1;
-}
-#ifndef RANDSTOR
-int *prerand;
-void
-inirand(void)
-{ int i;
- srand(123); /* fixed startpoint */
- prerand = (int *) emalloc((omaxdepth+3)*sizeof(int));
- for (i = 0; i < omaxdepth+3; i++)
- prerand[i] = rand();
-}
-int
-pan_rand(void)
-{ if (!prerand) inirand();
- return prerand[depth];
-}
-#endif
-
-void
-set_masks(void) /* 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 = ((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);
- }
-}
-
-static long reclaim_size;
-static char *reclaim_mem;
-#if defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(MA)
-#if NCORE>1
- #error cannot combine AUTO_RESIZE with NCORE>1 yet
-#endif
-static struct H_el **N_tab;
-void
-reverse_capture(struct H_el *p)
-{ if (!p) return;
- reverse_capture(p->nxt);
- /* last element of list moves first */
- /* to preserve list-order */
- j2 = p->m_K1;
- if (ssize < 8*WS) /* probably always true */
- { j2 &= mask;
- }
- p->nxt = N_tab[j2];
- N_tab[j2] = p;
-}
-void
-resize_hashtable(void)
-{
- if (WS == 4 && ssize >= 27 - 1)
- { return; /* canot increase further */
- }
-
- ssize += 2; /* 4x size */
-
- printf("pan: resizing hashtable to -w%d.. ", ssize);
-
- N_tab = (struct H_el **)
- emalloc((ONE_L<<ssize)*sizeof(struct H_el *));
-
- set_masks(); /* they changed */
-
- for (j1 = 0; j1 < (ONE_L << (ssize - 2)); j1++)
- { reverse_capture(H_tab[j1]);
- }
- 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
-
-int
-main(int argc, char *argv[])
-{ void to_compile(void);
-
- efd = stderr; /* default */
-#ifdef BITSTATE
- bstore = 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
- case 'a': a_cycles = 1; break;
-#endif
-#endif
- case 'A': noasserts = 1; break;
- case 'b': bounded = 1; break;
-#ifdef HAS_CODE
- case 'C': coltrace = 1; goto samething;
-#endif
- case 'c': upto = atoi(&argv[1][2]); break;
- case 'd': state_tables++; break;
- case 'e': every_error = 1; Nr_Trails = 1; break;
- case 'E': noends = 1; break;
-#ifdef SC
- case 'F': if (strlen(argv[1]) > 2)
- stackfile = &argv[1][2];
- break;
-#endif
-#if !defined(SAFETY) && !defined(NOFAIR)
- case 'f': fairness = 1; break;
-#endif
-#ifdef HAS_CODE
- case 'g': gui = 1; goto samething;
-#endif
- case 'h': if (!argv[1][2]) usage(efd); else
- HASH_NR = atoi(&argv[1][2])%33; break;
- case 'I': iterative = 2; every_error = 1; break;
- case 'i': 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 SCHED
- case 'L': sched_max = atoi(&argv[1][2]); break;
-#endif
-#ifndef SAFETY
-#ifdef NP
- case 'l': a_cycles = 1; break;
-#else
- case 'l': fprintf(efd, "error: -l disabled");
- usage(efd); break;
-#endif
-#endif
-#ifdef BITSTATE
- case 'M': udmem = atoi(&argv[1][2]); break;
- case 'G': udmem = atoi(&argv[1][2]); udmem *= 1024; break;
-#else
- case 'M': case 'G':
- fprintf(stderr, "-M and -G affect only -DBITSTATE\n");
- break;
-#endif
- case 'm': maxdepth = atoi(&argv[1][2]); break;
- case 'n': no_rck = 1; break;
- case 'P': readtrail = 1; onlyproc = atoi(&argv[1][2]);
- if (argv[2][0] != '-') /* check next arg */
- { trailfilename = argv[2];
- argc--; argv++; /* skip next arg */
- }
- break;
-#ifdef SVDUMP
- case 'p': vprefix = atoi(&argv[1][2]); break;
-#endif
-#if NCORE==1
- case 'Q': quota = (double) 60.0 * (double) atoi(&argv[1][2]); break;
-#endif
- case 'q': strict = 1; break;
- case 'R': Nrun = atoi(&argv[1][2]); break;
-#ifdef HAS_CODE
- case 'r':
-samething: readtrail = 1;
- if (isdigit(argv[1][2]))
- whichtrail = atoi(&argv[1][2]);
- else if (argc > 2 && argv[2][0] != '-') /* check next arg */
- { trailfilename = argv[2];
- argc--; argv++; /* skip next arg */
- }
- break;
- case 'S': silent = 1; goto samething;
-#endif
-#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': 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]); break;
- case 'Y': signoff = 1; break;
- case 'X': efd = stdout; 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 that 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 (iterative && TMODE != 0666)
- { TMODE = 0666;
- fprintf(efd, "warning: -T ignored when -i or -I is used\n");
- }
-#if defined(HASH32) && !defined(SFH)
- if (WS > 4)
- { fprintf(efd, "strong warning: compiling -DHASH32 on a 64-bit machine\n");
- fprintf(efd, " without -DSFH can slow down performance a lot\n");
- }
-#endif
-#if defined(WIN32) || defined(WIN64)
- if (TMODE == 0666)
- 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);
-#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
- }
- #endif
- #ifdef HAS_HIDDEN
- #error cannot use hidden variables when compiling multi-core
- #endif
-#endif
-#ifdef BITSTATE
- if (hfns <= 0)
- { hfns = 1;
- fprintf(efd, "warning: using -k%d as minimal usable value\n", hfns);
- }
-#endif
- omaxdepth = maxdepth;
-#ifdef BITSTATE
- if (WS == 4 && ssize > 34)
- { ssize = 34;
- 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
- */
- }
-#else
- if (WS == 4 && ssize > 27)
- { ssize = 27;
- fprintf(efd, "warning: using -w%d as max usable value\n", ssize);
-/*
- * for emalloc, the lookup table size multiplies by 4 for the pointers
- * the largest power of 2 that can be represented in a ulong is 1^31
- * hence the largest number of lookup table slots is 31-4 = 27
- */
- }
-#endif
-#ifdef SC
- hiwater = HHH = maxdepth-10;
- DDD = HHH/2;
- if (!stackfile)
- { 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");
- pan_exit(1);
- }
-#endif
-#if (defined(R_XPT) || defined(W_XPT)) && !defined(MA)
- #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
- #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 REACH
- #warning -DREACH is redundant when -DBFS is used
- #endif
-#endif
-#if defined(MERGED) && defined(PEG)
- #error to use -DPEG use: spin -o3 -a
-#endif
-#ifdef HC
- #ifdef SFH
- #error cannot combine -DHC and -DSFH
- /* use of NOCOMP is the real reason */
- #else
- #ifdef NOCOMP
- #error cannot combine -DHC and -DNOCOMP
- #endif
- #endif
- #ifdef BITSTATE
- #error cannot combine -DHC and -DBITSTATE
- #endif
-#endif
-#if defined(SAFETY) && defined(NP)
- #error cannot combine -DNP and -DBFS or -DSAFETY
-#endif
-#ifdef MA
- #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
- #ifdef BITSTATE
- #error cannot combine -DBITSTATE and -DCOLLAPSE
- #endif
- #ifdef SFH
- #error cannot combine -DCOLLAPSE and -DSFH
- /* use of NOCOMP is the real reason */
- #else
- #ifdef NOCOMP
- #error cannot combine -DCOLLAPSE and -DNOCOMP
- #endif
- #endif
-#endif
- if (maxdepth <= 0 || ssize <= 1) usage(efd);
-#if SYNC>0 && !defined(NOREDUCE)
- if (a_cycles && fairness)
- { fprintf(efd, "error: p.o. reduction not compatible with ");
- fprintf(efd, "fairness (-f) in models\n");
- fprintf(efd, " with rendezvous operations: ");
- fprintf(efd, "recompile with -DNOREDUCE\n");
- pan_exit(1);
- }
-#endif
-#if defined(REM_VARS) && !defined(NOREDUCE)
- #warning p.o. reduction not compatible with remote varrefs (use -DNOREDUCE)
-#endif
-#if defined(NOCOMP) && !defined(BITSTATE)
- if (a_cycles)
- { fprintf(efd, "error: use of -DNOCOMP voids -l and -a\n");
- pan_exit(1);
- }
-#endif
-#ifdef MEMLIM
- memlim = ((double) MEMLIM) * (double) (1<<20); /* size in Mbyte */
-#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)
- { fprintf(efd, "error: no accept labels defined ");
- fprintf(efd, "in model (for option -a)\n");
- usage(efd);
- }
- #endif
-#endif
-#ifndef NOREDUCE
- #ifdef 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
- #ifdef HAS_LAST
- #error use of _last requires -DNOREDUCE
- #endif
-#endif
-#if SYNC>0 && !defined(NOREDUCE)
- #ifdef HAS_UNLESS
- fprintf(efd, "warning: use of a rendezvous stmnts in the escape\n");
- fprintf(efd, " of an unless clause, if present, could make p.o. reduction\n");
- fprintf(efd, " invalid (use -DNOREDUCE to avoid this)\n");
- #ifdef BFS
- fprintf(efd, " (this type of rv is also not compatible with -DBFS)\n");
- #endif
- #endif
-#endif
-#if SYNC>0 && defined(BFS)
- #warning use of rendezvous with BFS does not preserve all invalid endstates
-#endif
-#if !defined(REACH) && !defined(BITSTATE)
- if (iterative != 0 && a_cycles == 0)
- { fprintf(efd, "warning: -i and -I need -DREACH to work accurately\n");
- }
-#endif
-#if defined(BITSTATE) && defined(REACH)
- #warning -DREACH is voided by -DBITSTATE
-#endif
-#if defined(MA) && defined(REACH)
- #warning -DREACH is voided by -DMA
-#endif
-#if defined(FULLSTACK) && defined(CNTRSTACK)
- #error cannot combine -DFULLSTACK and -DCNTRSTACK
-#endif
-#if defined(VERI)
- #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 (!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 (!a_cycles
- #ifdef HAS_CODE
- && !readtrail
- #endif
- #if NCORE>1
- && core_id == 0
- #endif
- && !state_tables)
- { fprintf(efd, "hint: this search is more efficient ");
- fprintf(efd, "if pan.c is compiled -DSAFETY\n");
- }
- #ifndef NOCOMP
- if (!a_cycles)
- { 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;
- /* -2 because first two uchars in now are masked */
- #endif
- } }
- #endif
-#endif
- signal(SIGINT, stopped);
- set_masks();
-#ifdef BFS
- 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
-#ifdef SVDUMP
- if (vprefix > 0)
- { char nm[64];
- 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);
-#endif
-#if SYNC>0 && ASYNC==0
- set_recvs();
-#endif
- run();
- done = 1;
- wrapup();
- return 0;
-}
-
-void
-usage(FILE *fd)
-{
- fprintf(fd, "%s\n", SpinVersion);
- fprintf(fd, "Valid Options are:\n");
-#ifndef SAFETY
-#ifdef NP
- fprintf(fd, " -a -> is disabled by -DNP ");
- fprintf(fd, "(-DNP compiles for -l only)\n");
-#else
- fprintf(fd, " -a find acceptance cycles\n");
-#endif
-#else
- fprintf(fd, " -a,-l,-f -> are disabled by -DSAFETY\n");
-#endif
- fprintf(fd, " -A ignore assert() violations\n");
- fprintf(fd, " -b consider it an error to exceed the depth-limit\n");
- fprintf(fd, " -cN stop at Nth error ");
- fprintf(fd, "(defaults to -c1)\n");
- fprintf(fd, " -d print state tables and stop\n");
- fprintf(fd, " -e create trails for all errors\n");
- fprintf(fd, " -E ignore invalid end states\n");
-#ifdef SC
- fprintf(fd, " -Ffile use 'file' to store disk-stack\n");
-#endif
-#ifndef NOFAIR
- fprintf(fd, " -f add weak fairness (to -a or -l)\n");
-#endif
- fprintf(fd, " -hN use different hash-seed N:1..32\n");
- fprintf(fd, " -i search for shortest path to error\n");
- fprintf(fd, " -I like -i, but approximate and faster\n");
- fprintf(fd, " -J reverse eval order of nested unlesses\n");
-#ifdef BITSTATE
- fprintf(fd, " -kN set N bits per state (defaults to 3)\n");
-#endif
-#ifdef SCHED
- fprintf(fd, " -LN set scheduling restriction to N (default 10)\n");
-#endif
-#ifndef SAFETY
-#ifdef NP
- fprintf(fd, " -l find non-progress cycles\n");
-#else
- fprintf(fd, " -l find non-progress cycles -> ");
- fprintf(fd, "disabled, requires ");
- fprintf(fd, "compilation with -DNP\n");
-#endif
-#endif
-#ifdef BITSTATE
- fprintf(fd, " -MN use N Megabytes for bitstate hash array\n");
- fprintf(fd, " -GN use N Gigabytes for bitstate hash array\n");
-#endif
- fprintf(fd, " -mN max depth N steps (default=10k)\n");
- fprintf(fd, " -n no listing of unreached states\n");
-#ifdef SVDUMP
- fprintf(fd, " -pN create svfile (save N bytes per state)\n");
-#endif
- fprintf(fd, " -QN set time-limit on execution of N minutes\n");
- fprintf(fd, " -q require empty chans in valid end states\n");
-#ifdef HAS_CODE
- fprintf(fd, " -r read and execute trail - can add -v,-n,-PN,-g,-C\n");
- fprintf(fd, " -rN read and execute N-th error trail\n");
- fprintf(fd, " -C read and execute trail - columnated output (can add -v,-n)\n");
- fprintf(fd, " -PN read and execute trail - restrict trail output to proc N\n");
- fprintf(fd, " -g read and execute trail + msc gui support\n");
- fprintf(fd, " -S silent replay: only user defined printfs show\n");
-#endif
-#ifdef BITSTATE
- fprintf(fd, " -RN repeat run Nx with N ");
- fprintf(fd, "[1..32] independent hash functions\n");
- fprintf(fd, " -s same as -k1 (single bit per state)\n");
-#endif
- fprintf(fd, " -T create trail files in read-only mode\n");
- fprintf(fd, " -tsuf replace .trail with .suf on trailfiles\n");
- fprintf(fd, " -V print SPIN version number\n");
- fprintf(fd, " -v verbose -- filenames in unreached state listing\n");
- fprintf(fd, " -wN hashtable of 2^N entries ");
- fprintf(fd, "(defaults to -w%d)\n", ssize);
- fprintf(fd, " -x do not overwrite an existing trail file\n");
-#if NCORE>1
- fprintf(fd, " -zN handoff states below depth N to 2nd cpu (multi_core)\n");
-#endif
-#ifdef HAS_CODE
- fprintf(fd, "\n options -r, -C, -PN, -g, and -S can optionally be followed by\n");
- fprintf(fd, " a 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)
-{ char *tmp;
-#ifdef MEMLIM
- if (memcnt+ (double) n > memlim) goto err;
-#endif
-#if 1
- tmp = (char *) malloc(n);
- if (!tmp)
-#else
- tmp = (char *) sbrk(n);
- if (tmp == (char *) -ONE_L)
-#endif
- {
-#ifdef MEMLIM
-err:
-#endif
- printf("pan: out of memory\n");
-#ifdef MEMLIM
- printf(" %g bytes used\n", memcnt);
- printf(" %g bytes more needed\n", (double) n);
- printf(" %g bytes limit\n",
- memlim);
-#endif
-#ifdef COLLAPSE
- printf("hint: to reduce memory, recompile with\n");
-#ifndef MA
- printf(" -DMA=%d # better/slower compression, or\n", hmax);
-#endif
- printf(" -DBITSTATE # supertrace, approximation\n");
-#else
-#ifndef BITSTATE
- printf("hint: to reduce memory, recompile with\n");
-#ifndef HC
- printf(" -DCOLLAPSE # good, fast compression, or\n");
-#ifndef MA
- printf(" -DMA=%d # better/slower compression, or\n", hmax);
-#endif
- printf(" -DHC # hash-compaction, approximation\n");
-#endif
- 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;
- return tmp;
-}
-
-#define CHUNK (100*VECTORSZ)
-
-char *
-emalloc(unsigned long 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)
- { grow = (n < CHUNK) ? CHUNK : n;
- have = Malloc(grow);
- fragment += (double) left;
- left = grow;
- }
- tmp = have;
- have += (long) n;
- left -= (long) n;
- memset(tmp, 0, n);
- return tmp;
-}
-void
-Uerror(char *str)
-{ /* always fatal */
- uerror(str);
-#if NCORE>1
- sudden_stop("Uerror");
-#endif
- wrapup();
-}
-
-#if defined(MA) && !defined(SAFETY)
-int
-Unwind(void)
-{ Trans *t; uchar ot, _m; int tt; short II;
-#ifdef VERBOSE
- int i;
-#endif
- uchar oat = now._a_t;
- now._a_t &= ~(1|16|32);
- memcpy((char *) &comp_now, (char *) &now, vsize);
- now._a_t = oat;
-Up:
-#ifdef SC
- trpt = getframe(depth);
-#endif
-#ifdef VERBOSE
- printf("%d State: ", depth);
- for (i = 0; i < vsize; i++) printf("%d%s,",
- ((char *)&now)[i], Mask[i]?"*":"");
- printf("\n");
-#endif
-#ifndef NOFAIR
- if (trpt->o_pm&128) /* fairness alg */
- { now._cnt[now._a_t&1] = trpt->bup.oval;
- depth--;
-#ifdef SC
- trpt = getframe(depth);
-#else
- trpt--;
-#endif
- goto Q999;
- }
-#endif
-#ifdef HAS_LAST
-#ifdef VERI
- { int d; Trail *trl;
- now._last = 0;
- for (d = 1; d < depth; d++)
- { trl = getframe(depth-d); /* was trl = (trpt-d); */
- if (trl->pr != 0)
- { now._last = trl->pr - BASE;
- break;
- } } }
-#else
- now._last = (depth<1)?0:(trpt-1)->pr;
-#endif
-#endif
-#ifdef EVENT_TRACE
- now._event = trpt->o_event;
-#endif
- if ((now._a_t&1) && depth <= A_depth)
- { now._a_t &= ~(1|16|32);
- if (fairness) now._a_t |= 2; /* ? */
- A_depth = 0;
- goto CameFromHere; /* checkcycles() */
- }
- t = trpt->o_t;
- ot = trpt->o_ot; II = trpt->pr;
- tt = trpt->o_tt; this = pptr(II);
- _m = do_reverse(t, II, trpt->o_m);
-#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] <unwind>\n",
- trpt->tau, (trpt-1)->tau);
-#endif
- depth--;
-#ifdef SC
- trpt = getframe(depth);
-#else
- trpt--;
-#endif
- /* reached[ot][t->st] = 1; 3.4.13 */
- ((P0 *)this)->_p = tt;
-#ifndef NOFAIR
- if ((trpt->o_pm&32))
- {
-#ifdef VERI
- if (now._cnt[now._a_t&1] == 0)
- now._cnt[now._a_t&1] = 1;
-#endif
- now._cnt[now._a_t&1] += 1;
- }
-Q999:
- if (trpt->o_pm&8)
- { now._a_t &= ~2;
- now._cnt[now._a_t&1] = 0;
- }
- if (trpt->o_pm&16)
- now._a_t |= 2;
-#endif
-CameFromHere:
- if (memcmp((char *) &now, (char *) &comp_now, vsize) == 0)
- return depth;
- if (depth > 0) goto Up;
- return 0;
-}
-#endif
-static char unwinding;
-void
-uerror(char *str)
-{ static char laststr[256];
- int is_cycle;
-
- if (unwinding) return; /* 1.4.2 */
- if (strncmp(str, laststr, 254))
-#if NCORE>1
- cpu_printf("pan: %s (at depth %ld)\n", str,
-#else
- printf("pan: %s (at depth %ld)\n", str,
-#endif
-#if NCORE>1
- (nr_handoffs * z_handoff) +
-#endif
- ((depthfound==-1)?depth:depthfound));
- strncpy(laststr, str, 254);
- errors++;
-#ifdef HAS_CODE
- if (readtrail) { wrap_trail(); return; }
-#endif
- is_cycle = (strstr(str, " cycle") != (char *) 0);
- if (!is_cycle)
- { depth++; trpt++;
- }
- if ((every_error != 0)
- || errors == upto)
- {
-#if defined(MA) && !defined(SAFETY)
- if (is_cycle)
- { int od = depth;
- unwinding = 1;
- depthfound = Unwind();
- unwinding = 0;
- depth = od;
- }
-#endif
-#if NCORE>1
- writing_trail = 1;
-#endif
-#ifdef BFS
- if (depth > 1) trpt--;
- nuerror(str);
- if (depth > 1) trpt++;
-#else
- putrail();
-#endif
-#if defined(MA) && !defined(SAFETY)
- if (strstr(str, " cycle"))
- { if (every_error)
- printf("sorry: MA writes 1 trail max\n");
- 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
- if (iterative != 0 && maxdepth > 0)
- { maxdepth = (iterative == 1)?(depth-1):(depth/2);
- warned = 1;
- printf("pan: reducing search depth to %ld\n",
- maxdepth);
- } else
-#endif
- if (errors >= upto && upto != 0)
- {
-#if NCORE>1
- sudden_stop("uerror");
-#endif
- wrapup();
- }
- depthfound = -1;
-}
-
-int
-xrefsrc(int lno, S_F_MAP *mp, int M, int i)
-{ Trans *T; int j, retval=1;
- for (T = trans[M][i]; T; T = T->nxt)
- if (T && T->tp)
- { if (strcmp(T->tp, ".(goto)") == 0
- || 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(", state %d", i);
- if (strcmp(T->tp, "") != 0)
- { char *q;
- q = transmognify(T->tp);
- printf(", \"%s\"", q?q:"");
- } else if (stopstate[M][i])
- printf(", -end state-");
- printf("\n");
- retval = 0; /* reported */
- }
- return retval;
-}
-
-void
-r_ck(uchar *which, int N, int M, short *src, S_F_MAP *mp)
-{ int i, m=0;
-
-#ifdef VERI
- if (M == VERI && !verbose) return;
-#endif
- printf("unreached in proctype %s\n", procname[M]);
- for (i = 1; i < N; i++)
- if (which[i] == 0
- && (mapstate[M][i] == 0
- || which[mapstate[M][i]] == 0))
- m += xrefsrc((int) src[i], mp, M, i);
- else
- m++;
- printf(" (%d of %d states)\n", N-1-m, N-1);
-}
-#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)
- { 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)
- { write(fd, "-1:-1:-1\n", 9);
- } }
-}
-#endif
-#endif
-
-void
-putrail(void)
-{ 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));
-#endif
-#ifdef MERGED
- sprintf(snap, "-4:-4:-4\n");
- write(fd, snap, strlen(snap));
-#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);
- trl = getframe(i);
- if (!trl->o_t) continue;
- if (trl->o_pm&128) continue;
- sprintf(snap, "%ld:%d:%d\n",
- i, trl->pr, trl->o_t->t_id);
- j = strlen(snap);
- if (write(fd, snap, j) != j)
- { printf("pan: error writing trailfile\n");
- close(fd);
- wrapup();
- } }
-#endif
- close(fd);
-#if NCORE>1
- cpu_printf("pan: wrote trailfile\n");
-#endif
-}
-
-void
-sv_save(void) /* push state vector onto save stack */
-{ if (!svtack->nxt)
- { svtack->nxt = (Svtack *) emalloc(sizeof(Svtack));
- svtack->nxt->body = emalloc(vsize*sizeof(char));
- svtack->nxt->lst = svtack;
- svtack->nxt->m_delta = vsize;
- svmax++;
- } else if (vsize > svtack->nxt->m_delta)
- { svtack->nxt->body = emalloc(vsize*sizeof(char));
- svtack->nxt->lst = svtack;
- svtack->nxt->m_delta = vsize;
- svmax++;
- }
- svtack = svtack->nxt;
-#if SYNC
- svtack->o_boq = boq;
-#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
- cpu_printf("%d: sv_save\n", depth);
-#endif
-}
-
-void
-sv_restor(void) /* pop state vector from save stack */
-{
- memcpy((char *)&now, svtack->body, svtack->o_delta);
-#if SYNC
- boq = svtack->o_boq;
-#endif
-#if defined(C_States) && (HAS_TRACK==1)
-#ifdef HAS_STACK
- c_unstack((uchar *) &(svtack->c_stack[0]));
-#endif
- c_revert((uchar *) &(now.c_state[0]));
-#endif
- if (vsize != svtack->o_delta)
- Uerror("sv_restor");
- if (!svtack->lst)
- Uerror("error: v_restor");
- svtack = svtack->lst;
-#ifdef DEBUG
- cpu_printf(" sv_restor\n");
-#endif
-}
-
-void
-p_restor(int h)
-{ int i; char *z = (char *) &now;
-
- proc_offset[h] = stack->o_offset;
- proc_skip[h] = (uchar) stack->o_skip;
-#ifndef XUSAFE
- p_name[h] = stack->o_name;
-#endif
-#ifndef NOCOMP
- for (i = vsize + stack->o_skip; i > vsize; i--)
- Mask[i-1] = 1; /* align */
-#endif
- vsize += stack->o_skip;
- memcpy(z+vsize, stack->body, stack->o_delta);
- vsize += stack->o_delta;
-#ifndef NOVSZ
- now._vsz = vsize;
-#endif
-#ifndef NOCOMP
- for (i = 1; i <= Air[((P0 *)pptr(h))->_t]; i++)
- Mask[vsize - i] = 1; /* pad */
- Mask[proc_offset[h]] = 1; /* _pid */
-#endif
- if (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 */
- Uerror("error: p_restor");
- stack = stack->lst;
- this = pptr(h);
- while (i-- > 0)
- q_restor();
-}
-
-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
- vsize += stack->o_skip;
- memcpy(z+vsize, stack->body, stack->o_delta);
- vsize += stack->o_delta;
-#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 */
- Uerror("error: q_restor");
- stack = stack->lst;
-}
-typedef struct IntChunks {
- int *ptr;
- struct IntChunks *nxt;
-} IntChunks;
-IntChunks *filled_chunks[512];
-IntChunks *empty_chunks[512];
-int *
-grab_ints(int nr)
-{ IntChunks *z;
- if (nr >= 512) Uerror("cannot happen grab_int");
- if (filled_chunks[nr])
- { z = filled_chunks[nr];
- filled_chunks[nr] = filled_chunks[nr]->nxt;
- } else
- { z = (IntChunks *) emalloc(sizeof(IntChunks));
- z->ptr = (int *) emalloc(nr * sizeof(int));
- }
- z->nxt = empty_chunks[nr];
- empty_chunks[nr] = z;
- return z->ptr;
-}
-void
-ungrab_ints(int *p, int nr)
-{ IntChunks *z;
- if (!empty_chunks[nr]) Uerror("cannot happen ungrab_int");
- z = empty_chunks[nr];
- empty_chunks[nr] = empty_chunks[nr]->nxt;
- z->ptr = p;
- z->nxt = filled_chunks[nr];
- filled_chunks[nr] = z;
-}
-int
-delproc(int sav, int h)
-{ int d, i=0;
-#ifndef NOCOMP
- int o_vsize = vsize;
-#endif
- if (h+1 != (int) now._nr_pr) return 0;
-
- while (now._nr_qs
- && q_offset[now._nr_qs-1] > proc_offset[h])
- { delq(sav);
- i++;
- }
- 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->lst = stack;
- smax++;
- }
- stack = stack->nxt;
- stack->o_offset = proc_offset[h];
-#if VECTORSZ>32000
- stack->o_skip = (int) proc_skip[h];
-#else
- stack->o_skip = (short) proc_skip[h];
-#endif
-#ifndef XUSAFE
- stack->o_name = p_name[h];
-#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;
- memset((char *)pptr(h), 0, d);
- vsize -= (int) proc_skip[h];
-#ifndef NOVSZ
- now._vsz = vsize;
-#endif
-#ifndef NOCOMP
- for (i = vsize; i < o_vsize; i++)
- Mask[i] = 0; /* reset */
-#endif
- return 1;
-}
-
-void
-delq(int sav)
-{ int h = now._nr_qs - 1;
- int d = vsize - q_offset[now._nr_qs - 1];
-#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->lst = stack;
- smax++;
- }
- stack = stack->nxt;
- stack->o_offset = q_offset[h];
-#if VECTORSZ>32000
- stack->o_skip = (int) q_skip[h];
-#else
- stack->o_skip = (short) q_skip[h];
-#endif
-#ifndef XUSAFE
- stack->o_name = q_name[h];
-#endif
- stack->o_delta = d;
- memcpy(stack->body, (char *)qptr(h), d);
- }
- vsize = q_offset[h];
- now._nr_qs = now._nr_qs - 1;
- memset((char *)qptr(h), 0, d);
- vsize -= (int) q_skip[h];
-#ifndef NOVSZ
- now._vsz = vsize;
-#endif
-#ifndef NOCOMP
- for (k = vsize; k < o_vsize; k++)
- Mask[k] = 0; /* reset */
-#endif
-}
-
-int
-qs_empty(void)
-{ int i;
- for (i = 0; i < (int) now._nr_qs; i++)
- { if (q_sz(i) > 0)
- return 0;
- }
- return 1;
-}
-
-int
-endstate(void)
-{ int i; P0 *ptr;
- for (i = BASE; i < (int) now._nr_pr; i++)
- { ptr = (P0 *) pptr(i);
- if (!stopstate[ptr->_t][ptr->_p])
- return 0;
- }
- if (strict) return qs_empty();
-#if defined(EVENT_TRACE) && !defined(OTIM)
- if (!stopstate[EVENT_TRACE][now._event] && !a_cycles)
- { printf("pan: event_trace not completed\n");
- return 0;
- }
-#endif
- return 1;
-}
-
-#ifndef SAFETY
-void
-checkcycles(void)
-{ uchar o_a_t = now._a_t;
-#ifdef SCHED
- int o_limit;
-#endif
-#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
- now._a_t |= (1|16|32);
- /* 1 = 2nd DFS; (16|32) to help hasher */
-#ifndef NOFAIR
- now._cnt[1] = now._cnt[0];
-#endif
- memcpy((char *)&A_Root, (char *)&now, vsize);
- A_depth = depthfound = depth;
-#if NCORE>1
- mem_put_acc();
-#else
- #ifdef SCHED
- o_limit = trpt->sched_limit;
- trpt->sched_limit = 0;
- #endif
- new_state(); /* start 2nd DFS */
- #ifdef SCHED
- trpt->sched_limit = o_limit;
- #endif
-#endif
- now._a_t = o_a_t;
-#ifndef NOFAIR
- now._cnt[1] = o_cnt;
-#endif
- A_depth = 0; depthfound = -1;
-#ifdef DEBUG
- printf("%d: cycle check returns\n", depth);
-#endif
-#ifdef FULLSTACK
-#ifndef MA
- trpt->ostate = sv; /* restore */
-#else
- trpt->proviso = prov;
-#endif
-#endif
-}
-#endif
-
-#if defined(FULLSTACK) && defined(BITSTATE)
-struct H_el *Free_list = (struct 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;
- if (v && ((int) v->tagged >= n))
- goto gotcha;
- ngrabs++;
- }
- return (struct H_el *)
- emalloc(sizeof(struct H_el)+n-sizeof(unsigned));
-}
-
-#else
-#if NCORE>1
-struct H_el *
-grab_state(int n)
-{ struct H_el *grab_shared(int);
- return grab_shared(sizeof(struct H_el)+n-sizeof(unsigned));
-}
-#else
- #ifndef AUTO_RESIZE
- #define grab_state(n) (struct H_el *) \
- emalloc(sizeof(struct H_el)+n-sizeof(unsigned long));
- #else
- struct H_el *
- grab_state(int n)
- { struct H_el *p;
- int cnt = sizeof(struct H_el)+n-sizeof(unsigned long);
-
- if (reclaim_size >= cnt+WS)
- { if ((cnt & (WS-1)) != 0) /* alignment */
- { cnt += WS - (cnt & (WS-1));
- }
- p = (struct H_el *) reclaim_mem;
- reclaim_mem += cnt;
- reclaim_size -= cnt;
- memset(p, 0, cnt);
- } else
- { p = (struct H_el *) emalloc(cnt);
- }
- return p;
- }
- #endif
-#endif
-#endif
-#ifdef COLLAPSE
-unsigned long
-ordinal(char *v, long n, short tp)
-{ struct H_el *tmp, *ntmp; long m;
- struct H_el *olst = (struct H_el *) 0;
- s_hash((uchar *)v, n);
-#if NCORE>1 && !defined(SEP_STATE)
- enter_critical(CS_ID); /* uses spinlock - 1..128 */
-#endif
- tmp = H_tab[j1];
- if (!tmp)
- { tmp = grab_state(n);
- H_tab[j1] = tmp;
- } else
- for ( ;; olst = tmp, tmp = tmp->nxt)
- { m = memcmp(((char *)&(tmp->state)), v, n);
- if (n == tmp->ln)
- {
- if (m == 0)
- goto done;
- if (m < 0)
- {
-Insert: ntmp = grab_state(n);
- ntmp->nxt = tmp;
- if (!olst)
- H_tab[j1] = ntmp;
- else
- olst->nxt = ntmp;
- tmp = ntmp;
- break;
- } else if (!tmp->nxt)
- {
-Append: tmp->nxt = grab_state(n);
- tmp = tmp->nxt;
- break;
- }
- continue;
- }
- if (n < tmp->ln)
- goto Insert;
- else if (!tmp->nxt)
- goto Append;
- }
- m = ++ncomps[tp];
-#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); /* uses spinlock */
-#endif
-#ifdef FULLSTACK
- return tmp->tagged;
-#else
- return tmp->st_id;
-#endif
-}
-
-int
-compress(char *vin, int nin) /* collapse compression */
-{ char *w, *v = (char *) &comp_now;
- int i, j;
- unsigned long n;
- static char *x;
- static uchar nbytes[513]; /* 1 + 256 + 256 */
- static unsigned short nbytelen;
- long col_q(int, char *);
- long col_p(int, char *);
-#ifndef SAFETY
- if (a_cycles)
- *v++ = now._a_t;
-#ifndef NOFAIR
- if (fairness)
- for (i = 0; i < NFAIR; i++)
- *v++ = now._cnt[i];
-#endif
-#endif
- nbytelen = 0;
-#ifndef JOINPROCS
- for (i = 0; i < (int) now._nr_pr; i++)
- { n = col_p(i, (char *) 0);
-#ifdef NOFIX
- nbytes[nbytelen] = 0;
-#else
- nbytes[nbytelen] = 1;
- *v++ = ((P0 *) pptr(i))->_t;
-#endif
- *v++ = n&255;
- if (n >= (1<<8))
- { nbytes[nbytelen]++;
- *v++ = (n>>8)&255;
- }
- if (n >= (1<<16))
- { nbytes[nbytelen]++;
- *v++ = (n>>16)&255;
- }
- if (n >= (1<<24))
- { nbytes[nbytelen]++;
- *v++ = (n>>24)&255;
- }
- nbytelen++;
- }
-#else
- x = scratch;
- for (i = 0; i < (int) now._nr_pr; i++)
- x += col_p(i, x);
- n = ordinal(scratch, x-scratch, 2); /* procs */
- *v++ = n&255;
- nbytes[nbytelen] = 0;
- if (n >= (1<<8))
- { nbytes[nbytelen]++;
- *v++ = (n>>8)&255;
- }
- if (n >= (1<<16))
- { nbytes[nbytelen]++;
- *v++ = (n>>16)&255;
- }
- if (n >= (1<<24))
- { nbytes[nbytelen]++;
- *v++ = (n>>24)&255;
- }
- nbytelen++;
-#endif
-#ifdef SEPQS
- for (i = 0; i < (int) now._nr_qs; i++)
- { n = col_q(i, (char *) 0);
- nbytes[nbytelen] = 0;
- *v++ = n&255;
- if (n >= (1<<8))
- { nbytes[nbytelen]++;
- *v++ = (n>>8)&255;
- }
- if (n >= (1<<16))
- { nbytes[nbytelen]++;
- *v++ = (n>>16)&255;
- }
- if (n >= (1<<24))
- { nbytes[nbytelen]++;
- *v++ = (n>>24)&255;
- }
- nbytelen++;
- }
-#endif
-#ifdef NOVSZ
- /* 3 = _a_t, _nr_pr, _nr_qs */
- w = (char *) &now + 3 * sizeof(uchar);
-#ifndef NOFAIR
- w += NFAIR;
-#endif
-#else
-#if VECTORSZ<65536
- w = (char *) &(now._vsz) + sizeof(unsigned short);
-#else
- w = (char *) &(now._vsz) + sizeof(unsigned long);
-#endif
-#endif
- x = scratch;
- *x++ = now._nr_pr;
- *x++ = now._nr_qs;
- if (now._nr_qs > 0 && qptr(0) < pptr(0))
- n = qptr(0) - (uchar *) w;
- else
- n = pptr(0) - (uchar *) w;
- j = w - (char *) &now;
- for (i = 0; i < (int) n; i++, w++)
- if (!Mask[j++]) *x++ = *w;
-#ifndef SEPQS
- for (i = 0; i < (int) now._nr_qs; i++)
- x += col_q(i, x);
-#endif
- x--;
- for (i = 0, j = 6; i < nbytelen; i++)
- { if (j == 6)
- { j = 0;
- *(++x) = 0;
- } else
- j += 2;
- *x |= (nbytes[i] << j);
- }
- x++;
- for (j = 0; j < WS-1; j++)
- *x++ = 0;
- x -= j; j = 0;
- n = ordinal(scratch, x-scratch, 0); /* globals */
- *v++ = n&255;
- if (n >= (1<< 8)) { *v++ = (n>> 8)&255; j++; }
- if (n >= (1<<16)) { *v++ = (n>>16)&255; j++; }
- if (n >= (1<<24)) { *v++ = (n>>24)&255; j++; }
- *v++ = j; /* add last count as a byte */
- for (i = 0; i < WS-1; i++)
- *v++ = 0;
- v -= i;
-#if 0
- printf("collapse %d -> %d\n",
- vsize, v - (char *)&comp_now);
-#endif
- return v - (char *)&comp_now;
-}
-#else
-#if !defined(NOCOMP)
-int
-compress(char *vin, int n) /* default compression */
-{
-#ifdef HC
- int delta = 0;
- s_hash((uchar *)vin, n); /* sets K1 and K2 */
-#ifndef SAFETY
- if (S_A)
- { delta++; /* _a_t */
-#ifndef NOFAIR
- if (S_A > NFAIR)
- delta += NFAIR; /* _cnt[] */
-#endif
- }
-#endif
- memcpy((char *) &comp_now + delta, (char *) &K1, WS);
- delta += WS;
-#if HC>0
- memcpy((char *) &comp_now + delta, (char *) &K2, HC);
- delta += HC;
-#endif
- return delta;
-#else
- char *vv = vin;
- char *v = (char *) &comp_now;
- int i;
- #ifndef NO_FAST_C
- int r = 0, unroll = n/8;
- 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;
- }
- r = (n+WS-1)/WS; /* words rounded up */
- r *= WS; /* bytes */
- i = r - i; /* remainder */
- switch (i) {
- 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);
-#endif
- return v - (char *)&comp_now;
-#endif
-}
-#endif
-#endif
-#if defined(FULLSTACK) && defined(BITSTATE)
-#if defined(MA)
-#if !defined(onstack_now)
-int onstack_now(void) {}
-#endif
-#if !defined(onstack_put)
-void onstack_put(void) {}
-#endif
-#if !defined(onstack_zap)
-void onstack_zap(void) {}
-#endif
-#else
-void
-onstack_zap(void)
-{ struct H_el *v, *w, *last = 0;
- struct H_el **tmp = H_tab;
- char *nv; int n, m;
-
- static char warned = 0;
-
- H_tab = S_Tab;
-#ifndef NOCOMP
- nv = (char *) &comp_now;
- n = compress((char *)&now, vsize);
-#else
-#if defined(BITSTATE) && defined(LC)
- nv = (char *) &comp_now;
- n = compact_stack((char *)&now, vsize);
-#else
- nv = (char *) &now;
- n = vsize;
-#endif
-#endif
-#if !defined(HC) && !(defined(BITSTATE) && defined(LC))
- s_hash((uchar *)nv, n);
-#endif
- H_tab = tmp;
- for (v = S_Tab[j1]; v; Zh++, last=v, v=v->nxt)
- { m = memcmp(&(v->state), nv, n);
- if (m == 0)
- goto Found;
- if (m < 0)
- break;
- }
-/* NotFound: */
-#ifndef ZAPH
- #if defined(BITSTATE) && NCORE>1
- /* seen this happen, likely harmless, but not yet understood */
- if (warned == 0)
- #endif
- { /* Uerror("stack out of wack - zap"); */
- cpu_printf("pan: warning, stack incomplete\n");
- warned = 1;
- }
-#endif
- return;
-Found:
- ZAPS++;
- if (last)
- last->nxt = v->nxt;
- else
- S_Tab[j1] = v->nxt;
- v->tagged = (unsigned) n;
-#if !defined(NOREDUCE) && !defined(SAFETY)
- v->proviso = 0;
-#endif
- v->nxt = last = (struct H_el *) 0;
- for (w = Free_list; w; Fa++, last=w, w = w->nxt)
- { if ((int) w->tagged <= n)
- { if (last)
- { v->nxt = w;
- last->nxt = v;
- } else
- { v->nxt = Free_list;
- Free_list = v;
- }
- return;
- }
- if (!w->nxt)
- { w->nxt = v;
- return;
- } }
- 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
- #ifndef ZAPH
- Uerror("cannot happen - unstack_put");
- #endif
-#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;
-
- 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
-void
-hinit(void)
-{
- #ifdef MA
-#ifdef R_XPT
- { void r_xpoint(void);
- r_xpoint();
- }
-#else
- dfa_init((unsigned short) (MA+a_cycles));
-#if NCORE>1 && !defined(COLLAPSE)
- if (!readtrail)
- { void init_HT(unsigned long);
- init_HT(0L);
- }
-#endif
-#endif
- #endif
- #if !defined(MA) || defined(COLLAPSE)
-#if NCORE>1
- if (!readtrail)
- { void init_HT(unsigned long);
- init_HT((unsigned long) (ONE_L<<ssize)*sizeof(struct H_el *));
- } else
-#endif
- H_tab = (struct H_el **)
- emalloc((ONE_L<<ssize)*sizeof(struct H_el *));
- #endif
-}
-#endif
-
-#if !defined(BITSTATE) || defined(FULLSTACK)
-#ifdef DEBUG
-void
-dumpstate(int wasnew, char *v, int n, int tag)
-{ int i;
-#ifndef SAFETY
- if (S_A)
- { printf(" state tags %d (%d::%d): ",
- V_A, wasnew, v[0]);
-#ifdef FULLSTACK
- printf(" %d ", tag);
-#endif
- printf("\n");
- }
-#endif
-#ifdef SDUMP
-#ifndef NOCOMP
- printf(" State: ");
- for (i = 0; i < vsize; i++) printf("%d%s,",
- ((char *)&now)[i], Mask[i]?"*":"");
-#endif
- printf("\n Vector: ");
- for (i = 0; i < n; i++) printf("%d,", v[i]);
- printf("\n");
-#endif
-}
-#endif
-#ifdef MA
-int
-gstore(char *vin, int nin, uchar pbit)
-{ int n, i;
- int ret_val = 1;
- uchar *v;
- static uchar Info[MA+1];
-#ifndef NOCOMP
- n = compress(vin, nin);
- v = (uchar *) &comp_now;
-#else
- n = nin;
- v = 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;
- }
- for (i = 0; i < n; i++)
- { Info[i] = v[i];
- }
- for ( ; i < MA-1; i++)
- { Info[i] = 0;
- }
- Info[MA-1] = pbit;
- if (a_cycles) /* place _a_t at the end */
- { Info[MA] = Info[0];
- Info[0] = 0;
- }
-
-#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)
- && depth > A_depth)
- { Info[MA] &= ~(1|16|32); /* _a_t */
- if (dfa_member(MA))
- { Info[MA-1] = 4; /* off-stack bit */
- nShadow++;
- if (!dfa_member(MA-1))
- { ret_val = 3;
- #ifdef VERBOSE
- printf("intersected 1st dfs stack\n");
- #endif
- goto done;
- } } }
- ret_val = 0;
- #ifdef VERBOSE
- printf("new state\n");
- #endif
- goto done;
- }
-#ifdef FULLSTACK
- if (pbit == 0)
- { Info[MA-1] = 1; /* proviso bit */
-#ifndef BFS
- trpt->proviso = dfa_member(MA-1);
-#endif
- Info[MA-1] = 4; /* off-stack bit */
- if (dfa_member(MA-1))
- { ret_val = 1; /* off-stack */
- #ifdef VERBOSE
- printf("old state\n");
- #endif
- } else
- { ret_val = 2; /* on-stack */
- #ifdef VERBOSE
- printf("on-stack\n");
- #endif
- }
- goto done;
- }
-#endif
- ret_val = 1;
-#ifdef VERBOSE
- printf("old state\n");
-#endif
-done:
-#if NCORE>1 && !defined(SEP_STATE)
- leave_critical(GLOBAL_LOCK);
-#endif
- return ret_val; /* old state */
-}
-#endif
-#if defined(BITSTATE) && defined(LC)
-int
-compact_stack(char *vin, int n)
-{ int delta = 0;
- s_hash((uchar *)vin, n); /* sets K1 and K2 */
-#ifndef SAFETY
- delta++; /* room for state[0] |= 128 */
-#endif
- memcpy((char *) &comp_now + delta, (char *) &K1, WS);
- delta += WS;
- memcpy((char *) &comp_now + delta, (char *) &K2, WS);
- delta += WS; /* use all available bits */
- return delta;
-}
-#endif
-int
-hstore(char *vin, int nin) /* hash table storage */
-{ struct H_el *ntmp;
- struct H_el *tmp, *olst = (struct H_el *) 0;
- char *v; int n, m=0;
-#ifdef HC
- uchar rem_a;
-#endif
-#ifdef NOCOMP
-#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
- v = vin; n = nin;
-#endif
-#else
- v = (char *) &comp_now;
- #ifdef HC
- rem_a = now._a_t;
- now._a_t = 0;
- #endif
- n = compress(vin, nin);
- #ifdef HC
- now._a_t = rem_a;
- #endif
-#ifndef SAFETY
- if (S_A)
- { v[0] = 0; /* _a_t */
-#ifndef NOFAIR
- if (S_A > NFAIR)
- for (m = 0; m < NFAIR; m++)
- v[m+1] = 0; /* _cnt[] */
-#endif
- m = 0;
- }
- #endif
-#endif
-#if !defined(HC) && !(defined(BITSTATE) && defined(LC))
- s_hash((uchar *)v, n);
-#endif
-#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)
- enter_critical(CS_ID); /* uses spinlock */
-#endif
- tmp = H_tab[j1];
- if (!tmp)
- { tmp = grab_state(n);
-#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] = tmp;
- } else
- { for (;; hcmp++, olst = tmp, tmp = tmp->nxt)
- { /* skip the _a_t and the _cnt bytes */
-#ifdef COLLAPSE
- if (tmp->ln != 0)
- { if (!tmp->nxt) goto Append;
- continue;
- }
-#endif
- m = memcmp(((char *)&(tmp->state)) + S_A,
- v + S_A, n - S_A);
- if (m == 0) {
-#ifdef SAFETY
-#define wasnew 0
-#else
- int wasnew = 0;
-#endif
-#ifndef SAFETY
-#ifndef NOCOMP
- if (S_A)
- { if ((((char *)&(tmp->state))[0] & V_A) != V_A)
- { wasnew = 1; nShadow++;
- ((char *)&(tmp->state))[0] |= V_A;
- }
-#ifndef NOFAIR
- if (S_A > NFAIR)
- { /* 0 <= now._cnt[now._a_t&1] < MAXPROC */
- unsigned 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 */
- { ci = (NFAIR - 1) - ci;
- bp = 7 - bp; /* bp = 0..7 */
- }
- ci++; /* skip over _a_t */
- bp = 1 << bp; /* the bit mask */
- if ((((char *)&(tmp->state))[ci] & bp)==0)
- { if (!wasnew)
- { wasnew = 1;
- nShadow++;
- }
- ((char *)&(tmp->state))[ci] |= bp;
- }
- }
- /* else: wasnew == 0, i.e., old state */
-#endif
- }
-#endif
-#endif
-#if NCORE>1
- Lstate = (struct H_el *) tmp;
-#endif
-#ifdef FULLSTACK
-#ifndef SAFETY
- if (wasnew)
- { Lstate = (struct H_el *) tmp;
- tmp->tagged |= V_A;
- if ((now._a_t&1)
- && (tmp->tagged&A_V)
- && depth > A_depth)
- {
-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 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(" New state %d+\n", (int) tmp->st_id);
-#endif
-#ifdef DEBUG
- dumpstate(1, (char *)&(tmp->state),n,tmp->tagged);
-#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;
-#ifndef SAFETY
- /* already on current dfs stack */
- /* but may also be on 1st dfs stack */
- if ((now._a_t&1)
- && (tmp->tagged&A_V)
- && depth > A_depth
-#ifndef NOFAIR
- && (!fairness || now._cnt[1] <= 1)
-#endif
- )
- goto intersect;
-#endif
-#ifdef CHECK
-#if NCORE>1
- printf("cpu%d: ", core_id);
-#endif
- printf(" Stack state %d\n", (int) tmp->st_id);
-#endif
-#ifdef DEBUG
- dumpstate(0, (char *)&(tmp->state),n,tmp->tagged);
-#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(" New state %d+\n", (int) tmp->st_id);
-#endif
-#ifdef DEBUG
- dumpstate(1, (char *)&(tmp->state), n, 0);
-#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(" Old 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
-#if NCORE>1
- printf("cpu%d: ", core_id);
-#endif
- printf(" ReVisiting (from smaller depth)\n");
-#endif
- nstates--;
-#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)
- leave_critical(CS_ID);
-#endif
- return 0;
- }
-#endif
-#if (defined(BFS) && defined(Q_PROVISO)) || NCORE>1
- Lstate = (struct H_el *) tmp;
-#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;
- else
- olst->nxt = ntmp;
- tmp = ntmp;
- break;
- } else if (!tmp->nxt)
- { /* append after tmp */
-#ifdef COLLAPSE
-Append:
-#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
- 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)
- tmp->D = depth;
-#endif
-#ifndef SAFETY
-#ifndef NOCOMP
- if (S_A)
- { v[0] = V_A;
-#ifndef NOFAIR
- if (S_A > NFAIR)
- { unsigned 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)
- { ci = (NFAIR - 1) - ci;
- bp = 7 - bp; /* bp = 0..7 */
- }
- v[1+ci] = 1 << bp;
- }
-#endif
- }
-#endif
-#endif
-#if defined(AUTO_RESIZE) && !defined(BITSTATE)
- tmp->m_K1 = K1;
-#endif
- memcpy(((char *)&(tmp->state)), v, n);
-#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
- #if NCORE>1
- Lstate = (struct H_el *) tmp;
- #endif
-#endif
-/* #if NCORE>1 && !defined(SEP_STATE) */
-#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
-#include TRANSITIONS
-void
-do_reach(void)
-{
- r_ck(reached0, nstates0, 0, src_ln0, src_file0);
- r_ck(reached1, nstates1, 1, src_ln1, src_file1);
- r_ck(reached2, nstates2, 2, src_ln2, src_file2);
- r_ck(reached3, nstates3, 3, src_ln3, src_file3);
- r_ck(reached4, nstates4, 4, src_ln4, src_file4);
-}
-
-void
-iniglobals(void)
-{
- deliver = 0;
- { int l_in;
- for (l_in = 0; l_in < 4; l_in++)
- {
- now.buffer_use[l_in] = 0;
- }
- }
- now.write_off = 0;
- { int l_in;
- for (l_in = 0; l_in < 2; l_in++)
- {
- now.commit_count[l_in] = 0;
- }
- }
- now.read_off = 0;
- now.events_lost = 0;
- now.refcount = 0;
-#ifdef VAR_RANGES
- { int l_in;
- for (l_in = 0; l_in < 4; l_in++)
- {
- logval("buffer_use[l_in]", now.buffer_use[l_in]);
- }
- }
- logval("write_off", now.write_off);
- { int l_in;
- for (l_in = 0; l_in < 2; l_in++)
- {
- logval("commit_count[l_in]", now.commit_count[l_in]);
- }
- }
- logval("read_off", now.read_off);
- logval("events_lost", now.events_lost);
- logval("refcount", now.refcount);
-#endif
- Maxbody = max(Maxbody, sizeof(State)-VECTORSZ);
-}
-
-int
-addqueue(int n, int is_rv)
-{ int j=0, i = now._nr_qs;
-#ifndef NOCOMP
- int k;
-#endif
- if (i >= MAXQ)
- Uerror("too many queues");
- switch (n) {
- default: Uerror("bad queue - addqueue");
- }
- 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
- vsize += (int) q_skip[i];
- q_offset[i] = vsize;
- now._nr_qs += 1;
- vsize += j;
-#ifndef NOVSZ
- now._vsz = vsize;
-#endif
- hmax = max(hmax, vsize);
- if (vsize >= VECTORSZ)
- Uerror("VECTORSZ is too small, edit pan.h");
- memset((char *)qptr(i), 0, j);
- ((Q0 *)qptr(i))->_t = n;
- return i+1;
-}
-
-#if NQS>0
-void
-qsend(int into, int sorted, int args_given)
-{ int j; uchar *z;
-
-#ifdef HAS_SORTED
- int k;
-#endif
- if (!into--)
- uerror("ref to uninitialized chan name (sending)");
- if (into >= (int) now._nr_qs || into < 0)
- Uerror("qsend bad queue#");
- z = qptr(into);
- j = ((Q0 *)qptr(into))->Qlen;
- switch (((Q0 *)qptr(into))->_t) {
- case 0: printf("queue %d was deleted\n", into+1);
- default: Uerror("bad queue - qsend");
- }
-#ifdef EVENT_TRACE
- if (in_s_scope(into+1))
- require('s', into);
-#endif
-}
-#endif
-
-#if SYNC
-int
-q_zero(int from)
-{ if (!from--)
- { uerror("ref to uninitialized chan name (q_zero)");
- return 0;
- }
- switch(((Q0 *)qptr(from))->_t) {
- case 0: printf("queue %d was deleted\n", from+1);
- }
- Uerror("bad queue q-zero");
- return -1;
-}
-int
-not_RV(int from)
-{ if (q_zero(from))
- { printf("==>> a test of the contents of a rv ");
- printf("channel always returns FALSE\n");
- uerror("error to poll rendezvous channel");
- }
- return 1;
-}
-#endif
-#ifndef XUSAFE
-void
-setq_claim(int x, int m, char *s, int y, char *p)
-{ if (x == 0)
- uerror("x[rs] claim on uninitialized channel");
- if (x < 0 || x > MAXQ)
- Uerror("cannot happen setq_claim");
- q_claim[x] |= m;
- p_name[y] = p;
- q_name[x] = s;
- if (m&2) q_S_check(x, y);
- if (m&1) q_R_check(x, y);
-}
-short q_sender[MAXQ+1];
-int
-q_S_check(int x, int who)
-{ if (!q_sender[x])
- { q_sender[x] = who+1;
-#if SYNC
- if (q_zero(x))
- { printf("chan %s (%d), ",
- q_name[x], x-1);
- printf("sndr proc %s (%d)\n",
- p_name[who], who);
- uerror("xs chans cannot be used for rv");
- }
-#endif
- } else
- if (q_sender[x] != who+1)
- { printf("pan: xs assertion violated: ");
- printf("access to chan <%s> (%d)\npan: by ",
- q_name[x], x-1);
- if (q_sender[x] > 0 && p_name[q_sender[x]-1])
- printf("%s (proc %d) and by ",
- p_name[q_sender[x]-1], q_sender[x]-1);
- printf("%s (proc %d)\n",
- p_name[who], who);
- uerror("error, partial order reduction invalid");
- }
- return 1;
-}
-short q_recver[MAXQ+1];
-int
-q_R_check(int x, int who)
-{ if (!q_recver[x])
- { q_recver[x] = who+1;
-#if SYNC
- if (q_zero(x))
- { printf("chan %s (%d), ",
- q_name[x], x-1);
- printf("recv proc %s (%d)\n",
- p_name[who], who);
- uerror("xr chans cannot be used for rv");
- }
-#endif
- } else
- if (q_recver[x] != who+1)
- { printf("pan: xr assertion violated: ");
- printf("access to chan %s (%d)\npan: ",
- q_name[x], x-1);
- if (q_recver[x] > 0 && p_name[q_recver[x]-1])
- printf("by %s (proc %d) and ",
- p_name[q_recver[x]-1], q_recver[x]-1);
- printf("by %s (proc %d)\n",
- p_name[who], who);
- uerror("error, partial order reduction invalid");
- }
- return 1;
-}
-#endif
-int
-q_len(int x)
-{ if (!x--)
- uerror("ref to uninitialized chan name (len)");
- return ((Q0 *)qptr(x))->Qlen;
-}
-
-int
-q_full(int from)
-{ if (!from--)
- uerror("ref to uninitialized chan name (qfull)");
- switch(((Q0 *)qptr(from))->_t) {
- case 0: printf("queue %d was deleted\n", from+1);
- }
- Uerror("bad queue - q_full");
- return 0;
-}
-
-#ifdef HAS_UNLESS
-int
-q_e_f(int from)
-{ /* empty or full */
- return !q_len(from) || q_full(from);
-}
-#endif
-#if NQS>0
-int
-qrecv(int from, int slot, int fld, int done)
-{ uchar *z;
- int j, k, r=0;
-
- if (!from--)
- uerror("ref to uninitialized chan name (receiving)");
- if (from >= (int) now._nr_qs || from < 0)
- Uerror("qrecv bad queue#");
- z = qptr(from);
-#ifdef EVENT_TRACE
- if (done && (in_r_scope(from+1)))
- require('r', from);
-#endif
- switch (((Q0 *)qptr(from))->_t) {
- case 0: printf("queue %d was deleted\n", from+1);
- default: Uerror("bad queue - qrecv");
- }
- return r;
-}
-#endif
-
-#ifndef BITSTATE
-#ifdef COLLAPSE
-long
-col_q(int i, char *z)
-{ int j=0, k;
- char *x, *y;
- Q0 *ptr = (Q0 *) qptr(i);
- switch (ptr->_t) {
- default: Uerror("bad qtype - collapse");
- }
- if (z) x = z; else x = scratch;
- y = (char *) ptr; k = q_offset[i];
- /* no need to store the empty slots at the end */
- j -= (q_max[ptr->_t] - ptr->Qlen) * ((j - 2)/q_max[ptr->_t]);
- for ( ; j > 0; j--, y++)
- if (!Mask[k++]) *x++ = *y;
- 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
-int
-unsend(int into)
-{ int _m=0, j; uchar *z;
-
-#ifdef HAS_SORTED
- int k;
-#endif
- if (!into--)
- uerror("ref to uninitialized chan (unsend)");
- z = qptr(into);
- j = ((Q0 *)z)->Qlen;
- ((Q0 *)z)->Qlen = --j;
- switch (((Q0 *)qptr(into))->_t) {
- default: Uerror("bad queue - unsend");
- }
- return _m;
-}
-
-void
-unrecv(int from, int slot, int fld, int fldvar, int strt)
-{ int j; uchar *z;
-
- if (!from--)
- uerror("ref to uninitialized chan (unrecv)");
- z = qptr(from);
- j = ((Q0 *)z)->Qlen;
- if (strt) ((Q0 *)z)->Qlen = j+1;
- switch (((Q0 *)qptr(from))->_t) {
- default: Uerror("bad queue - qrecv");
- }
-}
-int
-q_cond(short II, Trans *t)
-{ int i = 0;
- for (i = 0; i < 6; i++)
- { if (t->ty[i] == TIMEOUT_F) return 1;
- if (t->ty[i] == ALPHA_F)
-#ifdef GLOB_ALPHA
- return 0;
-#else
- return (II+1 == (short) now._nr_pr && II+1 < MAXPROC);
-#endif
- switch (t->qu[i]) {
- case 0: break;
- default: Uerror("unknown qid - q_cond");
- return 0;
- }
- }
- return 1;
-}
-void
-to_compile(void)
-{ char ctd[1024], carg[64];
-#ifdef BITSTATE
- strcpy(ctd, "-DBITSTATE ");
-#else
- strcpy(ctd, "");
-#endif
-#ifdef NOVSZ
- strcat(ctd, "-DNOVSZ ");
-#endif
-#ifdef REVERSE
- strcat(ctd, "-DREVERSE ");
-#endif
-#ifdef T_REVERSE
- strcat(ctd, "-DT_REVERSE ");
-#endif
-#ifdef RANDOMIZE
- #if RANDOMIZE>0
- sprintf(carg, "-DRANDOMIZE=%d ", RANDOMIZE);
- strcat(ctd, carg);
- #else
- strcat(ctd, "-DRANDOMIZE ");
- #endif
-#endif
-#ifdef SCHED
- sprintf(carg, "-DSCHED=%d ", SCHED);
- strcat(ctd, carg);
-#endif
-#ifdef BFS
- strcat(ctd, "-DBFS ");
-#endif
-#ifdef MEMLIM
- sprintf(carg, "-DMEMLIM=%d ", MEMLIM);
- strcat(ctd, carg);
-#else
-#ifdef MEMCNT
- sprintf(carg, "-DMEMCNT=%d ", MEMCNT);
- strcat(ctd, carg);
-#endif
-#endif
-#ifdef NOCLAIM
- strcat(ctd, "-DNOCLAIM ");
-#endif
-#ifdef SAFETY
- strcat(ctd, "-DSAFETY ");
-#else
-#ifdef NOFAIR
- strcat(ctd, "-DNOFAIR ");
-#else
-#ifdef NFAIR
- if (NFAIR != 2)
- { sprintf(carg, "-DNFAIR=%d ", NFAIR);
- strcat(ctd, carg);
- }
-#endif
-#endif
-#endif
-#ifdef NOREDUCE
- strcat(ctd, "-DNOREDUCE ");
-#else
-#ifdef XUSAFE
- strcat(ctd, "-DXUSAFE ");
-#endif
-#endif
-#ifdef NP
- strcat(ctd, "-DNP ");
-#endif
-#ifdef PEG
- strcat(ctd, "-DPEG ");
-#endif
-#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 ");
-#endif
-#ifdef CHECK
- strcat(ctd, "-DCHECK ");
-#endif
-#ifdef CTL
- strcat(ctd, "-DCTL ");
-#endif
-#ifdef NIBIS
- strcat(ctd, "-DNIBIS ");
-#endif
-#ifdef NOBOUNDCHECK
- strcat(ctd, "-DNOBOUNDCHECK ");
-#endif
-#ifdef NOSTUTTER
- strcat(ctd, "-DNOSTUTTER ");
-#endif
-#ifdef REACH
- strcat(ctd, "-DREACH ");
-#endif
-#ifdef PRINTF
- strcat(ctd, "-DPRINTF ");
-#endif
-#ifdef OTIM
- strcat(ctd, "-DOTIM ");
-#endif
-#ifdef COLLAPSE
- strcat(ctd, "-DCOLLAPSE ");
-#endif
-#ifdef MA
- sprintf(carg, "-DMA=%d ", MA);
- strcat(ctd, carg);
-#endif
-#ifdef SVDUMP
- strcat(ctd, "-DSVDUMP ");
-#endif
-#ifdef VECTORSZ
- if (VECTORSZ != 1024)
- { sprintf(carg, "-DVECTORSZ=%d ", VECTORSZ);
- strcat(ctd, carg);
- }
-#endif
-#ifdef VERBOSE
- strcat(ctd, "-DVERBOSE ");
-#endif
-#ifdef CHECK
- strcat(ctd, "-DCHECK ");
-#endif
-#ifdef SDUMP
- strcat(ctd, "-DSDUMP ");
-#endif
-#if NCORE>1
- sprintf(carg, "-DNCORE=%d ", NCORE);
- strcat(ctd, carg);
-#endif
-#ifdef SFH
- sprintf(carg, "-DSFH ");
- 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);
-}
-void
-active_procs(void)
-{
- if (!permuted) {
- Addproc(4);
- } else {
- Addproc(4);
- }
-}
-#ifdef MA
-/*
-#include <stdio.h>
-#define uchar unsigned char
-*/
-#define ulong unsigned long
-#define ushort unsigned short
-
-#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))
-
-extern char *emalloc(unsigned long); /* imported routine */
-extern void dfa_init(ushort); /* 4 exported routines */
-extern int dfa_member(ulong);
-extern int dfa_store(uchar *);
-extern void dfa_stats(void);
-
-typedef struct Edge {
- uchar From, To; /* max range 0..255 */
- uchar s, S; /* if s=1, S is singleton */
- struct Vertex *Dst;
- struct Edge *Nxt;
-} Edge;
-
-typedef struct Vertex {
- ulong key, num; /* key for splay tree, nr incoming edges */
- uchar from[2], to[2]; /* in-node predefined edge info */
- struct Vertex *dst[2];/* most nodes have 2 or more edges */
- struct Edge *Succ; /* in case there are more edges */
- struct Vertex *lnk, *left, *right; /* splay tree plumbing */
-} Vertex;
-
-static Edge *free_edges;
-static Vertex *free_vertices;
-static Vertex **layers; /* one splay tree of nodes per layer */
-static Vertex **path; /* run of word in the DFA */
-static Vertex *R, *F, *NF; /* Root, Final, Not-Final */
-static uchar *word, *lastword;/* string, and last string inserted */
-static int dfa_depth, iv=0, nv=0, pfrst=0, Tally;
-
-static void insert_it(Vertex *, int); /* splay-tree code */
-static void delete_it(Vertex *, int);
-static Vertex *find_it(Vertex *, Vertex *, uchar, int);
-
-static void
-recyc_edges(Edge *e)
-{
- if (!e) return;
- recyc_edges(e->Nxt);
- e->Nxt = free_edges;
- free_edges = e;
-}
-
-static Edge *
-new_edge(Vertex *dst)
-{ Edge *e;
-
- if (free_edges)
- { e = free_edges;
- free_edges = e->Nxt;
- e->From = e->To = e->s = e->S = 0;
- e->Nxt = (Edge *) 0;
- } else
- e = (Edge *) emalloc(sizeof(Edge));
- e->Dst = dst;
-
- return e;
-}
-
-static void
-recyc_vertex(Vertex *v)
-{
- recyc_edges(v->Succ);
- v->Succ = (Edge *) free_vertices;
- free_vertices = v;
- nr_states--;
-}
-
-static Vertex *
-new_vertex(void)
-{ Vertex *v;
-
- if (free_vertices)
- { v = free_vertices;
- free_vertices = (Vertex *) v->Succ;
- v->Succ = (Edge *) 0;
- v->num = 0;
- } else
- v = (Vertex *) emalloc(sizeof(Vertex));
-
- nr_states++;
- return v;
-}
-
-static Vertex *
-allDelta(Vertex *v, int n)
-{ Vertex *dst = new_vertex();
-
- v->from[0] = 0;
- v->to[0] = 255;
- v->dst[0] = dst;
- dst->num = 256;
- insert_it(v, n);
- return dst;
-}
-
-static void
-insert_edge(Vertex *v, Edge *e)
-{ /* put new edge first */
- if (!v->dst[0])
- { v->dst[0] = e->Dst;
- v->from[0] = e->From;
- v->to[0] = e->To;
- recyc_edges(e);
- return;
- }
- if (!v->dst[1])
- { v->from[1] = v->from[0]; v->from[0] = e->From;
- v->to[1] = v->to[0]; v->to[0] = e->To;
- v->dst[1] = v->dst[0]; v->dst[0] = e->Dst;
- recyc_edges(e);
- return;
- } /* shift */
- { int f = v->from[1];
- int t = v->to[1];
- Vertex *d = v->dst[1];
- v->from[1] = v->from[0]; v->from[0] = e->From;
- v->to[1] = v->to[0]; v->to[0] = e->To;
- v->dst[1] = v->dst[0]; v->dst[0] = e->Dst;
- e->From = f;
- e->To = t;
- e->Dst = d;
- }
- e->Nxt = v->Succ;
- v->Succ = e;
-}
-
-static void
-copyRecursive(Vertex *v, Edge *e)
-{ Edge *f;
- if (e->Nxt) copyRecursive(v, e->Nxt);
- f = new_edge(e->Dst);
- f->From = e->From;
- f->To = e->To;
- f->s = e->s;
- f->S = e->S;
- f->Nxt = v->Succ;
- v->Succ = f;
-}
-
-static void
-copyEdges(Vertex *to, Vertex *from)
-{ int i;
- for (i = 0; i < 2; i++)
- { to->from[i] = from->from[i];
- to->to[i] = from->to[i];
- to->dst[i] = from->dst[i];
- }
- if (from->Succ) copyRecursive(to, from->Succ);
-}
-
-static Edge *
-cacheDelta(Vertex *v, int h, int first)
-{ static Edge *ov, tmp; int i;
-
- if (!first && INRANGE(ov,h))
- return ov; /* intercepts about 10% */
- for (i = 0; i < 2; i++)
- if (v->dst[i] && h >= v->from[i] && h <= v->to[i])
- { tmp.From = v->from[i];
- tmp.To = v->to[i];
- tmp.Dst = v->dst[i];
- tmp.s = tmp.S = 0;
- ov = &tmp;
- return ov;
- }
- for (ov = v->Succ; ov; ov = ov->Nxt)
- if (INRANGE(ov,h)) return ov;
-
- Uerror("cannot get here, cacheDelta");
- return (Edge *) 0;
-}
-
-static Vertex *
-Delta(Vertex *v, int h) /* v->delta[h] */
-{ Edge *e;
-
- if (v->dst[0] && h >= v->from[0] && h <= v->to[0])
- return v->dst[0]; /* oldest edge */
- if (v->dst[1] && h >= v->from[1] && h <= v->to[1])
- return v->dst[1];
- for (e = v->Succ; e; e = e->Nxt)
- if (INRANGE(e,h))
- return e->Dst;
- Uerror("cannot happen Delta");
- return (Vertex *) 0;
-}
-
-static void
-numDelta(Vertex *v, int d)
-{ Edge *e;
- ulong cnt;
- int i;
-
- for (i = 0; i < 2; i++)
- if (v->dst[i])
- { cnt = v->dst[i]->num + d*(1 + v->to[i] - v->from[i]);
- if (d == 1 && cnt < v->dst[i]->num) goto bad;
- v->dst[i]->num = cnt;
- }
- for (e = v->Succ; e; e = e->Nxt)
- { cnt = e->Dst->num + d*(1 + e->To - e->From + e->s);
- if (d == 1 && cnt < e->Dst->num)
-bad: Uerror("too many incoming edges");
- e->Dst->num = cnt;
- }
-}
-
-static void
-setDelta(Vertex *v, int h, Vertex *newdst) /* v->delta[h] = newdst; */
-{ Edge *e, *f = (Edge *) 0, *g;
- int i;
-
- /* remove the old entry, if there */
- for (i = 0; i < 2; i++)
- if (v->dst[i] && h >= v->from[i] && h <= v->to[i])
- { if (h == v->from[i])
- { if (h == v->to[i])
- { v->dst[i] = (Vertex *) 0;
- v->from[i] = v->to[i] = 0;
- } else
- v->from[i]++;
- } else if (h == v->to[i])
- { v->to[i]--;
- } else
- { g = new_edge(v->dst[i]);/* same dst */
- g->From = v->from[i];
- g->To = h-1; /* left half */
- v->from[i] = h+1; /* right half */
- insert_edge(v, g);
- }
- goto part2;
- }
- for (e = v->Succ; e; f = e, e = e->Nxt)
- { if (e->s == 1 && e->S == h)
- { e->s = e->S = 0;
- goto rem_tst;
- }
- if (h >= e->From && h <= e->To)
- { if (h == e->From)
- { if (h == e->To)
- { if (e->s)
- { e->From = e->To = e->S;
- e->s = 0;
- break;
- } else
- goto rem_do;
- } else
- e->From++;
- } else if (h == e->To)
- { e->To--;
- } else /* split */
- { g = new_edge(e->Dst); /* same dst */
- g->From = e->From;
- g->To = h-1; /* g=left half */
- e->From = h+1; /* e=right half */
- g->Nxt = e->Nxt; /* insert g */
- e->Nxt = g; /* behind e */
- break; /* done */
- }
-
-rem_tst: if (e->From > e->To)
- { if (e->s == 0) {
-rem_do: if (f)
- f->Nxt = e->Nxt;
- else
- v->Succ = e->Nxt;
- e->Nxt = (Edge *) 0;
- recyc_edges(e);
- } else
- { e->From = e->To = e->S;
- e->s = 0;
- } }
- break;
- } }
-part2:
- /* check if newdst is already there */
- for (i = 0; i < 2; i++)
- if (v->dst[i] == newdst)
- { if (h+1 == (int) v->from[i])
- { v->from[i] = h;
- return;
- }
- if (h == (int) v->to[i]+1)
- { v->to[i] = h;
- return;
- } }
- for (e = v->Succ; e; e = e->Nxt)
- { if (e->Dst == newdst)
- { if (h+1 == (int) e->From)
- { e->From = h;
- if (e->s == 1 && e->S+1 == e->From)
- { e->From = e->S;
- e->s = e->S = 0;
- }
- return;
- }
- if (h == (int) e->To+1)
- { e->To = h;
- if (e->s == 1 && e->S == e->To+1)
- { e->To = e->S;
- e->s = e->S = 0;
- }
- return;
- }
- if (e->s == 0)
- { e->s = 1;
- e->S = h;
- return;
- } } }
- /* add as a new edge */
- e = new_edge(newdst);
- e->From = e->To = h;
- insert_edge(v, e);
-}
-
-static ulong
-cheap_key(Vertex *v)
-{ ulong vk2 = 0;
-
- if (v->dst[0])
- { vk2 = (ulong) v->dst[0];
- if ((ulong) v->dst[1] > vk2)
- vk2 = (ulong) v->dst[1];
- } else if (v->dst[1])
- vk2 = (ulong) v->dst[1];
- if (v->Succ)
- { Edge *e;
- for (e = v->Succ; e; e = e->Nxt)
- if ((ulong) e->Dst > vk2)
- vk2 = (ulong) e->Dst;
- }
- Tally = (vk2>>2)&(TWIDTH-1);
- return v->key;
-}
-
-static ulong
-mk_key(Vertex *v) /* not sensitive to order */
-{ ulong m = 0, vk2 = 0;
- Edge *e;
-
- if (v->dst[0])
- { m += HASH(v->dst[0], v->to[0] - v->from[0] + 1);
- vk2 = (ulong) v->dst[0];
- }
- if (v->dst[1])
- { m += HASH(v->dst[1], v->to[1] - v->from[1] + 1);
- if ((ulong) v->dst[1] > vk2) vk2 = (ulong) v->dst[1];
- }
- for (e = v->Succ; e; e = e->Nxt)
- { m += HASH(e->Dst, e->To - e->From + 1 + e->s);
- if ((ulong) e->Dst > vk2) vk2 = (ulong) e->Dst;
- }
- Tally = (vk2>>2)&(TWIDTH-1);
- return m;
-}
-
-static ulong
-mk_special(int sigma, Vertex *n, Vertex *v)
-{ ulong m = 0, vk2 = 0;
- Edge *f;
- int i;
-
- for (i = 0; i < 2; i++)
- if (v->dst[i])
- { if (sigma >= v->from[i] && sigma <= v->to[i])
- { m += HASH(v->dst[i], v->to[i]-v->from[i]);
- if ((ulong) v->dst[i] > vk2
- && v->to[i] > v->from[i])
- vk2 = (ulong) v->dst[i];
- } else
- { m += HASH(v->dst[i], v->to[i]-v->from[i]+1);
- if ((ulong) v->dst[i] > vk2)
- vk2 = (ulong) v->dst[i];
- } }
- for (f = v->Succ; f; f = f->Nxt)
- { if (sigma >= f->From && sigma <= f->To)
- { m += HASH(f->Dst, f->To - f->From + f->s);
- if ((ulong) f->Dst > vk2
- && f->To - f->From + f->s > 0)
- vk2 = (ulong) f->Dst;
- } else if (f->s == 1 && sigma == f->S)
- { m += HASH(f->Dst, f->To - f->From + 1);
- if ((ulong) f->Dst > vk2) vk2 = (ulong) f->Dst;
- } else
- { m += HASH(f->Dst, f->To - f->From + 1 + f->s);
- if ((ulong) f->Dst > vk2) vk2 = (ulong) f->Dst;
- } }
-
- if ((ulong) n > vk2) vk2 = (ulong) n;
- Tally = (vk2>>2)&(TWIDTH-1);
- m += HASH(n, 1);
- return m;
-}
-
-void
-dfa_init(ushort nr_layers)
-{ int i; Vertex *r, *t;
-
- dfa_depth = nr_layers; /* one byte per layer */
- path = (Vertex **) emalloc((dfa_depth+1)*sizeof(Vertex *));
- layers = (Vertex **) emalloc(TWIDTH*(dfa_depth+1)*sizeof(Vertex *));
- lastword = (uchar *) emalloc((dfa_depth+1)*sizeof(uchar));
- lastword[dfa_depth] = lastword[0] = 255;
- path[0] = R = new_vertex(); F = new_vertex();
-
- for (i = 1, r = R; i < dfa_depth; i++, r = t)
- t = allDelta(r, i-1);
- NF = allDelta(r, i-1);
-}
-
-#if 0
-static void complement_dfa(void) { Vertex *tmp = F; F = NF; NF = tmp; }
-#endif
-
-double
-tree_stats(Vertex *t)
-{ Edge *e; double cnt=0.0;
- if (!t) return 0;
- if (!t->key) return 0;
- t->key = 0; /* precaution */
- if (t->dst[0]) cnt++;
- if (t->dst[1]) cnt++;
- for (e = t->Succ; e; e = e->Nxt)
- cnt++;
- cnt += tree_stats(t->lnk);
- cnt += tree_stats(t->left);
- cnt += tree_stats(t->right);
- return cnt;
-}
-
-void
-dfa_stats(void)
-{ int i, j; double cnt = 0.0;
- for (j = 0; j < TWIDTH; j++)
- for (i = 0; i < dfa_depth+1; i++)
- cnt += tree_stats(layers[i*TWIDTH+j]);
- printf("Minimized Automaton: %6d nodes and %6g edges\n",
- nr_states, cnt);
-}
-
-int
-dfa_member(ulong n)
-{ Vertex **p, **q;
- uchar *w = &word[n];
- int i;
-
- p = &path[n]; q = (p+1);
- for (i = n; i < dfa_depth; i++)
- *q++ = Delta(*p++, *w++);
- return (*p == F);
-}
-
-int
-dfa_store(uchar *sv)
-{ Vertex **p, **q, *s, *y, *old, *new = F;
- uchar *w, *u = lastword;
- int i, j, k;
-
- w = word = sv;
- while (*w++ == *u++) /* find first byte that differs */
- ;
- pfrst = (int) (u - lastword) - 1;
- memcpy(&lastword[pfrst], &sv[pfrst], dfa_depth-pfrst);
- if (pfrst > iv) pfrst = iv;
- if (pfrst > nv) pfrst = nv;
-/* phase1: */
- p = &path[pfrst]; q = (p+1); w = &word[pfrst];
- for (i = pfrst; i < dfa_depth; i++)
- *q++ = Delta(*p++, *w++); /* (*p)->delta[*w++]; */
-
- if (*p == F) return 1; /* it's already there */
-/* phase2: */
- iv = dfa_depth;
- do { iv--;
- old = new;
- new = find_it(path[iv], old, word[iv], iv);
- } while (new && iv > 0);
-
-/* phase3: */
- nv = k = 0; s = path[0];
- for (j = 1; j <= iv; ++j)
- if (path[j]->num > 1)
- { y = new_vertex();
- copyEdges(y, path[j]);
- insert_it(y, j);
- numDelta(y, 1);
- delete_it(s, j-1);
- setDelta(s, word[j-1], y);
- insert_it(s, j-1);
- y->num = 1; /* initial value 1 */
- s = y;
- path[j]->num--; /* only 1 moved from j to y */
- k = 1;
- } else
- { s = path[j];
- if (!k) nv = j;
- }
- y = Delta(s, word[iv]);
- y->num--;
- delete_it(s, iv);
- setDelta(s, word[iv], old);
- insert_it(s, iv);
- old->num++;
-
- for (j = iv+1; j < dfa_depth; j++)
- if (path[j]->num == 0)
- { numDelta(path[j], -1);
- delete_it(path[j], j);
- recyc_vertex(path[j]);
- } else
- break;
- return 0;
-}
-
-static Vertex *
-splay(ulong i, Vertex *t)
-{ Vertex N, *l, *r, *y;
-
- if (!t) return t;
- N.left = N.right = (Vertex *) 0;
- l = r = &N;
- for (;;)
- { if (i < t->key)
- { if (!t->left) break;
- if (i < t->left->key)
- { y = t->left;
- t->left = y->right;
- y->right = t;
- t = y;
- if (!t->left) break;
- }
- r->left = t;
- r = t;
- t = t->left;
- } else if (i > t->key)
- { if (!t->right) break;
- if (i > t->right->key)
- { y = t->right;
- t->right = y->left;
- y->left = t;
- t = y;
- if (!t->right) break;
- }
- l->right = t;
- l = t;
- t = t->right;
- } else
- break;
- }
- l->right = t->left;
- r->left = t->right;
- t->left = N.right;
- t->right = N.left;
- return t;
-}
-
-static void
-insert_it(Vertex *v, int L)
-{ Vertex *new, *t;
- ulong i; int nr;
-
- i = mk_key(v);
- nr = ((L*TWIDTH)+Tally);
- t = layers[nr];
-
- v->key = i;
- if (!t)
- { layers[nr] = v;
- return;
- }
- t = splay(i, t);
- if (i < t->key)
- { new = v;
- new->left = t->left;
- new->right = t;
- t->left = (Vertex *) 0;
- } else if (i > t->key)
- { new = v;
- new->right = t->right;
- new->left = t;
- t->right = (Vertex *) 0;
- } else /* it's already there */
- { v->lnk = t->lnk; /* put in linked list off v */
- t->lnk = v;
- new = t;
- }
- layers[nr] = new;
-}
-
-static int
-checkit(Vertex *h, Vertex *v, Vertex *n, uchar sigma)
-{ Edge *g, *f;
- int i, k, j = 1;
-
- for (k = 0; k < 2; k++)
- if (h->dst[k])
- { if (sigma >= h->from[k] && sigma <= h->to[k])
- { if (h->dst[k] != n) goto no_match;
- }
- for (i = h->from[k]; i <= h->to[k]; i++)
- { if (i == sigma) continue;
- g = cacheDelta(v, i, j); j = 0;
- if (h->dst[k] != g->Dst)
- goto no_match;
- if (g->s == 0 || g->S != i)
- i = g->To;
- } }
- for (f = h->Succ; f; f = f->Nxt)
- { if (INRANGE(f,sigma))
- { if (f->Dst != n) goto no_match;
- }
- for (i = f->From; i <= f->To; i++)
- { if (i == sigma) continue;
- g = cacheDelta(v, i, j); j = 0;
- if (f->Dst != g->Dst)
- goto no_match;
- if (g->s == 1 && i == g->S)
- continue;
- i = g->To;
- }
- if (f->s && f->S != sigma)
- { g = cacheDelta(v, f->S, 1);
- if (f->Dst != g->Dst)
- goto no_match;
- }
- }
- if (h->Succ || h->dst[0] || h->dst[1]) return 1;
-no_match:
- return 0;
-}
-
-static Vertex *
-find_it(Vertex *v, Vertex *n, uchar sigma, int L)
-{ Vertex *z, *t;
- ulong i; int nr;
-
- i = mk_special(sigma,n,v);
- nr = ((L*TWIDTH)+Tally);
- t = layers[nr];
-
- if (!t) return (Vertex *) 0;
- layers[nr] = t = splay(i, t);
- if (i == t->key)
- for (z = t; z; z = z->lnk)
- if (checkit(z, v, n, sigma))
- return z;
-
- return (Vertex *) 0;
-}
-
-static void
-delete_it(Vertex *v, int L)
-{ Vertex *x, *t;
- ulong i; int nr;
-
- i = cheap_key(v);
- nr = ((L*TWIDTH)+Tally);
- t = layers[nr];
- if (!t) return;
-
- t = splay(i, t);
- if (i == t->key)
- { Vertex *z, *y = (Vertex *) 0;
- for (z = t; z && z != v; y = z, z = z->lnk)
- ;
- if (z != v) goto bad;
- if (y)
- { y->lnk = z->lnk;
- z->lnk = (Vertex *) 0;
- layers[nr] = t;
- return;
- } else if (z->lnk) /* z == t == v */
- { y = z->lnk;
- y->left = t->left;
- y->right = t->right;
- t->left = t->right = t->lnk = (Vertex *) 0;
- layers[nr] = y;
- return;
- }
- /* delete the node itself */
- if (!t->left)
- { x = t->right;
- } else
- { x = splay(i, t->left);
- x->right = t->right;
- }
- t->left = t->right = t->lnk = (Vertex *) 0;
- layers[nr] = x;
- return;
- }
-bad: Uerror("cannot happen delete");
-}
-#endif
-#if defined(MA) && (defined(W_XPT) || defined(R_XPT))
-static Vertex **temptree;
-static char wbuf[4096];
-static int WCNT = 4096, wcnt=0;
-static uchar stacker[MA+1];
-static ulong stackcnt = 0;
-extern double nstates, nlinks, truncs, truncs2;
-
-static void
-xwrite(int fd, char *b, int n)
-{
- if (wcnt+n >= 4096)
- { write(fd, wbuf, wcnt);
- wcnt = 0;
- }
- memcpy(&wbuf[wcnt], b, n);
- wcnt += n;
-}
-
-static void
-wclose(fd)
-{
- if (wcnt > 0)
- write(fd, wbuf, wcnt);
- wcnt = 0;
- close(fd);
-}
-
-static void
-w_vertex(int fd, Vertex *v)
-{ char t[3]; int i; Edge *e;
-
- xwrite(fd, (char *) &v, sizeof(Vertex *));
- t[0] = 0;
- for (i = 0; i < 2; i++)
- if (v->dst[i])
- { t[1] = v->from[i], t[2] = v->to[i];
- xwrite(fd, t, 3);
- xwrite(fd, (char *) &(v->dst[i]), sizeof(Vertex *));
- }
- for (e = v->Succ; e; e = e->Nxt)
- { t[1] = e->From, t[2] = e->To;
- xwrite(fd, t, 3);
- xwrite(fd, (char *) &(e->Dst), sizeof(Vertex *));
-
- if (e->s)
- { t[1] = t[2] = e->S;
- xwrite(fd, t, 3);
- xwrite(fd, (char *) &(e->Dst), sizeof(Vertex *));
- } }
-}
-
-static void
-w_layer(int fd, Vertex *v)
-{ uchar c=1;
-
- if (!v) return;
- xwrite(fd, (char *) &c, 1);
- w_vertex(fd, v);
- w_layer(fd, v->lnk);
- w_layer(fd, v->left);
- w_layer(fd, v->right);
-}
-
-void
-w_xpoint(void)
-{ int fd; char nm[64];
- int i, j; uchar c;
- static uchar xwarned = 0;
-
- sprintf(nm, "%s.xpt", PanSource);
- if ((fd = creat(nm, 0666)) <= 0)
- if (!xwarned)
- { xwarned = 1;
- printf("cannot creat checkpoint file\n");
- return;
- }
- xwrite(fd, (char *) &nstates, sizeof(double));
- xwrite(fd, (char *) &truncs, sizeof(double));
- xwrite(fd, (char *) &truncs2, sizeof(double));
- xwrite(fd, (char *) &nlinks, sizeof(double));
- xwrite(fd, (char *) &dfa_depth, sizeof(int));
- xwrite(fd, (char *) &R, sizeof(Vertex *));
- xwrite(fd, (char *) &F, sizeof(Vertex *));
- xwrite(fd, (char *) &NF, sizeof(Vertex *));
-
- for (j = 0; j < TWIDTH; j++)
- for (i = 0; i < dfa_depth+1; i++)
- { w_layer(fd, layers[i*TWIDTH+j]);
- c = 2; xwrite(fd, (char *) &c, 1);
- }
- wclose(fd);
-}
-
-static void
-xread(int fd, char *b, int n)
-{ int m = wcnt; int delta = 0;
- if (m < n)
- { if (m > 0) memcpy(b, &wbuf[WCNT-m], m);
- delta = m;
- WCNT = wcnt = read(fd, wbuf, 4096);
- if (wcnt < n-m)
- Uerror("xread failed -- insufficient data");
- n -= m;
- }
- memcpy(&b[delta], &wbuf[WCNT-wcnt], n);
- wcnt -= n;
-}
-
-static void
-x_cleanup(Vertex *c)
-{ Edge *e; /* remove the tree and edges from c */
- if (!c) return;
- for (e = c->Succ; e; e = e->Nxt)
- x_cleanup(e->Dst);
- recyc_vertex(c);
-}
-
-static void
-x_remove(void)
-{ Vertex *tmp; int i, s;
- int r, j;
- /* double-check: */
- 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);
- for (i = 0; i < dfa_depth; i++)
- printf("%d,", stacker[i]);
- printf(" -- not a stackstate <o:%d,4:%d>\n", r, j);
- return;
- }
- stacker[dfa_depth-1] = 1;
- s = dfa_member(dfa_depth-1);
-
- { tmp = F; F = NF; NF = tmp; } /* complement */
- if (s) dfa_store(stacker);
- stacker[dfa_depth-1] = 0;
- dfa_store(stacker);
- stackcnt++;
- { tmp = F; F = NF; NF = tmp; }
-}
-
-static void
-x_rm_stack(Vertex *t, int k)
-{ int j; Edge *e;
-
- if (k == 0)
- { x_remove();
- return;
- }
- if (t)
- for (e = t->Succ; e; e = e->Nxt)
- { for (j = e->From; j <= (int) e->To; j++)
- { stacker[k] = (uchar) j;
- x_rm_stack(e->Dst, k-1);
- }
- if (e->s)
- { stacker[k] = e->S;
- x_rm_stack(e->Dst, k-1);
- } }
-}
-
-static Vertex *
-insert_withkey(Vertex *v, int L)
-{ Vertex *new, *t = temptree[L];
-
- if (!t) { temptree[L] = v; return v; }
- t = splay(v->key, t);
- if (v->key < t->key)
- { new = v;
- new->left = t->left;
- new->right = t;
- t->left = (Vertex *) 0;
- } else if (v->key > t->key)
- { new = v;
- new->right = t->right;
- new->left = t;
- t->right = (Vertex *) 0;
- } else
- { if (t != R && t != F && t != NF)
- Uerror("double insert, bad checkpoint data");
- else
- { recyc_vertex(v);
- new = t;
- } }
- temptree[L] = new;
-
- return new;
-}
-
-static Vertex *
-find_withkey(Vertex *v, int L)
-{ Vertex *t = temptree[L];
- if (t)
- { temptree[L] = t = splay((ulong) v, t);
- if (t->key == (ulong) v)
- return t;
- }
- Uerror("not found error, bad checkpoint data");
- return (Vertex *) 0;
-}
-
-void
-r_layer(int fd, int n)
-{ Vertex *v;
- Edge *e;
- char c, t[2];
-
- for (;;)
- { xread(fd, &c, 1);
- if (c == 2) break;
- if (c == 1)
- { v = new_vertex();
- xread(fd, (char *) &(v->key), sizeof(Vertex *));
- v = insert_withkey(v, n);
- } else /* c == 0 */
- { e = new_edge((Vertex *) 0);
- xread(fd, t, 2);
- e->From = t[0];
- e->To = t[1];
- xread(fd, (char *) &(e->Dst), sizeof(Vertex *));
- insert_edge(v, e);
- } }
-}
-
-static void
-v_fix(Vertex *t, int nr)
-{ int i; Edge *e;
-
- if (!t) return;
-
- for (i = 0; i < 2; i++)
- if (t->dst[i])
- t->dst[i] = find_withkey(t->dst[i], nr);
-
- for (e = t->Succ; e; e = e->Nxt)
- e->Dst = find_withkey(e->Dst, nr);
-
- v_fix(t->left, nr);
- v_fix(t->right, nr);
-}
-
-static void
-v_insert(Vertex *t, int nr)
-{ Edge *e; int i;
-
- if (!t) return;
- v_insert(t->left, nr);
- v_insert(t->right, nr);
-
- /* remove only leafs from temptree */
- t->left = t->right = t->lnk = (Vertex *) 0;
- insert_it(t, nr); /* into layers */
- for (i = 0; i < 2; i++)
- if (t->dst[i])
- t->dst[i]->num += (t->to[i] - t->from[i] + 1);
- for (e = t->Succ; e; e = e->Nxt)
- e->Dst->num += (e->To - e->From + 1 + e->s);
-}
-
-static void
-x_fixup(void)
-{ int i;
-
- for (i = 0; i < dfa_depth; i++)
- v_fix(temptree[i], (i+1));
-
- for (i = dfa_depth; i >= 0; i--)
- v_insert(temptree[i], i);
-}
-
-static Vertex *
-x_tail(Vertex *t, ulong want)
-{ int i, yes, no; Edge *e; Vertex *v = (Vertex *) 0;
-
- if (!t) return v;
-
- yes = no = 0;
- for (i = 0; i < 2; i++)
- if ((ulong) t->dst[i] == want)
- { /* was t->from[i] <= 0 && t->to[i] >= 0 */
- /* but from and to are uchar */
- if (t->from[i] == 0)
- yes = 1;
- else
- if (t->from[i] <= 4 && t->to[i] >= 4)
- no = 1;
- }
-
- for (e = t->Succ; e; e = e->Nxt)
- if ((ulong) e->Dst == want)
- { /* was INRANGE(e,0) but From and To are uchar */
- if ((e->From == 0) || (e->s==1 && e->S==0))
- yes = 1;
- else if (INRANGE(e, 4))
- no = 1;
- }
- if (yes && !no) return t;
- v = x_tail(t->left, want); if (v) return v;
- v = x_tail(t->right, want); if (v) return v;
- return (Vertex *) 0;
-}
-
-static void
-x_anytail(Vertex *t, Vertex *c, int nr)
-{ int i; Edge *e, *f; Vertex *v;
-
- if (!t) return;
-
- for (i = 0; i < 2; i++)
- if ((ulong) t->dst[i] == c->key)
- { v = new_vertex(); v->key = t->key;
- f = new_edge(v);
- f->From = t->from[i];
- f->To = t->to[i];
- f->Nxt = c->Succ;
- c->Succ = f;
- if (nr > 0)
- x_anytail(temptree[nr-1], v, nr-1);
- }
-
- for (e = t->Succ; e; e = e->Nxt)
- if ((ulong) e->Dst == c->key)
- { v = new_vertex(); v->key = t->key;
- f = new_edge(v);
- f->From = e->From;
- f->To = e->To;
- f->s = e->s;
- f->S = e->S;
- f->Nxt = c->Succ;
- c->Succ = f;
- x_anytail(temptree[nr-1], v, nr-1);
- }
-
- x_anytail(t->left, c, nr);
- x_anytail(t->right, c, nr);
-}
-
-static Vertex *
-x_cpy_rev(void)
-{ Vertex *c, *v; /* find 0 and !4 predecessor of F */
-
- v = x_tail(temptree[dfa_depth-1], F->key);
- if (!v) return (Vertex *) 0;
-
- c = new_vertex(); c->key = v->key;
-
- /* every node on dfa_depth-2 that has v->key as succ */
- /* make copy and let c point to these (reversing ptrs) */
-
- x_anytail(temptree[dfa_depth-2], c, dfa_depth-2);
-
- return c;
-}
-
-void
-r_xpoint(void)
-{ int fd; char nm[64]; Vertex *d;
- int i, j;
-
- wcnt = 0;
- sprintf(nm, "%s.xpt", PanSource);
- if ((fd = open(nm, 0)) < 0) /* O_RDONLY */
- Uerror("cannot open checkpoint file");
-
- xread(fd, (char *) &nstates, sizeof(double));
- xread(fd, (char *) &truncs, sizeof(double));
- xread(fd, (char *) &truncs2, sizeof(double));
- xread(fd, (char *) &nlinks, sizeof(double));
- xread(fd, (char *) &dfa_depth, sizeof(int));
-
- if (dfa_depth != MA+a_cycles)
- Uerror("bad dfa_depth in checkpoint file");
-
- path = (Vertex **) emalloc((dfa_depth+1)*sizeof(Vertex *));
- layers = (Vertex **) emalloc(TWIDTH*(dfa_depth+1)*sizeof(Vertex *));
- temptree = (Vertex **) emalloc((dfa_depth+2)*sizeof(Vertex *));
- lastword = (uchar *) emalloc((dfa_depth+1)*sizeof(uchar));
- lastword[dfa_depth] = lastword[0] = 255;
-
- path[0] = R = new_vertex();
- xread(fd, (char *) &R->key, sizeof(Vertex *));
- R = insert_withkey(R, 0);
-
- F = new_vertex();
- xread(fd, (char *) &F->key, sizeof(Vertex *));
- F = insert_withkey(F, dfa_depth);
-
- NF = new_vertex();
- xread(fd, (char *) &NF->key, sizeof(Vertex *));
- NF = insert_withkey(NF, dfa_depth);
-
- for (j = 0; j < TWIDTH; j++)
- for (i = 0; i < dfa_depth+1; i++)
- r_layer(fd, i);
-
- if (wcnt != 0) Uerror("bad count in checkpoint file");
-
- d = x_cpy_rev();
- x_fixup();
- stacker[dfa_depth-1] = 0;
- x_rm_stack(d, dfa_depth-2);
- x_cleanup(d);
- close(fd);
-
- printf("pan: removed %d stackstates\n", stackcnt);
- nstates -= (double) stackcnt;
-}
-#endif
-#ifdef VERI
-void
-check_claim(int st)
-{
- if (st == endclaim)
- uerror("claim violated!");
- if (stopstate[VERI][st])
- uerror("end state in claim reached");
-}
-#endif
-void
-c_globals(void)
-{ /* int i; */
- printf("global vars:\n");
- printf(" byte write_off: %d\n", now.write_off);
- { int l_in;
- for (l_in = 0; l_in < 2; l_in++)
- {
- printf(" byte commit_count[%d]: %d\n", l_in, now.commit_count[l_in]);
- }
- }
- printf(" byte read_off: %d\n", now.read_off);
- printf(" byte events_lost: %d\n", now.events_lost);
- printf(" byte refcount: %d\n", now.refcount);
- { int l_in;
- for (l_in = 0; l_in < 4; l_in++)
- {
- printf(" bit buffer_use[%d]: %d\n", l_in, now.buffer_use[l_in]);
- }
- }
-}
-void
-c_locals(int pid, int tp)
-{ /* int i; */
- switch(tp) {
- case 4:
- printf("local vars proc %d (:init:):\n", pid);
- printf(" byte i: %d\n", ((P4 *)pptr(pid))->i);
- printf(" byte j: %d\n", ((P4 *)pptr(pid))->j);
- printf(" byte sum: %d\n", ((P4 *)pptr(pid))->sum);
- printf(" byte commit_sum: %d\n", ((P4 *)pptr(pid))->commit_sum);
- break;
- case 3:
- /* none */
- break;
- case 2:
- printf("local vars proc %d (reader):\n", pid);
- printf(" byte i: %d\n", ((P2 *)pptr(pid))->i);
- printf(" byte j: %d\n", ((P2 *)pptr(pid))->j);
- break;
- case 1:
- printf("local vars proc %d (tracer):\n", pid);
- printf(" byte size: %d\n", ((P1 *)pptr(pid))->size);
- printf(" byte prev_off: %d\n", ((P1 *)pptr(pid))->prev_off);
- printf(" byte new_off: %d\n", ((P1 *)pptr(pid))->new_off);
- printf(" byte tmp_commit: %d\n", ((P1 *)pptr(pid))->tmp_commit);
- printf(" byte i: %d\n", ((P1 *)pptr(pid))->i);
- printf(" byte j: %d\n", ((P1 *)pptr(pid))->j);
- break;
- case 0:
- printf("local vars proc %d (switcher):\n", pid);
- printf(" byte prev_off: %d\n", ((P0 *)pptr(pid))->prev_off);
- printf(" byte new_off: %d\n", ((P0 *)pptr(pid))->new_off);
- printf(" byte tmp_commit: %d\n", ((P0 *)pptr(pid))->tmp_commit);
- printf(" byte size: %d\n", ((P0 *)pptr(pid))->size);
- break;
- }
-}
-void
-printm(int x)
-{
- switch (x) {
- default: Printf("%d", x);
- }
-}
-void
-c_chandump(int unused) { unused++; /* avoid complaints */ }
+++ /dev/null
-#ifdef PEG
-struct T_SRC {
- char *fl; int ln;
-} T_SRC[NTRANS];
-
-void
-tr_2_src(int m, char *file, int ln)
-{ T_SRC[m].fl = file;
- T_SRC[m].ln = ln;
-}
-
-void
-putpeg(int n, int m)
-{ printf("%5d trans %4d ", m, n);
- printf("file %s line %3d\n",
- T_SRC[n].fl, T_SRC[n].ln);
-}
-#endif
-
-void
-settable(void)
-{ Trans *T;
- Trans *settr(int, int, int, int, int, char *, int, int, int);
-
- trans = (Trans ***) emalloc(6*sizeof(Trans **));
-
- /* proctype 4: :init: */
-
- trans[4] = (Trans **) emalloc(57*sizeof(Trans *));
-
- T = trans[ 4][41] = settr(158,2,0,0,0,"ATOMIC", 1, 2, 0);
- T->nxt = settr(158,2,1,0,0,"ATOMIC", 1, 2, 0);
- trans[4][1] = settr(118,2,7,3,3,"i = 0", 1, 2, 0);
- trans[4][8] = settr(125,2,7,1,0,".(goto)", 1, 2, 0);
- T = trans[4][7] = settr(124,2,0,0,0,"DO", 1, 2, 0);
- T = T->nxt = settr(124,2,2,0,0,"DO", 1, 2, 0);
- T->nxt = settr(124,2,5,0,0,"DO", 1, 2, 0);
- trans[4][2] = settr(119,2,7,4,4,"((i<2))", 1, 2, 0); /* m: 3 -> 7,0 */
- reached4[3] = 1;
- trans[4][3] = settr(0,0,0,0,0,"commit_count[i] = 0",0,0,0);
- trans[4][4] = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
- trans[4][5] = settr(122,2,16,5,5,"((i>=2))", 1, 2, 0); /* m: 10 -> 16,0 */
- reached4[10] = 1;
- trans[4][6] = settr(123,2,10,1,0,"goto :b6", 1, 2, 0); /* m: 10 -> 0,16 */
- reached4[10] = 1;
- trans[4][9] = settr(126,2,10,1,0,"break", 1, 2, 0);
- trans[4][10] = settr(127,2,16,6,6,"i = 0", 1, 2, 0);
- trans[4][17] = settr(134,2,16,1,0,".(goto)", 1, 2, 0);
- T = trans[4][16] = settr(133,2,0,0,0,"DO", 1, 2, 0);
- T = T->nxt = settr(133,2,11,0,0,"DO", 1, 2, 0);
- T->nxt = settr(133,2,14,0,0,"DO", 1, 2, 0);
- trans[4][11] = settr(128,2,16,7,7,"((i<4))", 1, 2, 0); /* m: 12 -> 16,0 */
- reached4[12] = 1;
- trans[4][12] = settr(0,0,0,0,0,"buffer_use[i] = 0",0,0,0);
- trans[4][13] = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
- trans[4][14] = settr(131,2,19,8,8,"((i>=4))", 1, 2, 0);
- trans[4][15] = settr(132,2,19,1,0,"goto :b7", 1, 2, 0);
- trans[4][18] = settr(135,2,19,1,0,"break", 1, 2, 0);
- trans[4][19] = settr(136,2,20,9,9,"(run reader())", 1, 2, 0);
- trans[4][20] = settr(137,2,28,10,10,"(run cleaner())", 1, 2, 0); /* m: 21 -> 28,0 */
- reached4[21] = 1;
- trans[4][21] = settr(0,0,0,0,0,"i = 0",0,0,0);
- trans[4][29] = settr(146,2,28,1,0,".(goto)", 1, 2, 0);
- T = trans[4][28] = settr(145,2,0,0,0,"DO", 1, 2, 0);
- T = T->nxt = settr(145,2,22,0,0,"DO", 1, 2, 0);
- T->nxt = settr(145,2,26,0,0,"DO", 1, 2, 0);
- trans[4][22] = settr(139,2,24,11,11,"((i<4))", 1, 2, 0); /* m: 23 -> 24,0 */
- reached4[23] = 1;
- trans[4][23] = settr(0,0,0,0,0,"refcount = (refcount+1)",0,0,0);
- trans[4][24] = settr(141,2,28,12,12,"(run tracer())", 1, 2, 0); /* m: 25 -> 28,0 */
- reached4[25] = 1;
- trans[4][25] = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
- trans[4][26] = settr(143,2,38,13,13,"((i>=4))", 1, 2, 0); /* m: 31 -> 38,0 */
- reached4[31] = 1;
- trans[4][27] = settr(144,2,31,1,0,"goto :b8", 1, 2, 0); /* m: 31 -> 0,38 */
- reached4[31] = 1;
- trans[4][30] = settr(147,2,31,1,0,"break", 1, 2, 0);
- trans[4][31] = settr(148,2,38,14,14,"i = 0", 1, 2, 0);
- trans[4][39] = settr(156,2,38,1,0,".(goto)", 1, 2, 0);
- T = trans[4][38] = settr(155,2,0,0,0,"DO", 1, 2, 0);
- T = T->nxt = settr(155,2,32,0,0,"DO", 1, 2, 0);
- T->nxt = settr(155,2,36,0,0,"DO", 1, 2, 0);
- trans[4][32] = settr(149,2,34,15,15,"((i<1))", 1, 2, 0); /* m: 33 -> 34,0 */
- reached4[33] = 1;
- trans[4][33] = settr(0,0,0,0,0,"refcount = (refcount+1)",0,0,0);
- trans[4][34] = settr(151,2,38,16,16,"(run switcher())", 1, 2, 0); /* m: 35 -> 38,0 */
- reached4[35] = 1;
- trans[4][35] = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
- trans[4][36] = settr(153,2,40,17,17,"((i>=1))", 1, 2, 0); /* m: 37 -> 40,0 */
- reached4[37] = 1;
- trans[4][37] = settr(154,2,40,1,0,"goto :b9", 1, 2, 0);
- trans[4][40] = settr(157,0,55,1,0,"break", 1, 2, 0);
- T = trans[ 4][55] = settr(172,2,0,0,0,"ATOMIC", 1, 2, 0);
- T->nxt = settr(172,2,42,0,0,"ATOMIC", 1, 2, 0);
- trans[4][42] = settr(159,2,50,18,18,"assert((((write_off-read_off)>=0)&&((write_off-read_off)<(255/2))))", 1, 2, 0); /* m: 43 -> 0,50 */
- reached4[43] = 1;
- trans[4][43] = settr(0,0,0,0,0,"j = 0",0,0,0);
- trans[4][44] = settr(0,0,0,0,0,"commit_sum = 0",0,0,0);
- trans[4][51] = settr(168,2,50,1,0,".(goto)", 1, 2, 0);
- T = trans[4][50] = settr(167,2,0,0,0,"DO", 1, 2, 0);
- T = T->nxt = settr(167,2,45,0,0,"DO", 1, 2, 0);
- T->nxt = settr(167,2,48,0,0,"DO", 1, 2, 0);
- trans[4][45] = settr(162,2,50,19,19,"((j<2))", 1, 2, 0); /* m: 46 -> 50,0 */
- reached4[46] = 1;
- trans[4][46] = settr(0,0,0,0,0,"commit_sum = (commit_sum+commit_count[j])",0,0,0);
- trans[4][47] = settr(0,0,0,0,0,"j = (j+1)",0,0,0);
- trans[4][48] = settr(165,4,56,20,20,"((j>=2))", 1, 2, 0); /* m: 53 -> 56,0 */
- reached4[53] = 1;
- trans[4][49] = settr(166,2,53,1,0,"goto :b10", 1, 2, 0); /* m: 53 -> 0,56 */
- reached4[53] = 1;
- trans[4][52] = settr(169,2,53,1,0,"break", 1, 2, 0);
- trans[4][53] = settr(170,4,56,21,21,"assert((((write_off-commit_sum)>=0)&&((write_off-commit_sum)<(255/2))))", 1, 2, 0); /* m: 54 -> 0,56 */
- reached4[54] = 1;
- trans[4][54] = settr(0,0,0,0,0,"assert((((4+1)>4)||(events_lost==0)))",0,0,0);
- trans[4][56] = settr(173,0,0,22,22,"-end-", 0, 3500, 0);
-
- /* proctype 3: cleaner */
-
- trans[3] = (Trans **) emalloc(10*sizeof(Trans *));
-
- T = trans[ 3][8] = settr(116,2,0,0,0,"ATOMIC", 1, 2, 0);
- T->nxt = settr(116,2,5,0,0,"ATOMIC", 1, 2, 0);
- trans[3][6] = settr(114,2,5,1,0,".(goto)", 1, 2, 0);
- T = trans[3][5] = settr(113,2,0,0,0,"DO", 1, 2, 0);
- T->nxt = settr(113,2,1,0,0,"DO", 1, 2, 0);
- trans[3][1] = settr(109,2,3,23,23,"((refcount==0))", 1, 2, 0); /* m: 2 -> 3,0 */
- reached3[2] = 1;
- trans[3][2] = settr(0,0,0,0,0,"refcount = (refcount+1)",0,0,0);
- trans[3][3] = settr(111,2,7,24,24,"(run switcher())", 1, 2, 0); /* m: 4 -> 7,0 */
- reached3[4] = 1;
- trans[3][4] = settr(112,2,7,1,0,"goto :b5", 1, 2, 0);
- trans[3][7] = settr(115,0,9,1,0,"break", 1, 2, 0);
- trans[3][9] = settr(117,0,0,25,25,"-end-", 0, 3500, 0);
-
- /* proctype 2: reader */
-
- trans[2] = (Trans **) emalloc(30*sizeof(Trans *));
-
- trans[2][27] = settr(106,0,26,1,0,".(goto)", 0, 2, 0);
- T = trans[2][26] = settr(105,0,0,0,0,"DO", 0, 2, 0);
- T = T->nxt = settr(105,0,1,0,0,"DO", 0, 2, 0);
- T->nxt = settr(105,0,24,0,0,"DO", 0, 2, 0);
- trans[2][1] = settr(80,0,12,26,0,"((((((write_off/(4/2))-(read_off/(4/2)))>0)&&(((write_off/(4/2))-(read_off/(4/2)))<(255/2)))&&(((commit_count[((read_off%4)/(4/2))]-(4/2))-(((read_off/4)*4)/2))==0)))", 1, 2, 0);
- T = trans[ 2][12] = settr(91,2,0,0,0,"ATOMIC", 1, 2, 0);
- T->nxt = settr(91,2,2,0,0,"ATOMIC", 1, 2, 0);
- trans[2][2] = settr(81,2,9,27,27,"i = 0", 1, 2, 0);
- trans[2][10] = settr(89,2,9,1,0,".(goto)", 1, 2, 0);
- T = trans[2][9] = settr(88,2,0,0,0,"DO", 1, 2, 0);
- T = T->nxt = settr(88,2,3,0,0,"DO", 1, 2, 0);
- T->nxt = settr(88,2,7,0,0,"DO", 1, 2, 0);
- trans[2][3] = settr(82,2,9,28,28,"((i<(4/2)))", 1, 2, 0); /* m: 4 -> 9,0 */
- reached2[4] = 1;
- trans[2][4] = settr(0,0,0,0,0,"assert((buffer_use[((read_off+i)%4)]==0))",0,0,0);
- trans[2][5] = settr(0,0,0,0,0,"buffer_use[((read_off+i)%4)] = 1",0,0,0);
- trans[2][6] = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
- trans[2][7] = settr(86,2,11,29,29,"((i>=(4/2)))", 1, 2, 0); /* m: 8 -> 11,0 */
- reached2[8] = 1;
- trans[2][8] = settr(87,2,11,1,0,"goto :b3", 1, 2, 0);
- trans[2][11] = settr(90,0,23,1,0,"break", 1, 2, 0);
- T = trans[ 2][23] = settr(102,2,0,0,0,"ATOMIC", 1, 2, 0);
- T->nxt = settr(102,2,13,0,0,"ATOMIC", 1, 2, 0);
- trans[2][13] = /* c */ settr(92,2,19,27,27,"i = 0", 1, 2, 0);
- trans[2][20] = settr(99,2,19,1,0,".(goto)", 1, 2, 0);
- T = trans[2][19] = settr(98,2,0,0,0,"DO", 1, 2, 0);
- T = T->nxt = settr(98,2,14,0,0,"DO", 1, 2, 0);
- T->nxt = settr(98,2,17,0,0,"DO", 1, 2, 0);
- trans[2][14] = settr(93,2,19,30,30,"((i<(4/2)))", 1, 2, 0); /* m: 15 -> 19,0 */
- reached2[15] = 1;
- trans[2][15] = settr(0,0,0,0,0,"buffer_use[((read_off+i)%4)] = 0",0,0,0);
- trans[2][16] = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
- trans[2][17] = settr(96,2,21,31,31,"((i>=(4/2)))", 1, 2, 0);
- trans[2][18] = settr(97,2,21,1,0,"goto :b4", 1, 2, 0);
- trans[2][21] = settr(100,2,22,1,0,"break", 1, 2, 0);
- trans[2][22] = settr(101,0,26,32,32,"read_off = (read_off+(4/2))", 1, 2, 0);
- trans[2][24] = settr(103,0,29,33,0,"((read_off>=(4-events_lost)))", 1, 2, 0);
- trans[2][25] = settr(104,0,29,1,0,"goto :b2", 0, 2, 0);
- trans[2][28] = settr(107,0,29,1,0,"break", 0, 2, 0);
- trans[2][29] = settr(108,0,0,34,34,"-end-", 0, 3500, 0);
-
- /* proctype 1: tracer */
-
- trans[1] = (Trans **) emalloc(51*sizeof(Trans *));
-
- T = trans[ 1][3] = settr(32,2,0,0,0,"ATOMIC", 1, 2, 0);
- T->nxt = settr(32,2,1,0,0,"ATOMIC", 1, 2, 0);
- trans[1][1] = settr(30,4,10,35,35,"prev_off = write_off", 1, 2, 0); /* m: 2 -> 0,10 */
- reached1[2] = 1;
- trans[1][2] = settr(0,0,0,0,0,"new_off = (prev_off+size)",0,0,0);
- T = trans[ 1][10] = settr(39,2,0,0,0,"ATOMIC", 1, 2, 0);
- T->nxt = settr(39,2,8,0,0,"ATOMIC", 1, 2, 0);
- T = trans[1][8] = settr(37,2,0,0,0,"IF", 1, 2, 0);
- T = T->nxt = settr(37,2,4,0,0,"IF", 1, 2, 0);
- T->nxt = settr(37,2,6,0,0,"IF", 1, 2, 0);
- trans[1][4] = settr(33,2,47,36,36,"((((new_off-read_off)>4)&&((new_off-read_off)<(255/2))))", 1, 2, 0);
- trans[1][5] = settr(34,2,47,1,0,"goto lost", 1, 2, 0);
- trans[1][9] = settr(38,0,27,1,0,".(goto)", 1, 2, 0);
- trans[1][6] = settr(35,2,7,2,0,"else", 1, 2, 0);
- trans[1][7] = settr(36,4,27,37,37,"(1)", 1, 2, 0); /* m: 9 -> 27,0 */
- reached1[9] = 1;
- T = trans[ 1][27] = settr(56,2,0,0,0,"ATOMIC", 1, 2, 0);
- T->nxt = settr(56,2,15,0,0,"ATOMIC", 1, 2, 0);
- T = trans[1][15] = settr(44,2,0,0,0,"IF", 1, 2, 0);
- T = T->nxt = settr(44,2,11,0,0,"IF", 1, 2, 0);
- T->nxt = settr(44,2,13,0,0,"IF", 1, 2, 0);
- trans[1][11] = settr(40,4,3,38,38,"((prev_off!=write_off))", 1, 2, 0); /* m: 12 -> 3,0 */
- reached1[12] = 1;
- trans[1][12] = settr(41,0,3,1,0,"goto cmpxchg_loop", 1, 2, 0);
- trans[1][16] = settr(45,2,17,1,0,".(goto)", 1, 2, 0); /* m: 17 -> 0,24 */
- reached1[17] = 1;
- trans[1][13] = settr(42,2,14,2,0,"else", 1, 2, 0);
- trans[1][14] = settr(43,2,24,39,39,"write_off = new_off", 1, 2, 0); /* m: 17 -> 0,24 */
- reached1[17] = 1;
- trans[1][17] = settr(46,2,24,40,40,"i = 0", 1, 2, 0);
- trans[1][25] = settr(54,2,24,1,0,".(goto)", 1, 2, 0);
- T = trans[1][24] = settr(53,2,0,0,0,"DO", 1, 2, 0);
- T = T->nxt = settr(53,2,18,0,0,"DO", 1, 2, 0);
- T->nxt = settr(53,2,22,0,0,"DO", 1, 2, 0);
- trans[1][18] = settr(47,2,24,41,41,"((i<size))", 1, 2, 0); /* m: 19 -> 24,0 */
- reached1[19] = 1;
- trans[1][19] = settr(0,0,0,0,0,"assert((buffer_use[((prev_off+i)%4)]==0))",0,0,0);
- trans[1][20] = settr(0,0,0,0,0,"buffer_use[((prev_off+i)%4)] = 1",0,0,0);
- trans[1][21] = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
- trans[1][22] = settr(51,2,26,42,42,"((i>=size))", 1, 2, 0); /* m: 23 -> 26,0 */
- reached1[23] = 1;
- trans[1][23] = settr(52,2,26,1,0,"goto :b0", 1, 2, 0);
- trans[1][26] = settr(55,0,45,1,0,"break", 1, 2, 0);
- T = trans[ 1][45] = settr(74,2,0,0,0,"ATOMIC", 1, 2, 0);
- T->nxt = settr(74,2,28,0,0,"ATOMIC", 1, 2, 0);
- trans[1][28] = settr(57,2,34,43,43,"i = 0", 1, 2, 0);
- trans[1][35] = settr(64,2,34,1,0,".(goto)", 1, 2, 0);
- T = trans[1][34] = settr(63,2,0,0,0,"DO", 1, 2, 0);
- T = T->nxt = settr(63,2,29,0,0,"DO", 1, 2, 0);
- T->nxt = settr(63,2,32,0,0,"DO", 1, 2, 0);
- trans[1][29] = settr(58,2,34,44,44,"((i<size))", 1, 2, 0); /* m: 30 -> 34,0 */
- reached1[30] = 1;
- trans[1][30] = settr(0,0,0,0,0,"buffer_use[((prev_off+i)%4)] = 0",0,0,0);
- trans[1][31] = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
- trans[1][32] = settr(61,2,43,45,45,"((i>=size))", 1, 2, 0); /* m: 37 -> 43,0 */
- reached1[37] = 1;
- trans[1][33] = settr(62,2,37,1,0,"goto :b1", 1, 2, 0); /* m: 37 -> 0,43 */
- reached1[37] = 1;
- trans[1][36] = settr(65,2,37,1,0,"break", 1, 2, 0);
- trans[1][37] = settr(66,2,43,46,46,"tmp_commit = (commit_count[((prev_off%4)/(4/2))]+size)", 1, 2, 0); /* m: 38 -> 0,43 */
- reached1[38] = 1;
- trans[1][38] = settr(0,0,0,0,0,"commit_count[((prev_off%4)/(4/2))] = tmp_commit",0,0,0);
- T = trans[1][43] = settr(72,2,0,0,0,"IF", 1, 2, 0);
- T = T->nxt = settr(72,2,39,0,0,"IF", 1, 2, 0);
- T->nxt = settr(72,2,41,0,0,"IF", 1, 2, 0);
- trans[1][39] = settr(68,4,49,47,47,"((((((prev_off/4)*4)/2)+(4/2))-tmp_commit))", 1, 2, 0); /* m: 40 -> 49,0 */
- reached1[40] = 1;
- trans[1][40] = settr(0,0,0,0,0,"deliver = 1",0,0,0);
- trans[1][44] = settr(73,0,49,48,48,".(goto)", 1, 2, 0);
- trans[1][41] = settr(70,2,42,2,0,"else", 1, 2, 0);
- trans[1][42] = settr(71,4,49,49,49,"(1)", 1, 2, 0); /* m: 44 -> 49,0 */
- reached1[44] = 1;
- T = trans[ 1][49] = settr(78,2,0,0,0,"ATOMIC", 1, 2, 0);
- T->nxt = settr(78,2,46,0,0,"ATOMIC", 1, 2, 0);
- trans[1][46] = settr(75,2,48,1,0,"goto end", 1, 2, 0);
- trans[1][47] = settr(76,2,48,50,50,"events_lost = (events_lost+1)", 1, 2, 0);
- trans[1][48] = settr(77,0,50,51,51,"refcount = (refcount-1)", 1, 2, 0);
- trans[1][50] = settr(79,0,0,52,52,"-end-", 0, 3500, 0);
-
- /* proctype 0: switcher */
-
- trans[0] = (Trans **) emalloc(31*sizeof(Trans *));
-
- T = trans[ 0][11] = settr(10,2,0,0,0,"ATOMIC", 1, 2, 0);
- T->nxt = settr(10,2,1,0,0,"ATOMIC", 1, 2, 0);
- trans[0][1] = settr(0,2,9,53,53,"prev_off = write_off", 1, 2, 0); /* m: 2 -> 0,9 */
- reached0[2] = 1;
- trans[0][2] = settr(0,0,0,0,0,"size = ((4/2)-(prev_off%(4/2)))",0,0,0);
- trans[0][3] = settr(0,0,0,0,0,"new_off = (prev_off+size)",0,0,0);
- T = trans[0][9] = settr(8,2,0,0,0,"IF", 1, 2, 0);
- T = T->nxt = settr(8,2,4,0,0,"IF", 1, 2, 0);
- T->nxt = settr(8,2,7,0,0,"IF", 1, 2, 0);
- trans[0][4] = settr(3,4,29,54,54,"(((((new_off-read_off)>4)&&((new_off-read_off)<(255/2)))||(size==(4/2))))", 1, 2, 0); /* m: 5 -> 29,0 */
- reached0[5] = 1;
- trans[0][5] = settr(0,0,0,0,0,"refcount = (refcount-1)",0,0,0);
- trans[0][6] = settr(5,0,29,1,0,"goto not_needed", 1, 2, 0);
- trans[0][10] = settr(9,0,18,1,0,".(goto)", 1, 2, 0);
- trans[0][7] = settr(6,2,8,2,0,"else", 1, 2, 0);
- trans[0][8] = settr(7,4,18,55,55,"(1)", 1, 2, 0); /* m: 10 -> 18,0 */
- reached0[10] = 1;
- T = trans[ 0][18] = settr(17,2,0,0,0,"ATOMIC", 1, 2, 0);
- T->nxt = settr(17,2,16,0,0,"ATOMIC", 1, 2, 0);
- T = trans[0][16] = settr(15,2,0,0,0,"IF", 1, 2, 0);
- T = T->nxt = settr(15,2,12,0,0,"IF", 1, 2, 0);
- T->nxt = settr(15,2,14,0,0,"IF", 1, 2, 0);
- trans[0][12] = settr(11,4,11,56,56,"((prev_off!=write_off))", 1, 2, 0); /* m: 13 -> 11,0 */
- reached0[13] = 1;
- trans[0][13] = settr(12,0,11,1,0,"goto cmpxchg_loop", 1, 2, 0);
- trans[0][17] = settr(16,0,28,57,57,".(goto)", 1, 2, 0);
- trans[0][14] = settr(13,2,15,2,0,"else", 1, 2, 0);
- trans[0][15] = settr(14,4,28,58,58,"write_off = new_off", 1, 2, 0); /* m: 17 -> 0,28 */
- reached0[17] = 1;
- T = trans[ 0][28] = settr(27,2,0,0,0,"ATOMIC", 1, 2, 0);
- T->nxt = settr(27,2,19,0,0,"ATOMIC", 1, 2, 0);
- trans[0][19] = settr(18,2,25,59,59,"tmp_commit = (commit_count[((prev_off%4)/(4/2))]+size)", 1, 2, 0); /* m: 20 -> 0,25 */
- reached0[20] = 1;
- trans[0][20] = settr(0,0,0,0,0,"commit_count[((prev_off%4)/(4/2))] = tmp_commit",0,0,0);
- T = trans[0][25] = settr(24,2,0,0,0,"IF", 1, 2, 0);
- T = T->nxt = settr(24,2,21,0,0,"IF", 1, 2, 0);
- T->nxt = settr(24,2,23,0,0,"IF", 1, 2, 0);
- trans[0][21] = settr(20,4,29,60,60,"((((((prev_off/4)*4)/2)+(4/2))-tmp_commit))", 1, 2, 0); /* m: 22 -> 29,0 */
- reached0[22] = 1;
- trans[0][22] = settr(0,0,0,0,0,"deliver = 1",0,0,0);
- trans[0][26] = settr(25,4,29,61,61,".(goto)", 1, 2, 0); /* m: 27 -> 0,29 */
- reached0[27] = 1;
- trans[0][23] = settr(22,2,24,2,0,"else", 1, 2, 0);
- trans[0][24] = settr(23,4,29,62,62,"(1)", 1, 2, 0); /* m: 26 -> 29,0 */
- reached0[26] = 1;
- trans[0][27] = settr(0,0,0,0,0,"refcount = (refcount-1)",0,0,0);
- trans[0][29] = settr(28,0,30,1,0,"(1)", 0, 2, 0);
- trans[0][30] = settr(29,0,0,63,63,"-end-", 0, 3500, 0);
- /* np_ demon: */
- trans[_NP_] = (Trans **) emalloc(2*sizeof(Trans *));
- T = trans[_NP_][0] = settr(9997,0,1,_T5,0,"(np_)", 1,2,0);
- T->nxt = settr(9998,0,0,_T2,0,"(1)", 0,2,0);
- T = trans[_NP_][1] = settr(9999,0,1,_T5,0,"(np_)", 1,2,0);
-}
-
-Trans *
-settr( int t_id, int a, int b, int c, int d,
- char *t, int g, int tpe0, int tpe1)
-{ Trans *tmp = (Trans *) emalloc(sizeof(Trans));
-
- tmp->atom = a&(6|32); /* only (2|8|32) have meaning */
- if (!g) tmp->atom |= 8; /* no global references */
- tmp->st = b;
- tmp->tpe[0] = tpe0;
- tmp->tpe[1] = tpe1;
- tmp->tp = t;
- tmp->t_id = t_id;
- tmp->forw = c;
- tmp->back = d;
- return tmp;
-}
-
-Trans *
-cpytr(Trans *a)
-{ Trans *tmp = (Trans *) emalloc(sizeof(Trans));
-
- int i;
- tmp->atom = a->atom;
- tmp->st = a->st;
-#ifdef HAS_UNLESS
- tmp->e_trans = a->e_trans;
- for (i = 0; i < HAS_UNLESS; i++)
- tmp->escp[i] = a->escp[i];
-#endif
- tmp->tpe[0] = a->tpe[0];
- tmp->tpe[1] = a->tpe[1];
- for (i = 0; i < 6; i++)
- { tmp->qu[i] = a->qu[i];
- tmp->ty[i] = a->ty[i];
- }
- tmp->tp = (char *) emalloc(strlen(a->tp)+1);
- strcpy(tmp->tp, a->tp);
- tmp->t_id = a->t_id;
- tmp->forw = a->forw;
- tmp->back = a->back;
- return tmp;
-}
-
-#ifndef NOREDUCE
-int
-srinc_set(int n)
-{ if (n <= 2) return LOCAL;
- if (n <= 2+ DELTA) return Q_FULL_F; /* 's' or nfull */
- if (n <= 2+2*DELTA) return Q_EMPT_F; /* 'r' or nempty */
- if (n <= 2+3*DELTA) return Q_EMPT_T; /* empty */
- if (n <= 2+4*DELTA) return Q_FULL_T; /* full */
- if (n == 5*DELTA) return GLOBAL;
- if (n == 6*DELTA) return TIMEOUT_F;
- if (n == 7*DELTA) return ALPHA_F;
- Uerror("cannot happen srinc_class");
- return BAD;
-}
-int
-srunc(int n, int m)
-{ switch(m) {
- case Q_FULL_F: return n-2;
- case Q_EMPT_F: return n-2-DELTA;
- case Q_EMPT_T: return n-2-2*DELTA;
- case Q_FULL_T: return n-2-3*DELTA;
- case ALPHA_F:
- case TIMEOUT_F: return 257; /* non-zero, and > MAXQ */
- }
- Uerror("cannot happen srunc");
- return 0;
-}
-#endif
-int cnt;
-#ifdef HAS_UNLESS
-int
-isthere(Trans *a, int b)
-{ Trans *t;
- for (t = a; t; t = t->nxt)
- if (t->t_id == b)
- return 1;
- return 0;
-}
-#endif
-#ifndef NOREDUCE
-int
-mark_safety(Trans *t) /* for conditional safety */
-{ int g = 0, i, j, k;
-
- if (!t) return 0;
- if (t->qu[0])
- return (t->qu[1])?2:1; /* marked */
-
- for (i = 0; i < 2; i++)
- { j = srinc_set(t->tpe[i]);
- if (j >= GLOBAL && j != ALPHA_F)
- return -1;
- if (j != LOCAL)
- { k = srunc(t->tpe[i], j);
- if (g == 0
- || t->qu[0] != k
- || t->ty[0] != j)
- { t->qu[g] = k;
- t->ty[g] = j;
- g++;
- } } }
- return g;
-}
-#endif
-void
-retrans(int n, int m, int is, short srcln[], uchar reach[], uchar lstate[])
- /* process n, with m states, is=initial state */
-{ Trans *T0, *T1, *T2, *T3;
- int i, k;
-#ifndef NOREDUCE
- int g, h, j, aa;
-#endif
-#ifdef HAS_UNLESS
- int p;
-#endif
- if (state_tables >= 4)
- { printf("STEP 1 proctype %s\n",
- procname[n]);
- for (i = 1; i < m; i++)
- for (T0 = trans[n][i]; T0; T0 = T0->nxt)
- crack(n, i, T0, srcln);
- return;
- }
- do {
- for (i = 1, cnt = 0; i < m; i++)
- { T2 = trans[n][i];
- T1 = T2?T2->nxt:(Trans *)0;
-/* prescan: */ for (T0 = T1; T0; T0 = T0->nxt)
-/* choice in choice */ { if (T0->st && trans[n][T0->st]
- && trans[n][T0->st]->nxt)
- break;
- }
-#if 0
- if (T0)
- printf("\tstate %d / %d: choice in choice\n",
- i, T0->st);
-#endif
- if (T0)
- for (T0 = T1; T0; T0 = T0->nxt)
- { T3 = trans[n][T0->st];
- if (!T3->nxt)
- { T2->nxt = cpytr(T0);
- T2 = T2->nxt;
- imed(T2, T0->st, n, i);
- continue;
- }
- do { T3 = T3->nxt;
- T2->nxt = cpytr(T3);
- T2 = T2->nxt;
- imed(T2, T0->st, n, i);
- } while (T3->nxt);
- cnt++;
- }
- }
- } while (cnt);
- if (state_tables >= 3)
- { printf("STEP 2 proctype %s\n",
- procname[n]);
- for (i = 1; i < m; i++)
- for (T0 = trans[n][i]; T0; T0 = T0->nxt)
- crack(n, i, T0, srcln);
- return;
- }
- for (i = 1; i < m; i++)
- { if (trans[n][i] && trans[n][i]->nxt) /* optimize */
- { T1 = trans[n][i]->nxt;
-#if 0
- printf("\t\tpull %d (%d) to %d\n",
- T1->st, T1->forw, i);
-#endif
- if (!trans[n][T1->st]) continue;
- T0 = cpytr(trans[n][T1->st]);
- trans[n][i] = T0;
- reach[T1->st] = 1;
- imed(T0, T1->st, n, i);
- for (T1 = T1->nxt; T1; T1 = T1->nxt)
- {
-#if 0
- printf("\t\tpull %d (%d) to %d\n",
- T1->st, T1->forw, i);
-#endif
- if (!trans[n][T1->st]) continue;
- T0->nxt = cpytr(trans[n][T1->st]);
- T0 = T0->nxt;
- reach[T1->st] = 1;
- imed(T0, T1->st, n, i);
- } } }
- if (state_tables >= 2)
- { printf("STEP 3 proctype %s\n",
- procname[n]);
- for (i = 1; i < m; i++)
- for (T0 = trans[n][i]; T0; T0 = T0->nxt)
- crack(n, i, T0, srcln);
- return;
- }
-#ifdef HAS_UNLESS
- for (i = 1; i < m; i++)
- { if (!trans[n][i]) continue;
- /* check for each state i if an
- * escape to some state p is defined
- * if so, copy and mark p's transitions
- * and prepend them to the transition-
- * list of state i
- */
- 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)
- { if (isthere(trans[n][i], T1->t_id))
- continue;
- T2 = cpytr(T1);
- T2->e_trans = p;
- T2->nxt = trans[n][i];
- trans[n][i] = T2;
- } }
- } else /* outermost unless checked first */
- { Trans *T4;
- 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])
- for (T1 = trans[n][p]; T1; T1 = T1->nxt)
- { if (isthere(trans[n][i], T1->t_id))
- continue;
- T2 = cpytr(T1);
- T2->nxt = (Trans *) 0;
- T2->e_trans = p;
- if (T3) T3->nxt = T2;
- else T4 = T2;
- T3 = T2;
- } }
- if (T4)
- { T3->nxt = trans[n][i];
- trans[n][i] = T4;
- }
- }
- }
-#endif
-#ifndef NOREDUCE
- for (i = 1; i < m; i++)
- { if (a_cycles)
- { /* moves through these states are visible */
- #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
- if (accpstate[n][i] || visstate[n][i])
- goto degrade;
- for (T1 = trans[n][i]; T1; T1 = T1->nxt)
- if (accpstate[n][T1->st])
- goto degrade;
- }
- T1 = trans[n][i];
- if (!T1) continue;
- g = mark_safety(T1); /* V3.3.1 */
- if (g < 0) goto degrade; /* global */
- /* check if mixing of guards preserves reduction */
- if (T1->nxt)
- { k = 0;
- for (T0 = T1; T0; T0 = T0->nxt)
- { if (!(T0->atom&8))
- goto degrade;
- for (aa = 0; aa < 2; aa++)
- { j = srinc_set(T0->tpe[aa]);
- if (j >= GLOBAL && j != ALPHA_F)
- goto degrade;
- if (T0->tpe[aa]
- && T0->tpe[aa]
- != T1->tpe[0])
- k = 1;
- } }
- /* g = 0; V3.3.1 */
- if (k) /* non-uniform selection */
- for (T0 = T1; T0; T0 = T0->nxt)
- for (aa = 0; aa < 2; aa++)
- { j = srinc_set(T0->tpe[aa]);
- if (j != LOCAL)
- { k = srunc(T0->tpe[aa], j);
- for (h = 0; h < 6; h++)
- if (T1->qu[h] == k
- && T1->ty[h] == j)
- break;
- if (h >= 6)
- { T1->qu[g%6] = k;
- T1->ty[g%6] = j;
- g++;
- } } }
- if (g > 6)
- { T1->qu[0] = 0; /* turn it off */
- printf("pan: warning, line %d, ",
- srcln[i]);
- printf("too many stmnt types (%d)",
- g);
- printf(" in selection\n");
- goto degrade;
- }
- }
- /* mark all options global if >=1 is global */
- for (T1 = trans[n][i]; T1; T1 = T1->nxt)
- if (!(T1->atom&8)) break;
- if (T1)
-degrade: for (T1 = trans[n][i]; T1; T1 = T1->nxt)
- T1->atom &= ~8; /* mark as unsafe */
- /* can only mix 'r's or 's's if on same chan */
- /* and not mixed with other local operations */
- T1 = trans[n][i];
- if (!T1 || T1->qu[0]) continue;
- j = T1->tpe[0];
- if (T1->nxt && T1->atom&8)
- { if (j == 5*DELTA)
- { printf("warning: line %d ", srcln[i]);
- printf("mixed condition ");
- printf("(defeats reduction)\n");
- goto degrade;
- }
- for (T0 = T1; T0; T0 = T0->nxt)
- for (aa = 0; aa < 2; aa++)
- if (T0->tpe[aa] && T0->tpe[aa] != j)
- { printf("warning: line %d ", srcln[i]);
- printf("[%d-%d] mixed %stion ",
- T0->tpe[aa], j,
- (j==5*DELTA)?"condi":"selec");
- printf("(defeats reduction)\n");
- printf(" '%s' <-> '%s'\n",
- T1->tp, T0->tp);
- goto degrade;
- } }
- }
-#endif
- for (i = 1; i < m; i++)
- { T2 = trans[n][i];
- if (!T2
- || T2->nxt
- || strncmp(T2->tp, ".(goto)", 7)
- || !stopstate[n][i])
- 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]);
- for (i = 1; i < m; i++)
- reach[i] = 1;
- tagtable(n, m, is, srcln, reach);
- } else
- for (i = 1; i < m; i++)
- { int nrelse;
- if (strcmp(procname[n], ":never:") != 0)
- { for (T0 = trans[n][i]; T0; T0 = T0->nxt)
- { if (T0->st == i
- && strcmp(T0->tp, "(1)") == 0)
- { printf("error: proctype '%s' ",
- procname[n]);
- printf("line %d, state %d: has un",
- srcln[i], i);
- printf("conditional self-loop\n");
- pan_exit(1);
- } } }
- nrelse = 0;
- for (T0 = trans[n][i]; T0; T0 = T0->nxt)
- { if (strcmp(T0->tp, "else") == 0)
- nrelse++;
- }
- if (nrelse > 1)
- { printf("error: proctype '%s' state",
- procname[n]);
- printf(" %d, inherits %d", i, nrelse);
- printf(" 'else' stmnts\n");
- pan_exit(1);
- } }
- if (!state_tables && strcmp(procname[n], ":never:") == 0)
- { int h = 0;
- 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;
- }
-#ifndef LOOPSTATE
- if (state_tables)
-#endif
- do_dfs(n, m, is, srcln, reach, lstate);
-#ifdef T_REVERSE
- /* process n, with m states, is=initial state -- reverse list */
- if (!state_tables && strcmp(procname[n], ":never:") != 0)
- { for (i = 1; i < m; i++)
- { Trans *T4 = (Trans *) 0;
- T1 = (Trans *) 0;
- T2 = (Trans *) 0;
- T3 = (Trans *) 0;
- for (T0 = trans[n][i]; T0; T0 = T4)
- { T4 = T0->nxt;
- if (strcmp(T0->tp, "else") == 0)
- { T3 = T0;
- T0->nxt = (Trans *) 0;
- } else
- { T0->nxt = T1;
- if (!T1) { T2 = T0; }
- T1 = T0;
- } }
- if (T2 && T3) { T2->nxt = T3; }
- trans[n][i] = T1; /* reversed -- else at end */
- } }
-#endif
-}
-void
-imed(Trans *T, int v, int n, int j) /* set intermediate state */
-{ progstate[n][T->st] |= progstate[n][v];
- accpstate[n][T->st] |= accpstate[n][v];
- stopstate[n][T->st] |= stopstate[n][v];
- mapstate[n][j] = T->st;
-}
-void
-tagtable(int n, int m, int is, short srcln[], uchar reach[])
-{ Trans *z;
-
- if (is >= m || !trans[n][is]
- || is <= 0 || reach[is] == 0)
- return;
- reach[is] = 0;
- if (state_tables)
- for (z = trans[n][is]; z; z = z->nxt)
- crack(n, is, z, srcln);
- for (z = trans[n][is]; z; z = z->nxt)
- {
-#ifdef HAS_UNLESS
- int i, j;
-#endif
- tagtable(n, m, z->st, srcln, reach);
-#ifdef HAS_UNLESS
- for (i = 0; i < HAS_UNLESS; i++)
- { j = trans[n][is]->escp[i];
- if (!j) break;
- tagtable(n, m, j, srcln, reach);
- }
-#endif
- }
-}
-void
-dfs_table(int n, int m, int is, short srcln[], uchar reach[], uchar lstate[])
-{ Trans *z;
-
- 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 */
- { lstate[is] = 1;
- reach[is] |= 8; /* recorded */
- if (state_tables)
- { 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)
- {
-#ifdef HAS_UNLESS
- int i, j;
-#endif
- dfs_table(n, m, z->st, srcln, reach, lstate);
-#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, lstate);
- }
-#endif
- }
- reach[is] &= ~16; /* no longer on stack */
-}
-void
-do_dfs(int n, int m, int is, short srcln[], uchar reach[], uchar lstate[])
-{ int i;
- dfs_table(n, m, is, srcln, reach, lstate);
- for (i = 0; i < m; i++)
- reach[i] &= ~(4|8|16);
-}
-void
-crack(int n, int j, Trans *z, short srcln[])
-{ int i;
-
- if (!z) return;
- printf(" state %3d -(tr %3d)-> state %3d ",
- j, z->forw, z->st);
- printf("[id %3d tp %3d", z->t_id, z->tpe[0]);
- if (z->tpe[1]) printf(",%d", z->tpe[1]);
-#ifdef HAS_UNLESS
- if (z->e_trans)
- printf(" org %3d", z->e_trans);
- else if (state_tables >= 2)
- for (i = 0; i < HAS_UNLESS; i++)
- { if (!z->escp[i]) break;
- printf(" esc %d", z->escp[i]);
- }
-#endif
- printf("]");
- printf(" [%s%s%s%s%s] line %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]);
- for (i = 0; z->tp[i]; i++)
- if (z->tp[i] == '\n')
- printf("\\n");
- else
- putchar(z->tp[i]);
- if (z->qu[0])
- { printf("\t[");
- for (i = 0; i < 6; i++)
- if (z->qu[i])
- printf("(%d,%d)",
- z->qu[i], z->ty[i]);
- printf("]");
- }
- printf("\n");
- fflush(stdout);
-}
-
-#ifdef VAR_RANGES
-#define BYTESIZE 32 /* 2^8 : 2^3 = 256:8 = 32 */
-
-typedef struct Vr_Ptr {
- char *nm;
- uchar vals[BYTESIZE];
- struct Vr_Ptr *nxt;
-} Vr_Ptr;
-Vr_Ptr *ranges = (Vr_Ptr *) 0;
-
-void
-logval(char *s, int v)
-{ Vr_Ptr *tmp;
-
- if (v<0 || v > 255) return;
- for (tmp = ranges; tmp; tmp = tmp->nxt)
- if (!strcmp(tmp->nm, s))
- goto found;
- tmp = (Vr_Ptr *) emalloc(sizeof(Vr_Ptr));
- tmp->nxt = ranges;
- ranges = tmp;
- tmp->nm = s;
-found:
- tmp->vals[(v)/8] |= 1<<((v)%8);
-}
-
-void
-dumpval(uchar X[], int range)
-{ int w, x, i, j = -1;
-
- for (w = i = 0; w < range; w++)
- for (x = 0; x < 8; x++, i++)
- {
-from: if ((X[w] & (1<<x)))
- { printf("%d", i);
- j = i;
- goto upto;
- } }
- return;
- for (w = 0; w < range; w++)
- for (x = 0; x < 8; x++, i++)
- {
-upto: if (!(X[w] & (1<<x)))
- { if (i-1 == j)
- printf(", ");
- else
- printf("-%d, ", i-1);
- goto from;
- } }
- if (j >= 0 && j != 255)
- printf("-255");
-}
-
-void
-dumpranges(void)
-{ Vr_Ptr *tmp;
- printf("\nValues assigned within ");
- printf("interval [0..255]:\n");
- for (tmp = ranges; tmp; tmp = tmp->nxt)
- { printf("\t%s\t: ", tmp->nm);
- dumpval(tmp->vals, BYTESIZE);
- printf("\n");
- }
-}
-#endif