100d97012SDavid du Colombier /***** spin: pangen6.h *****/ 200d97012SDavid du Colombier 3*de2caf28SDavid du Colombier /* 4*de2caf28SDavid du Colombier * This file is part of the public release of Spin. It is subject to the 5*de2caf28SDavid du Colombier * terms in the LICENSE file that is included in this source directory. 6*de2caf28SDavid du Colombier * Tool documentation is available at http://spinroot.com 7*de2caf28SDavid du Colombier */ 800d97012SDavid du Colombier 9*de2caf28SDavid du Colombier static const char *Code2e[] = { 10*de2caf28SDavid du Colombier "#if (NCORE>1 || defined(BFS_PAR)) && !defined(WIN32) && !defined(WIN64)", 11*de2caf28SDavid du Colombier " /* Test and Set assembly code */", 12*de2caf28SDavid du Colombier " #if defined(i386) || defined(__i386__) || defined(__x86_64__)", 13*de2caf28SDavid du Colombier " int", 14*de2caf28SDavid du Colombier " tas(volatile int *s) /* tested */", 15*de2caf28SDavid du Colombier " { int r;", 16*de2caf28SDavid du Colombier " __asm__ __volatile__(", 17*de2caf28SDavid du Colombier " \"xchgl %%0, %%1 \\n\\t\"", 18*de2caf28SDavid du Colombier " : \"=r\"(r), \"=m\"(*s)", 19*de2caf28SDavid du Colombier " : \"0\"(1), \"m\"(*s)", 20*de2caf28SDavid du Colombier " : \"memory\");", 21*de2caf28SDavid du Colombier " ", 22*de2caf28SDavid du Colombier " return r;", 23*de2caf28SDavid du Colombier " }", 24*de2caf28SDavid du Colombier " #elif defined(__arm__)", 25*de2caf28SDavid du Colombier " int", 26*de2caf28SDavid du Colombier " tas(volatile int *s) /* not tested */", 27*de2caf28SDavid du Colombier " { int r = 1;", 28*de2caf28SDavid du Colombier " __asm__ __volatile__(", 29*de2caf28SDavid du Colombier " \"swpb %%0, %%0, [%%3] \\n\"", 30*de2caf28SDavid du Colombier " : \"=r\"(r), \"=m\"(*s)", 31*de2caf28SDavid du Colombier " : \"0\"(r), \"r\"(s));", 32*de2caf28SDavid du Colombier "", 33*de2caf28SDavid du Colombier " return r;", 34*de2caf28SDavid du Colombier " }", 35*de2caf28SDavid du Colombier " #elif defined(sparc) || defined(__sparc__)", 36*de2caf28SDavid du Colombier " int", 37*de2caf28SDavid du Colombier " tas(volatile int *s) /* not tested */", 38*de2caf28SDavid du Colombier " { int r = 1;", 39*de2caf28SDavid du Colombier " __asm__ __volatile__(", 40*de2caf28SDavid du Colombier " \" ldstub [%%2], %%0 \\n\"", 41*de2caf28SDavid du Colombier " : \"=r\"(r), \"=m\"(*s)", 42*de2caf28SDavid du Colombier " : \"r\"(s));", 43*de2caf28SDavid du Colombier "", 44*de2caf28SDavid du Colombier " return r;", 45*de2caf28SDavid du Colombier " }", 46*de2caf28SDavid du Colombier " #elif defined(ia64) || defined(__ia64__)", 47*de2caf28SDavid du Colombier " /* Intel Itanium */", 48*de2caf28SDavid du Colombier " int", 49*de2caf28SDavid du Colombier " tas(volatile int *s) /* tested */", 50*de2caf28SDavid du Colombier " { long int r;", 51*de2caf28SDavid du Colombier " __asm__ __volatile__(", 52*de2caf28SDavid du Colombier " \" xchg4 %%0=%%1,%%2 \\n\"", 53*de2caf28SDavid du Colombier " : \"=r\"(r), \"+m\"(*s)", 54*de2caf28SDavid du Colombier " : \"r\"(1)", 55*de2caf28SDavid du Colombier " : \"memory\");", 56*de2caf28SDavid du Colombier " return (int) r;", 57*de2caf28SDavid du Colombier " }", 58*de2caf28SDavid du Colombier " #elif defined(__powerpc64__)", 59*de2caf28SDavid du Colombier " int", 60*de2caf28SDavid du Colombier " tas(volatile int *s) /* courtesy srirajpaul */", 61*de2caf28SDavid du Colombier " { int r;", 62*de2caf28SDavid du Colombier " #if 1", 63*de2caf28SDavid du Colombier " r = __sync_lock_test_and_set();", 64*de2caf28SDavid du Colombier " #else", 65*de2caf28SDavid du Colombier " /* xlc compiler only */", 66*de2caf28SDavid du Colombier " r = __fetch_and_or(s, 1);", 67*de2caf28SDavid du Colombier " __isync();", 68*de2caf28SDavid du Colombier " #endif", 69*de2caf28SDavid du Colombier " return r;", 70*de2caf28SDavid du Colombier " }", 71*de2caf28SDavid du Colombier " #else", 72*de2caf28SDavid du Colombier " #error missing definition of test and set operation for this platform", 73*de2caf28SDavid du Colombier " #endif", 74*de2caf28SDavid du Colombier "", 75*de2caf28SDavid du Colombier " #ifndef NO_CAS", /* linux, windows */ 76*de2caf28SDavid du Colombier " #define cas(a,b,c) __sync_bool_compare_and_swap(a,b,c)", 77*de2caf28SDavid du Colombier " #else", 78*de2caf28SDavid du Colombier " int", /* workaround if the above is not available */ 79*de2caf28SDavid du Colombier " cas(volatile uint32_t *a, uint32_t b, uint32_t c)", 80*de2caf28SDavid du Colombier " { static volatile int cas_lock;", 81*de2caf28SDavid du Colombier " while (tas(&cas_lock) != 0) { ; }", 82*de2caf28SDavid du Colombier " if (*a == b)", 83*de2caf28SDavid du Colombier " { *a = c;", 84*de2caf28SDavid du Colombier " cas_lock = 0;", 85*de2caf28SDavid du Colombier " return 1;", 86*de2caf28SDavid du Colombier " }", 87*de2caf28SDavid du Colombier " cas_lock = 0;", 88*de2caf28SDavid du Colombier " return 0;", 89*de2caf28SDavid du Colombier " }", 90*de2caf28SDavid du Colombier " #endif", 91*de2caf28SDavid du Colombier "#endif", 92*de2caf28SDavid du Colombier 0, 93*de2caf28SDavid du Colombier }; 94*de2caf28SDavid du Colombier 95*de2caf28SDavid du Colombier static const char *Code2c[] = { /* multi-core option - Spin 5.0 and later */ 9600d97012SDavid du Colombier "#if NCORE>1", 9700d97012SDavid du Colombier "#if defined(WIN32) || defined(WIN64)", 9800d97012SDavid du Colombier " #ifndef _CONSOLE", 9900d97012SDavid du Colombier " #define _CONSOLE", 10000d97012SDavid du Colombier " #endif", 10100d97012SDavid du Colombier " #ifdef WIN64", 10200d97012SDavid du Colombier " #undef long", 10300d97012SDavid du Colombier " #endif", 10400d97012SDavid du Colombier " #include <windows.h>", 105*de2caf28SDavid du Colombier "/*", 10600d97012SDavid du Colombier " #ifdef WIN64", 10700d97012SDavid du Colombier " #define long long long", 10800d97012SDavid du Colombier " #endif", 109*de2caf28SDavid du Colombier "*/", 11000d97012SDavid du Colombier "#else", 11100d97012SDavid du Colombier " #include <sys/ipc.h>", 11200d97012SDavid du Colombier " #include <sys/sem.h>", 11300d97012SDavid du Colombier " #include <sys/shm.h>", 11400d97012SDavid du Colombier "#endif", 11500d97012SDavid du Colombier "", 11600d97012SDavid du Colombier "/* code common to cygwin/linux and win32/win64: */", 11700d97012SDavid du Colombier "", 11800d97012SDavid du Colombier "#ifdef VERBOSE", 11900d97012SDavid du Colombier " #define VVERBOSE (1)", 12000d97012SDavid du Colombier "#else", 12100d97012SDavid du Colombier " #define VVERBOSE (0)", 12200d97012SDavid du Colombier "#endif", 12300d97012SDavid du Colombier "", 12400d97012SDavid du Colombier "/* the following values must be larger than 256 and must fit in an int */", 12500d97012SDavid du Colombier "#define QUIT 1024 /* terminate now command */", 12600d97012SDavid du Colombier "#define QUERY 512 /* termination status query message */", 12700d97012SDavid du Colombier "#define QUERY_F 513 /* query failed, cannot quit */", 12800d97012SDavid du Colombier "", 12900d97012SDavid du Colombier "#define GN_FRAMES (int) (GWQ_SIZE / (double) sizeof(SM_frame))", 13000d97012SDavid du Colombier "#define LN_FRAMES (int) (LWQ_SIZE / (double) sizeof(SM_frame))", 13100d97012SDavid du Colombier "", 13200d97012SDavid du Colombier "#ifndef VMAX", 13300d97012SDavid du Colombier " #define VMAX VECTORSZ", 13400d97012SDavid du Colombier "#endif", 13500d97012SDavid du Colombier "#ifndef PMAX", 13600d97012SDavid du Colombier " #define PMAX 64", 13700d97012SDavid du Colombier "#endif", 13800d97012SDavid du Colombier "#ifndef QMAX", 13900d97012SDavid du Colombier " #define QMAX 64", 14000d97012SDavid du Colombier "#endif", 14100d97012SDavid du Colombier "", 14200d97012SDavid du Colombier "#if VECTORSZ>32000", 14300d97012SDavid du Colombier " #define OFFT int", 14400d97012SDavid du Colombier "#else", 14500d97012SDavid du Colombier " #define OFFT short", 14600d97012SDavid du Colombier "#endif", 14700d97012SDavid du Colombier "", 14800d97012SDavid du Colombier "#ifdef SET_SEG_SIZE", 149*de2caf28SDavid du Colombier " /* no longer useful -- being recomputed for local heap size anyway */", 15000d97012SDavid du Colombier " double SEG_SIZE = (((double) SET_SEG_SIZE) * 1048576.);", 15100d97012SDavid du Colombier "#else", 15200d97012SDavid du Colombier " double SEG_SIZE = (1048576.*1024.); /* 1GB default shared memory pool segments */", 15300d97012SDavid du Colombier "#endif", 15400d97012SDavid du Colombier "", 15500d97012SDavid du Colombier "double LWQ_SIZE = 0.; /* initialized in main */", 15600d97012SDavid du Colombier "", 15700d97012SDavid du Colombier "#ifdef SET_WQ_SIZE", 15800d97012SDavid du Colombier " #ifdef NGQ", 15900d97012SDavid du Colombier " #warning SET_WQ_SIZE applies to global queue -- ignored", 16000d97012SDavid du Colombier " double GWQ_SIZE = 0.;", 16100d97012SDavid du Colombier " #else", 16200d97012SDavid du Colombier " double GWQ_SIZE = (((double) SET_WQ_SIZE) * 1048576.);", 16300d97012SDavid du Colombier " /* must match the value in pan_proxy.c, if used */", 16400d97012SDavid du Colombier " #endif", 16500d97012SDavid du Colombier "#else", 16600d97012SDavid du Colombier " #ifdef NGQ", 16700d97012SDavid du Colombier " double GWQ_SIZE = 0.;", 16800d97012SDavid du Colombier " #else", 16900d97012SDavid du Colombier " double GWQ_SIZE = (128.*1048576.); /* 128 MB default queue sizes */", 17000d97012SDavid du Colombier " #endif", 17100d97012SDavid du Colombier "#endif", 17200d97012SDavid du Colombier "", 17300d97012SDavid du Colombier "/* Crash Detection Parameters */", 17400d97012SDavid du Colombier "#ifndef ONESECOND", 17500d97012SDavid du Colombier " #define ONESECOND (1<<25)", /* name is somewhat of a misnomer */ 17600d97012SDavid du Colombier "#endif", 17700d97012SDavid du Colombier "#ifndef SHORT_T", 17800d97012SDavid du Colombier " #define SHORT_T (0.1)", 17900d97012SDavid du Colombier "#endif", 18000d97012SDavid du Colombier "#ifndef LONG_T", 18100d97012SDavid du Colombier " #define LONG_T (600)", 18200d97012SDavid du Colombier "#endif", 18300d97012SDavid du Colombier "", 18400d97012SDavid du Colombier "double OneSecond = (double) (ONESECOND); /* waiting for a free slot -- checks crash */", 18500d97012SDavid du Colombier "double TenSeconds = 10. * (ONESECOND); /* waiting for a lock -- check for a crash */", 18600d97012SDavid du Colombier "", 18700d97012SDavid du Colombier "/* Termination Detection Params -- waiting for new state input in Get_Full_Frame */", 18800d97012SDavid du Colombier "double Delay = ((double) SHORT_T) * (ONESECOND); /* termination detection trigger */", 18900d97012SDavid du Colombier "double OneHour = ((double) LONG_T) * (ONESECOND); /* timeout termination detection */", 19000d97012SDavid du Colombier "", 19100d97012SDavid du Colombier "typedef struct SM_frame SM_frame;", 19200d97012SDavid du Colombier "typedef struct SM_results SM_results;", 19300d97012SDavid du Colombier "typedef struct sh_Allocater sh_Allocater;", 19400d97012SDavid du Colombier "", 19500d97012SDavid du Colombier "struct SM_frame { /* about 6K per slot */", 19600d97012SDavid du Colombier " volatile int m_vsize; /* 0 means free slot */", 19700d97012SDavid du Colombier " volatile int m_boq; /* >500 is a control message */", 19800d97012SDavid du Colombier "#ifdef FULL_TRAIL", 19900d97012SDavid du Colombier " volatile struct Stack_Tree *m_stack; /* ptr to previous state */", 20000d97012SDavid du Colombier "#endif", 20100d97012SDavid du Colombier " volatile uchar m_tau;", 20200d97012SDavid du Colombier " volatile uchar m_o_pm;", 20300d97012SDavid du Colombier " volatile int nr_handoffs; /* to compute real_depth */", 20400d97012SDavid du Colombier " volatile char m_now [VMAX];", 205*de2caf28SDavid du Colombier "#if !defined(NOCOMP) && !defined(HC)", 206*de2caf28SDavid du Colombier " volatile char m_mask [(VMAX + 7)/8];", 207*de2caf28SDavid du Colombier "#endif", 20800d97012SDavid du Colombier " volatile OFFT m_p_offset[PMAX];", 20900d97012SDavid du Colombier " volatile OFFT m_q_offset[QMAX];", 21000d97012SDavid du Colombier " volatile uchar m_p_skip [PMAX];", 21100d97012SDavid du Colombier " volatile uchar m_q_skip [QMAX];", 21200d97012SDavid du Colombier "#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)", 21300d97012SDavid du Colombier " volatile uchar m_c_stack [StackSize];", 21400d97012SDavid du Colombier /* captures contents of c_stack[] for unmatched objects */ 21500d97012SDavid du Colombier "#endif", 21600d97012SDavid du Colombier "};", 21700d97012SDavid du Colombier "", 21800d97012SDavid du Colombier "int proxy_pid; /* id of proxy if nonzero -- receive half */", 21900d97012SDavid du Colombier "int store_proxy_pid;", 22000d97012SDavid du Colombier "short remote_party;", 22100d97012SDavid du Colombier "int proxy_pid_snd; /* id of proxy if nonzero -- send half */", 22200d97012SDavid du Colombier "", 22300d97012SDavid du Colombier "int iamin[CS_NR+NCORE]; /* non-shared */", 22400d97012SDavid du Colombier "", 22500d97012SDavid du Colombier "#if defined(WIN32) || defined(WIN64)", 22600d97012SDavid du Colombier "int tas(volatile LONG *);", 22700d97012SDavid du Colombier "", 22800d97012SDavid du Colombier "HANDLE proxy_handle_snd; /* for Windows Create and Terminate */", 22900d97012SDavid du Colombier "", 23000d97012SDavid du Colombier "struct sh_Allocater { /* shared memory for states */", 23100d97012SDavid du Colombier " volatile char *dc_arena; /* to allocate states from */", 23200d97012SDavid du Colombier " volatile long pattern; /* to detect overruns */", 23300d97012SDavid du Colombier " volatile long dc_size; /* nr of bytes left */", 23400d97012SDavid du Colombier " volatile void *dc_start; /* where memory segment starts */", 23500d97012SDavid du Colombier " volatile void *dc_id; /* to attach, detach, remove shared memory segments */", 23600d97012SDavid du Colombier " volatile sh_Allocater *nxt; /* linked list of pools */", 23700d97012SDavid du Colombier "};", 23800d97012SDavid du Colombier "DWORD worker_pids[NCORE]; /* root mem of pids of all workers created */", 23900d97012SDavid du Colombier "HANDLE worker_handles[NCORE]; /* for windows Create and Terminate */", 24000d97012SDavid du Colombier "void * shmid [NR_QS]; /* return value from CreateFileMapping */", 24100d97012SDavid du Colombier "void * shmid_M; /* shared mem for state allocation in hashtable */", 24200d97012SDavid du Colombier "", 24300d97012SDavid du Colombier "#ifdef SEP_STATE", 24400d97012SDavid du Colombier " void *shmid_X;", 24500d97012SDavid du Colombier "#else", 24600d97012SDavid du Colombier " void *shmid_S; /* shared bitstate arena or hashtable */", 24700d97012SDavid du Colombier "#endif", 24800d97012SDavid du Colombier "#else", 24900d97012SDavid du Colombier "int tas(volatile int *);", 25000d97012SDavid du Colombier "", 25100d97012SDavid du Colombier "struct sh_Allocater { /* shared memory for states */", 25200d97012SDavid du Colombier " volatile char *dc_arena; /* to allocate states from */", 25300d97012SDavid du Colombier " volatile long pattern; /* to detect overruns */", 25400d97012SDavid du Colombier " volatile long dc_size; /* nr of bytes left */", 25500d97012SDavid du Colombier " volatile char *dc_start; /* where memory segment starts */", 25600d97012SDavid du Colombier " volatile int dc_id; /* to attach, detach, remove shared memory segments */", 25700d97012SDavid du Colombier " volatile sh_Allocater *nxt; /* linked list of pools */", 25800d97012SDavid du Colombier "};", 25900d97012SDavid du Colombier "", 26000d97012SDavid du Colombier "int worker_pids[NCORE]; /* root mem of pids of all workers created */", 26100d97012SDavid du Colombier "int shmid [NR_QS]; /* return value from shmget */", 26200d97012SDavid du Colombier "int nibis = 0; /* set after shared mem has been released */", 26300d97012SDavid du Colombier "int shmid_M; /* shared mem for state allocation in hashtable */", 26400d97012SDavid du Colombier "#ifdef SEP_STATE", 26500d97012SDavid du Colombier " long shmid_X;", 26600d97012SDavid du Colombier "#else", 26700d97012SDavid du Colombier " int shmid_S; /* shared bitstate arena or hashtable */", 26800d97012SDavid du Colombier " volatile sh_Allocater *first_pool; /* of shared state memory */", 26900d97012SDavid du Colombier " volatile sh_Allocater *last_pool;", 27000d97012SDavid du Colombier "#endif", /* SEP_STATE */ 27100d97012SDavid du Colombier "#endif", /* WIN32 || WIN64 */ 27200d97012SDavid du Colombier "", 27300d97012SDavid du Colombier "struct SM_results { /* for shuttling back final stats */", 27400d97012SDavid du Colombier " volatile int m_vsize; /* avoid conflicts with frames */", 27500d97012SDavid du Colombier " volatile int m_boq; /* these 2 fields are not written in record_info */", 27600d97012SDavid du Colombier " /* probably not all fields really need to be volatile */", 27700d97012SDavid du Colombier " volatile double m_memcnt;", 27800d97012SDavid du Colombier " volatile double m_nstates;", 27900d97012SDavid du Colombier " volatile double m_truncs;", 28000d97012SDavid du Colombier " volatile double m_truncs2;", 28100d97012SDavid du Colombier " volatile double m_nShadow;", 28200d97012SDavid du Colombier " volatile double m_nlinks;", 28300d97012SDavid du Colombier " volatile double m_ngrabs;", 28400d97012SDavid du Colombier " volatile double m_nlost;", 28500d97012SDavid du Colombier " volatile double m_hcmp;", 28600d97012SDavid du Colombier " volatile double m_frame_wait;", 28700d97012SDavid du Colombier " volatile int m_hmax;", 28800d97012SDavid du Colombier " volatile int m_svmax;", 28900d97012SDavid du Colombier " volatile int m_smax;", 29000d97012SDavid du Colombier " volatile int m_mreached;", 29100d97012SDavid du Colombier " volatile int m_errors;", 29200d97012SDavid du Colombier " volatile int m_VMAX;", 29300d97012SDavid du Colombier " volatile short m_PMAX;", 29400d97012SDavid du Colombier " volatile short m_QMAX;", 29500d97012SDavid du Colombier " volatile uchar m_R; /* reached info for all proctypes */", 29600d97012SDavid du Colombier "};", 29700d97012SDavid du Colombier "", 29800d97012SDavid du Colombier "int core_id = 0; /* internal process nr, to know which q to use */", 29900d97012SDavid du Colombier "unsigned long nstates_put = 0; /* statistics */", 30000d97012SDavid du Colombier "unsigned long nstates_get = 0;", 30100d97012SDavid du Colombier "int query_in_progress = 0; /* termination detection */", 30200d97012SDavid du Colombier "", 30300d97012SDavid du Colombier "double free_wait = 0.; /* waiting for a free frame */", 30400d97012SDavid du Colombier "double frame_wait = 0.; /* waiting for a full frame */", 30500d97012SDavid du Colombier "double lock_wait = 0.; /* waiting for access to cs */", 30600d97012SDavid du Colombier "double glock_wait[3]; /* waiting for access to global lock */", 30700d97012SDavid du Colombier "", 30800d97012SDavid du Colombier "char *sprefix = \"rst\";", 30900d97012SDavid du Colombier "uchar was_interrupted, issued_kill, writing_trail;", 31000d97012SDavid du Colombier "", 31100d97012SDavid du Colombier "static SM_frame cur_Root; /* current root, to be safe with error trails */", 31200d97012SDavid du Colombier "", 31300d97012SDavid du Colombier "SM_frame *m_workq [NR_QS]; /* per cpu work queues + global q */", 31400d97012SDavid du Colombier "char *shared_mem[NR_QS]; /* return value from shmat */", 31500d97012SDavid du Colombier "#ifdef SEP_HEAP", 31600d97012SDavid du Colombier "char *my_heap;", 31700d97012SDavid du Colombier "long my_size;", 31800d97012SDavid du Colombier "#endif", 31900d97012SDavid du Colombier "volatile sh_Allocater *dc_shared; /* assigned at initialization */", 32000d97012SDavid du Colombier "", 32100d97012SDavid du Colombier "static int vmax_seen, pmax_seen, qmax_seen;", 32200d97012SDavid du Colombier "static double gq_tries, gq_hasroom, gq_hasnoroom;", 32300d97012SDavid du Colombier "", 32400d97012SDavid du Colombier "volatile int *prfree;", /* [NCORE] */ 32500d97012SDavid du Colombier "volatile int *prfull;", /* [NCORE] */ 32600d97012SDavid du Colombier "volatile int *prcnt;", /* [NCORE] */ 32700d97012SDavid du Colombier "volatile int *prmax;", /* [NCORE] */ 32800d97012SDavid du Colombier "", 32900d97012SDavid du Colombier "volatile int *sh_lock; /* mutual exclusion locks - in shared memory */", 33000d97012SDavid du Colombier "volatile double *is_alive; /* to detect when processes crash */", 33100d97012SDavid du Colombier "volatile int *grfree, *grfull, *grcnt, *grmax; /* access to shared global q */", 33200d97012SDavid du Colombier "volatile double *gr_readmiss, *gr_writemiss;", 33300d97012SDavid du Colombier "static int lrfree; /* used for temporary recording of slot */", 33400d97012SDavid du Colombier "static int dfs_phase2;", 33500d97012SDavid du Colombier "", 33600d97012SDavid du Colombier "void mem_put(int); /* handoff state to other cpu */", 33700d97012SDavid du Colombier "void mem_put_acc(void); /* liveness mode */", 33800d97012SDavid du Colombier "void mem_get(void); /* get state from work queue */", 33900d97012SDavid du Colombier "void sudden_stop(char *);", 34000d97012SDavid du Colombier "", 34100d97012SDavid du Colombier "void", 34200d97012SDavid du Colombier "record_info(SM_results *r)", 34300d97012SDavid du Colombier "{ int i;", 34400d97012SDavid du Colombier " uchar *ptr;", 34500d97012SDavid du Colombier "", 34600d97012SDavid du Colombier "#ifdef SEP_STATE", 34700d97012SDavid du Colombier " if (0)", 34800d97012SDavid du Colombier " { cpu_printf(\"nstates %%g nshadow %%g -- memory %%-6.3f Mb\\n\",", 34900d97012SDavid du Colombier " nstates, nShadow, memcnt/(1048576.));", 35000d97012SDavid du Colombier " }", 35100d97012SDavid du Colombier " r->m_memcnt = 0;", 35200d97012SDavid du Colombier "#else", 35300d97012SDavid du Colombier " #ifdef BITSTATE", 35400d97012SDavid du Colombier " r->m_memcnt = 0; /* it's shared */", 35500d97012SDavid du Colombier " #endif", 35600d97012SDavid du Colombier " r->m_memcnt = memcnt;", 35700d97012SDavid du Colombier "#endif", 35800d97012SDavid du Colombier " if (a_cycles && core_id == 1)", 35900d97012SDavid du Colombier " { r->m_nstates = nstates;", 36000d97012SDavid du Colombier " r->m_nShadow = nstates;", 36100d97012SDavid du Colombier " } else", 36200d97012SDavid du Colombier " { r->m_nstates = nstates;", 36300d97012SDavid du Colombier " r->m_nShadow = nShadow;", 36400d97012SDavid du Colombier " }", 36500d97012SDavid du Colombier " r->m_truncs = truncs;", 36600d97012SDavid du Colombier " r->m_truncs2 = truncs2;", 36700d97012SDavid du Colombier " r->m_nlinks = nlinks;", 36800d97012SDavid du Colombier " r->m_ngrabs = ngrabs;", 36900d97012SDavid du Colombier " r->m_nlost = nlost;", 37000d97012SDavid du Colombier " r->m_hcmp = hcmp;", 37100d97012SDavid du Colombier " r->m_frame_wait = frame_wait;", 37200d97012SDavid du Colombier " r->m_hmax = hmax;", 37300d97012SDavid du Colombier " r->m_svmax = svmax;", 37400d97012SDavid du Colombier " r->m_smax = smax;", 37500d97012SDavid du Colombier " r->m_mreached = mreached;", 376*de2caf28SDavid du Colombier " r->m_errors = (int) errors;", 37700d97012SDavid du Colombier " r->m_VMAX = vmax_seen;", 37800d97012SDavid du Colombier " r->m_PMAX = (short) pmax_seen;", 37900d97012SDavid du Colombier " r->m_QMAX = (short) qmax_seen;", 38000d97012SDavid du Colombier " ptr = (uchar *) &(r->m_R);", 38100d97012SDavid du Colombier " for (i = 0; i <= _NP_; i++) /* all proctypes */", 38200d97012SDavid du Colombier " { memcpy(ptr, reached[i], NrStates[i]*sizeof(uchar));", 38300d97012SDavid du Colombier " ptr += NrStates[i]*sizeof(uchar);", 38400d97012SDavid du Colombier " }", 38500d97012SDavid du Colombier " if (verbose>1)", 38600d97012SDavid du Colombier " { cpu_printf(\"Put Results nstates %%g (sz %%d)\\n\", nstates, ptr - &(r->m_R));", 38700d97012SDavid du Colombier " }", 38800d97012SDavid du Colombier "}", 38900d97012SDavid du Colombier "", 39000d97012SDavid du Colombier "void snapshot(void);", 39100d97012SDavid du Colombier "", 39200d97012SDavid du Colombier "void", 39300d97012SDavid du Colombier "retrieve_info(SM_results *r)", 39400d97012SDavid du Colombier "{ int i, j;", 39500d97012SDavid du Colombier " volatile uchar *ptr;", 39600d97012SDavid du Colombier "", 39700d97012SDavid du Colombier " snapshot(); /* for a final report */", 39800d97012SDavid du Colombier "", 39900d97012SDavid du Colombier " enter_critical(GLOBAL_LOCK);", 40000d97012SDavid du Colombier "#ifdef SEP_HEAP", 40100d97012SDavid du Colombier " if (verbose)", 40200d97012SDavid du Colombier " { printf(\"cpu%%d: local heap-left %%ld KB (%%d MB)\\n\",", 40300d97012SDavid du Colombier " core_id, (long) (my_size/1024), (int) (my_size/1048576));", 40400d97012SDavid du Colombier " }", 40500d97012SDavid du Colombier "#endif", 40600d97012SDavid du Colombier " if (verbose && core_id == 0)", 40700d97012SDavid du Colombier " { printf(\"qmax: \");", 40800d97012SDavid du Colombier " for (i = 0; i < NCORE; i++)", 40900d97012SDavid du Colombier " { printf(\"%%d \", prmax[i]);", 41000d97012SDavid du Colombier " }", 41100d97012SDavid du Colombier "#ifndef NGQ", 41200d97012SDavid du Colombier " printf(\"G: %%d\", *grmax);", 41300d97012SDavid du Colombier "#endif", 41400d97012SDavid du Colombier " printf(\"\\n\");", 41500d97012SDavid du Colombier " }", 41600d97012SDavid du Colombier " leave_critical(GLOBAL_LOCK);", 41700d97012SDavid du Colombier "", 41800d97012SDavid du Colombier " memcnt += r->m_memcnt;", 41900d97012SDavid du Colombier " nstates += r->m_nstates;", 42000d97012SDavid du Colombier " nShadow += r->m_nShadow;", 42100d97012SDavid du Colombier " truncs += r->m_truncs;", 42200d97012SDavid du Colombier " truncs2 += r->m_truncs2;", 42300d97012SDavid du Colombier " nlinks += r->m_nlinks;", 42400d97012SDavid du Colombier " ngrabs += r->m_ngrabs;", 42500d97012SDavid du Colombier " nlost += r->m_nlost;", 42600d97012SDavid du Colombier " hcmp += r->m_hcmp;", 42700d97012SDavid du Colombier " /* frame_wait += r->m_frame_wait; */", 428*de2caf28SDavid du Colombier " errors += (unsigned long int) r->m_errors;", 42900d97012SDavid du Colombier "", 43000d97012SDavid du Colombier " if (hmax < r->m_hmax) hmax = r->m_hmax;", 43100d97012SDavid du Colombier " if (svmax < r->m_svmax) svmax = r->m_svmax;", 43200d97012SDavid du Colombier " if (smax < r->m_smax) smax = r->m_smax;", 43300d97012SDavid du Colombier " if (mreached < r->m_mreached) mreached = r->m_mreached;", 43400d97012SDavid du Colombier "", 43500d97012SDavid du Colombier " if (vmax_seen < r->m_VMAX) vmax_seen = r->m_VMAX;", 43600d97012SDavid du Colombier " if (pmax_seen < (int) r->m_PMAX) pmax_seen = (int) r->m_PMAX;", 43700d97012SDavid du Colombier " if (qmax_seen < (int) r->m_QMAX) qmax_seen = (int) r->m_QMAX;", 43800d97012SDavid du Colombier "", 43900d97012SDavid du Colombier " ptr = &(r->m_R);", 44000d97012SDavid du Colombier " for (i = 0; i <= _NP_; i++) /* all proctypes */", 44100d97012SDavid du Colombier " { for (j = 0; j < NrStates[i]; j++)", 44200d97012SDavid du Colombier " { if (*(ptr + j) != 0)", 44300d97012SDavid du Colombier " { reached[i][j] = 1;", 44400d97012SDavid du Colombier " } }", 44500d97012SDavid du Colombier " ptr += NrStates[i]*sizeof(uchar);", 44600d97012SDavid du Colombier " }", 44700d97012SDavid du Colombier " if (verbose>1)", 44800d97012SDavid du Colombier " { cpu_printf(\"Got Results (%%d)\\n\", (int) (ptr - &(r->m_R)));", 44900d97012SDavid du Colombier " snapshot();", 45000d97012SDavid du Colombier " }", 45100d97012SDavid du Colombier "}", 45200d97012SDavid du Colombier "", 45300d97012SDavid du Colombier "#if !defined(WIN32) && !defined(WIN64)", 45400d97012SDavid du Colombier "static void", 45500d97012SDavid du Colombier "rm_shared_segments(void)", 45600d97012SDavid du Colombier "{ int m;", 45700d97012SDavid du Colombier " volatile sh_Allocater *nxt_pool;", 45800d97012SDavid du Colombier " /*", 45900d97012SDavid du Colombier " * mark all shared memory segments for removal ", 460*de2caf28SDavid du Colombier " * the actual removes won't happen intil last process dies or detaches", 46100d97012SDavid du Colombier " * the shmctl calls can return -1 if not all procs have detached yet", 46200d97012SDavid du Colombier " */", 46300d97012SDavid du Colombier " for (m = 0; m < NR_QS; m++) /* +1 for global q */", 46400d97012SDavid du Colombier " { if (shmid[m] != -1)", 46500d97012SDavid du Colombier " { (void) shmctl(shmid[m], IPC_RMID, NULL);", 46600d97012SDavid du Colombier " } }", 46700d97012SDavid du Colombier "#ifdef SEP_STATE", 46800d97012SDavid du Colombier " if (shmid_M != -1)", 46900d97012SDavid du Colombier " { (void) shmctl(shmid_M, IPC_RMID, NULL);", 47000d97012SDavid du Colombier " }", 47100d97012SDavid du Colombier "#else", 47200d97012SDavid du Colombier " if (shmid_S != -1)", 47300d97012SDavid du Colombier " { (void) shmctl(shmid_S, IPC_RMID, NULL);", 47400d97012SDavid du Colombier " }", 47500d97012SDavid du Colombier " for (last_pool = first_pool; last_pool != NULL; last_pool = nxt_pool)", 47600d97012SDavid du Colombier " { shmid_M = (int) (last_pool->dc_id);", 47700d97012SDavid du Colombier " nxt_pool = last_pool->nxt; /* as a pre-caution only */", 47800d97012SDavid du Colombier " if (shmid_M != -1)", 47900d97012SDavid du Colombier " { (void) shmctl(shmid_M, IPC_RMID, NULL);", 48000d97012SDavid du Colombier " } }", 48100d97012SDavid du Colombier "#endif", 48200d97012SDavid du Colombier "}", 48300d97012SDavid du Colombier "#endif", 48400d97012SDavid du Colombier "", 48500d97012SDavid du Colombier "void", 48600d97012SDavid du Colombier "sudden_stop(char *s)", 48700d97012SDavid du Colombier "{ char b[64];", 48800d97012SDavid du Colombier " int i;", 48900d97012SDavid du Colombier "", 49000d97012SDavid du Colombier " printf(\"cpu%%d: stop - %%s\\n\", core_id, s);", 49100d97012SDavid du Colombier "#if !defined(WIN32) && !defined(WIN64)", 49200d97012SDavid du Colombier " if (proxy_pid != 0)", 49300d97012SDavid du Colombier " { rm_shared_segments();", 49400d97012SDavid du Colombier " }", 49500d97012SDavid du Colombier "#endif", 49600d97012SDavid du Colombier " if (search_terminated != NULL)", 49700d97012SDavid du Colombier " { if (*search_terminated != 0)", 49800d97012SDavid du Colombier " { if (verbose)", 49900d97012SDavid du Colombier " { printf(\"cpu%%d: termination initiated (%%d)\\n\",", 500*de2caf28SDavid du Colombier " core_id, (int) *search_terminated);", 50100d97012SDavid du Colombier " }", 50200d97012SDavid du Colombier " } else", 50300d97012SDavid du Colombier " { if (verbose)", 50400d97012SDavid du Colombier " { printf(\"cpu%%d: initiated termination\\n\", core_id);", 50500d97012SDavid du Colombier " }", 50600d97012SDavid du Colombier " *search_terminated |= 8; /* sudden_stop */", 50700d97012SDavid du Colombier " }", 50800d97012SDavid du Colombier " if (core_id == 0)", 50900d97012SDavid du Colombier " { if (((*search_terminated) & 4) /* uerror in one of the cpus */", 51000d97012SDavid du Colombier " && !((*search_terminated) & (8|32|128|256))) /* abnormal stop */", 51100d97012SDavid du Colombier " { if (errors == 0) errors++; /* we know there is at least 1 */", 51200d97012SDavid du Colombier " }", 51300d97012SDavid du Colombier " wrapup(); /* incomplete stats, but at least something */", 51400d97012SDavid du Colombier " }", 51500d97012SDavid du Colombier " return;", 51600d97012SDavid du Colombier " } /* else: should rarely happen, take more drastic measures */", 51700d97012SDavid du Colombier "", 51800d97012SDavid du Colombier " if (core_id == 0) /* local root process */", 51900d97012SDavid du Colombier " { for (i = 1; i < NCORE; i++) /* not for 0 of course */", 520*de2caf28SDavid du Colombier " { int ignore;", 52100d97012SDavid du Colombier "#if defined(WIN32) || defined(WIN64)", 52200d97012SDavid du Colombier " DWORD dwExitCode = 0;", 52300d97012SDavid du Colombier " GetExitCodeProcess(worker_handles[i], &dwExitCode);", 52400d97012SDavid du Colombier " if (dwExitCode == STILL_ACTIVE)", 52500d97012SDavid du Colombier " { TerminateProcess(worker_handles[i], 0);", 52600d97012SDavid du Colombier " }", 52700d97012SDavid du Colombier " printf(\"cpu0: terminate %%d %%d\\n\",", 528*de2caf28SDavid du Colombier " (int) worker_pids[i], (dwExitCode == STILL_ACTIVE));", 52900d97012SDavid du Colombier "#else", 530*de2caf28SDavid du Colombier " sprintf(b, \"kill -%%d %%d\", (int) SIGKILL, (int) worker_pids[i]);", 531*de2caf28SDavid du Colombier " ignore = system(b); /* if this is a proxy: receive half */", 53200d97012SDavid du Colombier " printf(\"cpu0: %%s\\n\", b);", 53300d97012SDavid du Colombier "#endif", 53400d97012SDavid du Colombier " }", 53500d97012SDavid du Colombier " issued_kill++;", 53600d97012SDavid du Colombier " } else", 53700d97012SDavid du Colombier " { /* on WIN32/WIN64 -- these merely kills the root process... */", 53800d97012SDavid du Colombier " if (was_interrupted == 0)", /* 2=SIGINT to root to trigger stop */ 539*de2caf28SDavid du Colombier " { int ignore;", 540*de2caf28SDavid du Colombier " sprintf(b, \"kill -%%d %%d\", (int) SIGINT, (int) worker_pids[0]);", 541*de2caf28SDavid du Colombier " ignore = system(b); /* warn the root process */", 54200d97012SDavid du Colombier " printf(\"cpu%%d: %%s\\n\", core_id, b);", 54300d97012SDavid du Colombier " issued_kill++;", 54400d97012SDavid du Colombier " } }", 54500d97012SDavid du Colombier "}", 54600d97012SDavid du Colombier "", 54700d97012SDavid du Colombier "#define iam_alive() is_alive[core_id]++", /* for crash detection */ 54800d97012SDavid du Colombier "", 54900d97012SDavid du Colombier "extern int crash_test(double);", 55000d97012SDavid du Colombier "extern void crash_reset(void);", 55100d97012SDavid du Colombier "", 55200d97012SDavid du Colombier "int", 55300d97012SDavid du Colombier "someone_crashed(int wait_type)", 55400d97012SDavid du Colombier "{ static double last_value = 0.0;", 55500d97012SDavid du Colombier " static int count = 0;", 55600d97012SDavid du Colombier "", 55700d97012SDavid du Colombier " if (search_terminated == NULL", 55800d97012SDavid du Colombier " || *search_terminated != 0)", 55900d97012SDavid du Colombier " {", 56000d97012SDavid du Colombier " if (!(*search_terminated & (8|32|128|256)))", 56100d97012SDavid du Colombier " { if (count++ < 100*NCORE)", 56200d97012SDavid du Colombier " { return 0;", 56300d97012SDavid du Colombier " } }", 56400d97012SDavid du Colombier " return 1;", 56500d97012SDavid du Colombier " }", 56600d97012SDavid du Colombier " /* check left neighbor only */", 56700d97012SDavid du Colombier " if (last_value == is_alive[(core_id + NCORE - 1) %% NCORE])", 56800d97012SDavid du Colombier " { if (count++ >= 100) /* to avoid unnecessary checks */", 56900d97012SDavid du Colombier " { return 1;", 57000d97012SDavid du Colombier " }", 57100d97012SDavid du Colombier " return 0;", 57200d97012SDavid du Colombier " }", 57300d97012SDavid du Colombier " last_value = is_alive[(core_id + NCORE - 1) %% NCORE];", 57400d97012SDavid du Colombier " count = 0;", 57500d97012SDavid du Colombier " crash_reset();", 57600d97012SDavid du Colombier " return 0;", 57700d97012SDavid du Colombier "}", 57800d97012SDavid du Colombier "", 57900d97012SDavid du Colombier "void", 58000d97012SDavid du Colombier "sleep_report(void)", 58100d97012SDavid du Colombier "{", 58200d97012SDavid du Colombier " enter_critical(GLOBAL_LOCK);", 58300d97012SDavid du Colombier " if (verbose)", 58400d97012SDavid du Colombier " {", 58500d97012SDavid du Colombier "#ifdef NGQ", 58600d97012SDavid du Colombier " printf(\"cpu%%d: locks: global %%g\\tother %%g\\t\",", 58700d97012SDavid du Colombier " core_id, glock_wait[0], lock_wait - glock_wait[0]);", 58800d97012SDavid du Colombier "#else", 58900d97012SDavid du Colombier " printf(\"cpu%%d: locks: GL %%g, RQ %%g, WQ %%g, HT %%g\\t\",", 59000d97012SDavid du Colombier " core_id, glock_wait[0], glock_wait[1], glock_wait[2],", 59100d97012SDavid du Colombier " lock_wait - glock_wait[0] - glock_wait[1] - glock_wait[2]);", 59200d97012SDavid du Colombier "#endif", 59300d97012SDavid du Colombier " printf(\"waits: states %%g slots %%g\\n\", frame_wait, free_wait);", 59400d97012SDavid du Colombier "#ifndef NGQ", 59500d97012SDavid du Colombier " printf(\"cpu%%d: gq [tries %%g, room %%g, noroom %%g]\\n\", core_id, gq_tries, gq_hasroom, gq_hasnoroom);", 59600d97012SDavid du Colombier " if (core_id == 0 && (*gr_readmiss >= 1.0 || *gr_readmiss >= 1.0 || *grcnt != 0))", 59700d97012SDavid du Colombier " printf(\"cpu0: gq [readmiss: %%g, writemiss: %%g cnt %%d]\\n\", *gr_readmiss, *gr_writemiss, *grcnt);", 59800d97012SDavid du Colombier "#endif", 59900d97012SDavid du Colombier " }", 60000d97012SDavid du Colombier " if (free_wait > 1000000.)", 60100d97012SDavid du Colombier " #ifndef NGQ", 60200d97012SDavid du Colombier " if (!a_cycles)", 60300d97012SDavid du Colombier " { printf(\"hint: this search may be faster with a larger work-queue\\n\");", 60400d97012SDavid du Colombier " printf(\" (-DSET_WQ_SIZE=N with N>%%g), and/or with -DUSE_DISK\\n\",", 60500d97012SDavid du Colombier " GWQ_SIZE/sizeof(SM_frame));", 60600d97012SDavid du Colombier " printf(\" or with a larger value for -zN (N>%%ld)\\n\", z_handoff);", 60700d97012SDavid du Colombier " #else", 60800d97012SDavid du Colombier " { printf(\"hint: this search may be faster if compiled without -DNGQ, with -DUSE_DISK, \");", 60900d97012SDavid du Colombier " printf(\"or with a larger -zN (N>%%d)\\n\", z_handoff);", 61000d97012SDavid du Colombier " #endif", 61100d97012SDavid du Colombier " }", 61200d97012SDavid du Colombier " leave_critical(GLOBAL_LOCK);", 61300d97012SDavid du Colombier "}", 61400d97012SDavid du Colombier "", 61500d97012SDavid du Colombier "#ifndef MAX_DSK_FILE", 61600d97012SDavid du Colombier " #define MAX_DSK_FILE 1000000 /* default is max 1M states per file */", 61700d97012SDavid du Colombier "#endif", 61800d97012SDavid du Colombier "", 61900d97012SDavid du Colombier "void", 62000d97012SDavid du Colombier "multi_usage(FILE *fd)", 62100d97012SDavid du Colombier "{ static int warned = 0;", 62200d97012SDavid du Colombier " if (warned > 0) { return; } else { warned++; }", 62300d97012SDavid du Colombier " fprintf(fd, \"\\n\");", 62400d97012SDavid du Colombier " fprintf(fd, \"Defining multi-core mode:\\n\\n\");", 62500d97012SDavid du Colombier " fprintf(fd, \" -DDUAL_CORE --> same as -DNCORE=2\\n\");", 62600d97012SDavid du Colombier " fprintf(fd, \" -DQUAD_CORE --> same as -DNCORE=4\\n\");", 62700d97012SDavid du Colombier " fprintf(fd, \" -DNCORE=N --> enables multi_core verification if N>1\\n\");", 62800d97012SDavid du Colombier " fprintf(fd, \"\\n\");", 62900d97012SDavid du Colombier " fprintf(fd, \"Additional directives supported in multi-core mode:\\n\\n\");", 63000d97012SDavid du Colombier " fprintf(fd, \" -DSEP_STATE --> forces separate statespaces instead of a single shared state space\\n\");", 63100d97012SDavid du Colombier " fprintf(fd, \" -DNUSE_DISK --> use disk for storing states when a work queue overflows\\n\");", 63200d97012SDavid du Colombier " fprintf(fd, \" -DMAX_DSK_FILE --> max nr of states per diskfile (%%d)\\n\", MAX_DSK_FILE);", 63300d97012SDavid du Colombier " fprintf(fd, \" -DFULL_TRAIL --> support full error trails (increases memory use)\\n\");", 63400d97012SDavid du Colombier " fprintf(fd, \"\\n\");", 63500d97012SDavid du Colombier " fprintf(fd, \"More advanced use (should rarely need changing):\\n\\n\");", 63600d97012SDavid du Colombier " fprintf(fd, \" To change the nr of states that can be stored in the global queue\\n\");", 63700d97012SDavid du Colombier " fprintf(fd, \" (lower numbers allow for more states to be stored, prefer multiples of 8):\\n\");", 63800d97012SDavid du Colombier " fprintf(fd, \" -DVMAX=N --> upperbound on statevector for handoffs (N=%%d)\\n\", VMAX);", 63900d97012SDavid du Colombier " fprintf(fd, \" -DPMAX=N --> upperbound on nr of procs (default: N=%%d)\\n\", PMAX);", 64000d97012SDavid du Colombier " fprintf(fd, \" -DQMAX=N --> upperbound on nr of channels (default: N=%%d)\\n\", QMAX);", 64100d97012SDavid du Colombier " fprintf(fd, \"\\n\");", 64200d97012SDavid du Colombier #if 0 64300d97012SDavid du Colombier "#if !defined(WIN32) && !defined(WIN64)", 64400d97012SDavid du Colombier " fprintf(fd, \" To change the size of spin's individual shared memory segments for cygwin/linux:\\n\");", 64500d97012SDavid du Colombier " fprintf(fd, \" -DSET_SEG_SIZE=N --> default %%g (Mbytes)\\n\", SEG_SIZE/(1048576.));", 64600d97012SDavid du Colombier " fprintf(fd, \"\\n\");", 64700d97012SDavid du Colombier "#endif", 64800d97012SDavid du Colombier #endif 64900d97012SDavid du Colombier " fprintf(fd, \" To set the total amount of memory reserved for the global workqueue:\\n\");", 65000d97012SDavid du Colombier " fprintf(fd, \" -DSET_WQ_SIZE=N --> default: N=128 (defined in MBytes)\\n\\n\");", 65100d97012SDavid du Colombier #if 0 65200d97012SDavid du Colombier " fprintf(fd, \" To omit the global workqueue completely (bad idea):\\n\");", 65300d97012SDavid du Colombier " fprintf(fd, \" -DNGQ\\n\\n\");", 65400d97012SDavid du Colombier #endif 65500d97012SDavid du Colombier " fprintf(fd, \" To force the use of a single global heap, instead of separate heaps:\\n\");", 65600d97012SDavid du Colombier " fprintf(fd, \" -DGLOB_HEAP\\n\");", 65700d97012SDavid du Colombier " fprintf(fd, \"\\n\");", 65800d97012SDavid du Colombier " fprintf(fd, \" To define a fct to initialize data before spawning processes (use quotes):\\n\");", 65900d97012SDavid du Colombier " fprintf(fd, \" \\\"-DC_INIT=fct()\\\"\\n\");", 66000d97012SDavid du Colombier " fprintf(fd, \"\\n\");", 66100d97012SDavid du Colombier " fprintf(fd, \" Timer settings for termination and crash detection:\\n\");", 66200d97012SDavid du Colombier " fprintf(fd, \" -DSHORT_T=N --> timeout for termination detection trigger (N=%%g)\\n\", (double) SHORT_T);", 66300d97012SDavid du Colombier " fprintf(fd, \" -DLONG_T=N --> timeout for giving up on termination detection (N=%%g)\\n\", (double) LONG_T);", 66400d97012SDavid du Colombier " fprintf(fd, \" -DONESECOND --> (1<<29) --> timeout waiting for a free slot -- to check for crash\\n\");", 66500d97012SDavid du Colombier " fprintf(fd, \" -DT_ALERT --> collect stats on crash alert timeouts\\n\\n\");", 66600d97012SDavid du Colombier " fprintf(fd, \"Help with Linux/Windows/Cygwin configuration for multi-core:\\n\");", 66700d97012SDavid du Colombier " fprintf(fd, \" http://spinroot.com/spin/multicore/V5_Readme.html\\n\");", 66800d97012SDavid du Colombier " fprintf(fd, \"\\n\");", 66900d97012SDavid du Colombier "}", 67000d97012SDavid du Colombier "#if NCORE>1 && defined(FULL_TRAIL)", 67100d97012SDavid du Colombier "typedef struct Stack_Tree {", 67200d97012SDavid du Colombier " uchar pr; /* process that made transition */", 67300d97012SDavid du Colombier " T_ID t_id; /* id of transition */", 67400d97012SDavid du Colombier " volatile struct Stack_Tree *prv; /* backward link towards root */", 67500d97012SDavid du Colombier "} Stack_Tree;", 67600d97012SDavid du Colombier "", 677*de2caf28SDavid du Colombier "H_el *grab_shared(int);", 67800d97012SDavid du Colombier "volatile Stack_Tree **stack_last; /* in shared memory */", 67900d97012SDavid du Colombier "char *stack_cache = NULL; /* local */", 68000d97012SDavid du Colombier "int nr_cached = 0; /* local */", 68100d97012SDavid du Colombier "", 68200d97012SDavid du Colombier "#ifndef CACHE_NR", 68300d97012SDavid du Colombier " #define CACHE_NR 1024", 68400d97012SDavid du Colombier "#endif", 68500d97012SDavid du Colombier "", 68600d97012SDavid du Colombier "volatile Stack_Tree *", 68700d97012SDavid du Colombier "stack_prefetch(void)", 68800d97012SDavid du Colombier "{ volatile Stack_Tree *st;", 68900d97012SDavid du Colombier "", 69000d97012SDavid du Colombier " if (nr_cached == 0)", 69100d97012SDavid du Colombier " { stack_cache = (char *) grab_shared(CACHE_NR * sizeof(Stack_Tree));", 69200d97012SDavid du Colombier " nr_cached = CACHE_NR;", 69300d97012SDavid du Colombier " }", 69400d97012SDavid du Colombier " st = (volatile Stack_Tree *) stack_cache;", 69500d97012SDavid du Colombier " stack_cache += sizeof(Stack_Tree);", 69600d97012SDavid du Colombier " nr_cached--;", 69700d97012SDavid du Colombier " return st;", 69800d97012SDavid du Colombier "}", 69900d97012SDavid du Colombier "", 70000d97012SDavid du Colombier "void", 70100d97012SDavid du Colombier "Push_Stack_Tree(short II, T_ID t_id)", 70200d97012SDavid du Colombier "{ volatile Stack_Tree *st;", 70300d97012SDavid du Colombier "", 70400d97012SDavid du Colombier " st = (volatile Stack_Tree *) stack_prefetch();", 70500d97012SDavid du Colombier " st->pr = II;", 70600d97012SDavid du Colombier " st->t_id = t_id;", 70700d97012SDavid du Colombier " st->prv = (Stack_Tree *) stack_last[core_id];", 70800d97012SDavid du Colombier " stack_last[core_id] = st;", 70900d97012SDavid du Colombier "}", 71000d97012SDavid du Colombier "", 71100d97012SDavid du Colombier "void", 71200d97012SDavid du Colombier "Pop_Stack_Tree(void)", 71300d97012SDavid du Colombier "{ volatile Stack_Tree *cf = stack_last[core_id];", 71400d97012SDavid du Colombier "", 71500d97012SDavid du Colombier " if (cf)", 71600d97012SDavid du Colombier " { stack_last[core_id] = cf->prv;", 71700d97012SDavid du Colombier " } else if (nr_handoffs * z_handoff + depth > 0)", 718*de2caf28SDavid du Colombier " { printf(\"cpu%%d: error pop_stack_tree (depth %%ld)\\n\",", 71900d97012SDavid du Colombier " core_id, depth);", 72000d97012SDavid du Colombier " }", 72100d97012SDavid du Colombier "}", 72200d97012SDavid du Colombier "#endif", /* NCORE>1 && FULL_TRAIL */ 72300d97012SDavid du Colombier "", 72400d97012SDavid du Colombier "void", 72500d97012SDavid du Colombier "e_critical(int which)", 72600d97012SDavid du Colombier "{ double cnt_start;", 72700d97012SDavid du Colombier "", 72800d97012SDavid du Colombier " if (readtrail || iamin[which] > 0)", 72900d97012SDavid du Colombier " { if (!readtrail && verbose)", 73000d97012SDavid du Colombier " { printf(\"cpu%%d: Double Lock on %%d (now %%d)\\n\",", 73100d97012SDavid du Colombier " core_id, which, iamin[which]+1);", 73200d97012SDavid du Colombier " fflush(stdout);", 73300d97012SDavid du Colombier " }", 73400d97012SDavid du Colombier " iamin[which]++; /* local variable */", 73500d97012SDavid du Colombier " return;", 73600d97012SDavid du Colombier " }", 73700d97012SDavid du Colombier "", 73800d97012SDavid du Colombier " cnt_start = lock_wait;", 73900d97012SDavid du Colombier "", 74000d97012SDavid du Colombier " while (sh_lock != NULL) /* as long as we have shared memory */", 74100d97012SDavid du Colombier " { int r = tas(&sh_lock[which]);", 74200d97012SDavid du Colombier " if (r == 0)", 74300d97012SDavid du Colombier " { iamin[which] = 1;", 74400d97012SDavid du Colombier " return; /* locked */", 74500d97012SDavid du Colombier " }", 74600d97012SDavid du Colombier "", 74700d97012SDavid du Colombier " lock_wait++;", 74800d97012SDavid du Colombier "#ifndef NGQ", 74900d97012SDavid du Colombier " if (which < 3) { glock_wait[which]++; }", 75000d97012SDavid du Colombier "#else", 75100d97012SDavid du Colombier " if (which == 0) { glock_wait[which]++; }", 75200d97012SDavid du Colombier "#endif", 75300d97012SDavid du Colombier " iam_alive();", 75400d97012SDavid du Colombier "", 75500d97012SDavid du Colombier " if (lock_wait - cnt_start > TenSeconds)", 75600d97012SDavid du Colombier " { printf(\"cpu%%d: lock timeout on %%d\\n\", core_id, which);", 75700d97012SDavid du Colombier " cnt_start = lock_wait;", 75800d97012SDavid du Colombier " if (someone_crashed(1))", 75900d97012SDavid du Colombier " { sudden_stop(\"lock timeout\");", 76000d97012SDavid du Colombier " pan_exit(1);", 76100d97012SDavid du Colombier " } } }", 76200d97012SDavid du Colombier "}", 76300d97012SDavid du Colombier "", 76400d97012SDavid du Colombier "void", 76500d97012SDavid du Colombier "x_critical(int which)", 76600d97012SDavid du Colombier "{", 76700d97012SDavid du Colombier " if (iamin[which] != 1)", 76800d97012SDavid du Colombier " { if (iamin[which] > 1)", 76900d97012SDavid du Colombier " { iamin[which]--; /* this is thread-local - no races on this one */", 77000d97012SDavid du Colombier " if (!readtrail && verbose)", 77100d97012SDavid du Colombier " { printf(\"cpu%%d: Partial Unlock on %%d (%%d more needed)\\n\",", 77200d97012SDavid du Colombier " core_id, which, iamin[which]);", 77300d97012SDavid du Colombier " fflush(stdout);", 77400d97012SDavid du Colombier " }", 77500d97012SDavid du Colombier " return;", 77600d97012SDavid du Colombier " } else /* iamin[which] <= 0 */", 77700d97012SDavid du Colombier " { if (!readtrail)", 77800d97012SDavid du Colombier " { printf(\"cpu%%d: Invalid Unlock iamin[%%d] = %%d\\n\",", 77900d97012SDavid du Colombier " core_id, which, iamin[which]);", 78000d97012SDavid du Colombier " fflush(stdout);", 78100d97012SDavid du Colombier " }", 78200d97012SDavid du Colombier " return;", 78300d97012SDavid du Colombier " } }", 78400d97012SDavid du Colombier "", 78500d97012SDavid du Colombier " if (sh_lock != NULL)", 78600d97012SDavid du Colombier " { iamin[which] = 0;", 787*de2caf28SDavid du Colombier "#if defined(__powerpc64__)", 788*de2caf28SDavid du Colombier " #if 1", 789*de2caf28SDavid du Colombier " __sync_synchronize(); /* srirajpaul */", 790*de2caf28SDavid du Colombier " #else", 791*de2caf28SDavid du Colombier " __lwsync(); /* xlc compiler only */", 792*de2caf28SDavid du Colombier " #endif", 793*de2caf28SDavid du Colombier "#endif", 79400d97012SDavid du Colombier " sh_lock[which] = 0; /* unlock */", 79500d97012SDavid du Colombier " }", 79600d97012SDavid du Colombier "}", 79700d97012SDavid du Colombier "", 79800d97012SDavid du Colombier "void", 79900d97012SDavid du Colombier "#if defined(WIN32) || defined(WIN64)", 80000d97012SDavid du Colombier "start_proxy(char *s, DWORD r_pid)", 80100d97012SDavid du Colombier "#else", 80200d97012SDavid du Colombier "start_proxy(char *s, int r_pid)", 80300d97012SDavid du Colombier "#endif", 80400d97012SDavid du Colombier "{ char Q_arg[16], Z_arg[16], Y_arg[16];", 80500d97012SDavid du Colombier " char *args[32], *ptr;", 80600d97012SDavid du Colombier " int argcnt = 0;", 80700d97012SDavid du Colombier "", 80800d97012SDavid du Colombier " sprintf(Q_arg, \"-Q%%d\", getpid());", 80900d97012SDavid du Colombier " sprintf(Y_arg, \"-Y%%d\", r_pid);", 81000d97012SDavid du Colombier " sprintf(Z_arg, \"-Z%%d\", proxy_pid /* core_id */);", 81100d97012SDavid du Colombier "", 81200d97012SDavid du Colombier " args[argcnt++] = \"proxy\";", 81300d97012SDavid du Colombier " args[argcnt++] = s; /* -r or -s */", 81400d97012SDavid du Colombier " args[argcnt++] = Q_arg;", 81500d97012SDavid du Colombier " args[argcnt++] = Z_arg;", 81600d97012SDavid du Colombier " args[argcnt++] = Y_arg;", 81700d97012SDavid du Colombier "", 81800d97012SDavid du Colombier " if (strlen(o_cmdline) > 0)", 81900d97012SDavid du Colombier " { ptr = o_cmdline; /* assume args separated by spaces */", 82000d97012SDavid du Colombier " do { args[argcnt++] = ptr++;", 82100d97012SDavid du Colombier " if ((ptr = strchr(ptr, ' ')) != NULL)", 82200d97012SDavid du Colombier " { while (*ptr == ' ')", 82300d97012SDavid du Colombier " { *ptr++ = '\\0';", 82400d97012SDavid du Colombier " }", 82500d97012SDavid du Colombier " } else", 82600d97012SDavid du Colombier " { break;", 82700d97012SDavid du Colombier " }", 82800d97012SDavid du Colombier " } while (argcnt < 31);", 82900d97012SDavid du Colombier " }", 83000d97012SDavid du Colombier " args[argcnt] = NULL;", 83100d97012SDavid du Colombier "#if defined(WIN32) || defined(WIN64)", 83200d97012SDavid du Colombier " execvp(\"pan_proxy\", args); /* no return */", 83300d97012SDavid du Colombier "#else", 83400d97012SDavid du Colombier " execvp(\"./pan_proxy\", args); /* no return */", 83500d97012SDavid du Colombier "#endif", 83600d97012SDavid du Colombier " Uerror(\"pan_proxy exec failed\");", 83700d97012SDavid du Colombier "}", 83800d97012SDavid du Colombier "/*** end of common code fragment ***/", 83900d97012SDavid du Colombier "", 84000d97012SDavid du Colombier "#if !defined(WIN32) && !defined(WIN64)", 84100d97012SDavid du Colombier "void", 84200d97012SDavid du Colombier "init_shm(void) /* initialize shared work-queues - linux/cygwin */", 84300d97012SDavid du Colombier "{ key_t key[NR_QS];", 84400d97012SDavid du Colombier " int n, m;", 84500d97012SDavid du Colombier " int must_exit = 0;", 84600d97012SDavid du Colombier "", 84700d97012SDavid du Colombier " if (core_id == 0 && verbose)", 84800d97012SDavid du Colombier " { printf(\"cpu0: step 3: allocate shared workqueues %%g MB\\n\",", 84900d97012SDavid du Colombier " ((double) NCORE * LWQ_SIZE + GWQ_SIZE) / (1048576.) );", 85000d97012SDavid du Colombier " }", 85100d97012SDavid du Colombier " for (m = 0; m < NR_QS; m++) /* last q is the global q */", 85200d97012SDavid du Colombier " { double qsize = (m == NCORE) ? GWQ_SIZE : LWQ_SIZE;", 85300d97012SDavid du Colombier " key[m] = ftok(PanSource, m+1);", /* m must be nonzero, 1..NCORE */ 85400d97012SDavid du Colombier " if (key[m] == -1)", 85500d97012SDavid du Colombier " { perror(\"ftok shared queues\"); must_exit = 1; break;", 85600d97012SDavid du Colombier " }", 85700d97012SDavid du Colombier "", 85800d97012SDavid du Colombier " if (core_id == 0) /* root creates */", 85900d97012SDavid du Colombier " { /* check for stale copy */", 86000d97012SDavid du Colombier " shmid[m] = shmget(key[m], (size_t) qsize, 0600);", 86100d97012SDavid du Colombier " if (shmid[m] != -1) /* yes there is one; remove it */", 86200d97012SDavid du Colombier " { printf(\"cpu0: removing stale q%%d, status: %%d\\n\",", 86300d97012SDavid du Colombier " m, shmctl(shmid[m], IPC_RMID, NULL));", 86400d97012SDavid du Colombier " }", 86500d97012SDavid du Colombier " shmid[m] = shmget(key[m], (size_t) qsize, 0600|IPC_CREAT|IPC_EXCL);", 86600d97012SDavid du Colombier " memcnt += qsize;", 86700d97012SDavid du Colombier " } else /* workers attach */", 86800d97012SDavid du Colombier " { shmid[m] = shmget(key[m], (size_t) qsize, 0600);", 86900d97012SDavid du Colombier " /* never called, since we create shm *before* we fork */", 87000d97012SDavid du Colombier " }", 87100d97012SDavid du Colombier " if (shmid[m] == -1)", 87200d97012SDavid du Colombier " { perror(\"shmget shared queues\"); must_exit = 1; break;", 87300d97012SDavid du Colombier " }", 87400d97012SDavid du Colombier "", 87500d97012SDavid du Colombier " shared_mem[m] = (char *) shmat(shmid[m], (void *) 0, 0); /* attach */", 87600d97012SDavid du Colombier " if (shared_mem[m] == (char *) -1)", 87700d97012SDavid du Colombier " { fprintf(stderr, \"error: cannot attach shared wq %%d (%%d Mb)\\n\",", 87800d97012SDavid du Colombier " m+1, (int) (qsize/(1048576.)));", 87900d97012SDavid du Colombier " perror(\"shmat shared queues\"); must_exit = 1; break;", 88000d97012SDavid du Colombier " }", 88100d97012SDavid du Colombier "", 88200d97012SDavid du Colombier " m_workq[m] = (SM_frame *) shared_mem[m];", 88300d97012SDavid du Colombier " if (core_id == 0)", 88400d97012SDavid du Colombier " { int nframes = (m == NCORE) ? GN_FRAMES : LN_FRAMES;", 88500d97012SDavid du Colombier " for (n = 0; n < nframes; n++)", 88600d97012SDavid du Colombier " { m_workq[m][n].m_vsize = 0;", 88700d97012SDavid du Colombier " m_workq[m][n].m_boq = 0;", 88800d97012SDavid du Colombier " } } }", 88900d97012SDavid du Colombier "", 89000d97012SDavid du Colombier " if (must_exit)", 89100d97012SDavid du Colombier " { rm_shared_segments();", 89200d97012SDavid du Colombier " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");", 89300d97012SDavid du Colombier " pan_exit(1); /* calls cleanup_shm */", 89400d97012SDavid du Colombier " }", 89500d97012SDavid du Colombier "}", 89600d97012SDavid du Colombier "", 89700d97012SDavid du Colombier "static uchar *", 89800d97012SDavid du Colombier "prep_shmid_S(size_t n) /* either sets SS or H_tab, linux/cygwin */", 89900d97012SDavid du Colombier "{ char *rval;", 90000d97012SDavid du Colombier "#ifndef SEP_STATE", 90100d97012SDavid du Colombier " key_t key;", 90200d97012SDavid du Colombier "", 90300d97012SDavid du Colombier " if (verbose && core_id == 0)", 90400d97012SDavid du Colombier " {", 90500d97012SDavid du Colombier " #ifdef BITSTATE", 90600d97012SDavid du Colombier " printf(\"cpu0: step 1: allocate shared bitstate %%g Mb\\n\",", 90700d97012SDavid du Colombier " (double) n / (1048576.));", 90800d97012SDavid du Colombier " #else", 90900d97012SDavid du Colombier " printf(\"cpu0: step 1: allocate shared hastable %%g Mb\\n\",", 91000d97012SDavid du Colombier " (double) n / (1048576.));", 91100d97012SDavid du Colombier " #endif", 91200d97012SDavid du Colombier " }", 91300d97012SDavid du Colombier " #ifdef MEMLIM", /* memlim has a value */ 91400d97012SDavid du Colombier " if (memcnt + (double) n > memlim)", 91500d97012SDavid du Colombier " { printf(\"cpu0: S %%8g + %%d Kb exceeds memory limit of %%8g Mb\\n\",", 91600d97012SDavid du Colombier " memcnt/1024., (int) (n/1024), memlim/(1048576.));", 91700d97012SDavid du Colombier " printf(\"cpu0: insufficient memory -- aborting\\n\");", 91800d97012SDavid du Colombier " exit(1);", 91900d97012SDavid du Colombier " }", 92000d97012SDavid du Colombier " #endif", 92100d97012SDavid du Colombier "", 92200d97012SDavid du Colombier " key = ftok(PanSource, NCORE+2); /* different from queues */", 92300d97012SDavid du Colombier " if (key == -1)", 92400d97012SDavid du Colombier " { perror(\"ftok shared bitstate or hashtable\");", 92500d97012SDavid du Colombier " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");", 92600d97012SDavid du Colombier " pan_exit(1);", 92700d97012SDavid du Colombier " }", 92800d97012SDavid du Colombier "", 92900d97012SDavid du Colombier " if (core_id == 0) /* root */", 93000d97012SDavid du Colombier " { shmid_S = shmget(key, n, 0600);", 93100d97012SDavid du Colombier " if (shmid_S != -1)", 93200d97012SDavid du Colombier " { printf(\"cpu0: removing stale segment, status: %%d\\n\",", 93300d97012SDavid du Colombier " (int) shmctl(shmid_S, IPC_RMID, NULL));", 93400d97012SDavid du Colombier " }", 93500d97012SDavid du Colombier " shmid_S = shmget(key, n, 0600 | IPC_CREAT | IPC_EXCL);", 93600d97012SDavid du Colombier " memcnt += (double) n;", 93700d97012SDavid du Colombier " } else /* worker */", 93800d97012SDavid du Colombier " { shmid_S = shmget(key, n, 0600);", 93900d97012SDavid du Colombier " }", 94000d97012SDavid du Colombier " if (shmid_S == -1)", 94100d97012SDavid du Colombier " { perror(\"shmget shared bitstate or hashtable too large?\");", 94200d97012SDavid du Colombier " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");", 94300d97012SDavid du Colombier " pan_exit(1);", 94400d97012SDavid du Colombier " }", 94500d97012SDavid du Colombier "", 94600d97012SDavid du Colombier " rval = (char *) shmat(shmid_S, (void *) 0, 0); /* attach */", 94700d97012SDavid du Colombier " if ((char *) rval == (char *) -1)", 94800d97012SDavid du Colombier " { perror(\"shmat shared bitstate or hashtable\");", 94900d97012SDavid du Colombier " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");", 95000d97012SDavid du Colombier " pan_exit(1);", 95100d97012SDavid du Colombier " }", 95200d97012SDavid du Colombier "#else", 95300d97012SDavid du Colombier " rval = (char *) emalloc(n);", 95400d97012SDavid du Colombier "#endif", 95500d97012SDavid du Colombier " return (uchar *) rval;", 95600d97012SDavid du Colombier "}", 95700d97012SDavid du Colombier "", 95800d97012SDavid du Colombier "#define TRY_AGAIN 1", 95900d97012SDavid du Colombier "#define NOT_AGAIN 0", 96000d97012SDavid du Colombier "", 96100d97012SDavid du Colombier "static char shm_prep_result;", 96200d97012SDavid du Colombier "", 96300d97012SDavid du Colombier "static uchar *", 96400d97012SDavid du Colombier "prep_state_mem(size_t n) /* sets memory arena for states linux/cygwin */", 96500d97012SDavid du Colombier "{ char *rval;", 96600d97012SDavid du Colombier " key_t key;", 96700d97012SDavid du Colombier " static int cnt = 3; /* start larger than earlier ftok calls */", 96800d97012SDavid du Colombier "", 96900d97012SDavid du Colombier " shm_prep_result = NOT_AGAIN; /* default */", 97000d97012SDavid du Colombier " if (verbose && core_id == 0)", 97100d97012SDavid du Colombier " { printf(\"cpu0: step 2+: pre-allocate memory arena %%d of %%6.2g Mb\\n\",", 97200d97012SDavid du Colombier " cnt-3, (double) n / (1048576.));", 97300d97012SDavid du Colombier " }", 97400d97012SDavid du Colombier " #ifdef MEMLIM", 97500d97012SDavid du Colombier " if (memcnt + (double) n > memlim)", 97600d97012SDavid du Colombier " { printf(\"cpu0: error: M %%.0f + %%.0f Kb exceeds memory limit of %%.0f Mb\\n\",", 97700d97012SDavid du Colombier " memcnt/1024.0, (double) n/1024.0, memlim/(1048576.));", 97800d97012SDavid du Colombier " return NULL;", 97900d97012SDavid du Colombier " }", 98000d97012SDavid du Colombier " #endif", 98100d97012SDavid du Colombier "", 98200d97012SDavid du Colombier " key = ftok(PanSource, NCORE+cnt); cnt++;", /* starts at NCORE+3 */ 98300d97012SDavid du Colombier " if (key == -1)", 98400d97012SDavid du Colombier " { perror(\"ftok T\");", 98500d97012SDavid du Colombier " printf(\"pan: check './pan --' for usage details\\n\");", 98600d97012SDavid du Colombier " pan_exit(1);", 98700d97012SDavid du Colombier " }", 98800d97012SDavid du Colombier "", 98900d97012SDavid du Colombier " if (core_id == 0)", 99000d97012SDavid du Colombier " { shmid_M = shmget(key, n, 0600);", 99100d97012SDavid du Colombier " if (shmid_M != -1)", 99200d97012SDavid du Colombier " { printf(\"cpu0: removing stale memory segment %%d, status: %%d\\n\",", 99300d97012SDavid du Colombier " cnt-3, shmctl(shmid_M, IPC_RMID, NULL));", 99400d97012SDavid du Colombier " }", 99500d97012SDavid du Colombier " shmid_M = shmget(key, n, 0600 | IPC_CREAT | IPC_EXCL);", 99600d97012SDavid du Colombier " /* memcnt += (double) n; -- only amount actually used is counted */", 99700d97012SDavid du Colombier " } else", 99800d97012SDavid du Colombier " { shmid_M = shmget(key, n, 0600);", 99900d97012SDavid du Colombier " ", 100000d97012SDavid du Colombier " }", 100100d97012SDavid du Colombier " if (shmid_M == -1)", 100200d97012SDavid du Colombier " { if (verbose)", 100300d97012SDavid du Colombier " { printf(\"error: failed to get pool of shared memory %%d of %%.0f Mb\\n\",", 100400d97012SDavid du Colombier " cnt-3, ((double)n)/(1048576.));", 100500d97012SDavid du Colombier " perror(\"state mem\");", 100600d97012SDavid du Colombier " printf(\"pan: check './pan --' for usage details\\n\");", 100700d97012SDavid du Colombier " }", 100800d97012SDavid du Colombier " shm_prep_result = TRY_AGAIN;", 100900d97012SDavid du Colombier " return NULL;", 101000d97012SDavid du Colombier " }", 101100d97012SDavid du Colombier " rval = (char *) shmat(shmid_M, (void *) 0, 0); /* attach */", 101200d97012SDavid du Colombier "", 101300d97012SDavid du Colombier " if ((char *) rval == (char *) -1)", 101400d97012SDavid du Colombier " { printf(\"cpu%%d error: failed to attach pool of shared memory %%d of %%.0f Mb\\n\",", 101500d97012SDavid du Colombier " core_id, cnt-3, ((double)n)/(1048576.));", 101600d97012SDavid du Colombier " perror(\"state mem\");", 101700d97012SDavid du Colombier " return NULL;", 101800d97012SDavid du Colombier " }", 101900d97012SDavid du Colombier " return (uchar *) rval;", 102000d97012SDavid du Colombier "}", 102100d97012SDavid du Colombier "", 102200d97012SDavid du Colombier "void", 102300d97012SDavid du Colombier "init_HT(unsigned long n) /* cygwin/linux version */", 102400d97012SDavid du Colombier "{ volatile char *x;", 102500d97012SDavid du Colombier " double get_mem;", 102600d97012SDavid du Colombier "#ifndef SEP_STATE", 102700d97012SDavid du Colombier " volatile char *dc_mem_start;", 102800d97012SDavid du Colombier " double need_mem, got_mem = 0.;", 102900d97012SDavid du Colombier "#endif", 103000d97012SDavid du Colombier "", 103100d97012SDavid du Colombier "#ifdef SEP_STATE", 103200d97012SDavid du Colombier " #ifndef MEMLIM", 103300d97012SDavid du Colombier " if (verbose)", 103400d97012SDavid du Colombier " { printf(\"cpu0: steps 0,1: no -DMEMLIM set\\n\");", /* cannot happen */ 103500d97012SDavid du Colombier " }", 103600d97012SDavid du Colombier " #else", 103700d97012SDavid du Colombier " if (verbose)", 103800d97012SDavid du Colombier " { printf(\"cpu0: steps 0,1: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb)\\n\",", 103900d97012SDavid du Colombier " MEMLIM, ((double)n/(1048576.)), (((double) NCORE * LWQ_SIZE) + GWQ_SIZE) /(1048576.) );", 104000d97012SDavid du Colombier " }", 104100d97012SDavid du Colombier " #endif", 104200d97012SDavid du Colombier " get_mem = NCORE * sizeof(double) + (1 + CS_NR) * sizeof(void *) + 4*sizeof(void *) + 2*sizeof(double);", 104300d97012SDavid du Colombier " /* NCORE * is_alive + search_terminated + CS_NR * sh_lock + 6 gr vars */", 104400d97012SDavid du Colombier " get_mem += 4 * NCORE * sizeof(void *); /* prfree, prfull, prcnt, prmax */", 104500d97012SDavid du Colombier " #ifdef FULL_TRAIL", 104600d97012SDavid du Colombier " get_mem += (NCORE) * sizeof(Stack_Tree *); /* NCORE * stack_last */", 104700d97012SDavid du Colombier " #endif", 104800d97012SDavid du Colombier " x = (volatile char *) prep_state_mem((size_t) get_mem); /* work queues and basic structs */", 104900d97012SDavid du Colombier " shmid_X = (long) x;", 105000d97012SDavid du Colombier " if (x == NULL)", /* do not repeat for smaller sizes */ 105100d97012SDavid du Colombier " { printf(\"cpu0: could not allocate shared memory, see ./pan --\\n\");", 105200d97012SDavid du Colombier " exit(1);", 105300d97012SDavid du Colombier " }", 105400d97012SDavid du Colombier " search_terminated = (volatile unsigned int *) x; /* comes first */", 105500d97012SDavid du Colombier " x += sizeof(void *); /* maintain alignment */", 105600d97012SDavid du Colombier "", 105700d97012SDavid du Colombier " is_alive = (volatile double *) x;", 105800d97012SDavid du Colombier " x += NCORE * sizeof(double);", 105900d97012SDavid du Colombier "", 106000d97012SDavid du Colombier " sh_lock = (volatile int *) x;", 106100d97012SDavid du Colombier " x += CS_NR * sizeof(void *);", /* allow 1 word per entry */ 106200d97012SDavid du Colombier "", 106300d97012SDavid du Colombier " grfree = (volatile int *) x;", 106400d97012SDavid du Colombier " x += sizeof(void *);", 106500d97012SDavid du Colombier " grfull = (volatile int *) x;", 106600d97012SDavid du Colombier " x += sizeof(void *);", 106700d97012SDavid du Colombier " grcnt = (volatile int *) x;", 106800d97012SDavid du Colombier " x += sizeof(void *);", 106900d97012SDavid du Colombier " grmax = (volatile int *) x;", 107000d97012SDavid du Colombier " x += sizeof(void *);", 107100d97012SDavid du Colombier " prfree = (volatile int *) x;", 107200d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 107300d97012SDavid du Colombier " prfull = (volatile int *) x;", 107400d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 107500d97012SDavid du Colombier " prcnt = (volatile int *) x;", 107600d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 107700d97012SDavid du Colombier " prmax = (volatile int *) x;", 107800d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 107900d97012SDavid du Colombier " gr_readmiss = (volatile double *) x;", 108000d97012SDavid du Colombier " x += sizeof(double);", 108100d97012SDavid du Colombier " gr_writemiss = (volatile double *) x;", 108200d97012SDavid du Colombier " x += sizeof(double);", 108300d97012SDavid du Colombier "", 108400d97012SDavid du Colombier " #ifdef FULL_TRAIL", 108500d97012SDavid du Colombier " stack_last = (volatile Stack_Tree **) x;", 108600d97012SDavid du Colombier " x += NCORE * sizeof(Stack_Tree *);", 108700d97012SDavid du Colombier " #endif", 108800d97012SDavid du Colombier "", 108900d97012SDavid du Colombier " #ifndef BITSTATE", 1090*de2caf28SDavid du Colombier " H_tab = (H_el **) emalloc(n);", 109100d97012SDavid du Colombier " #endif", 109200d97012SDavid du Colombier "#else", 109300d97012SDavid du Colombier " #ifndef MEMLIM", 109400d97012SDavid du Colombier " #warning MEMLIM not set", /* cannot happen */ 109500d97012SDavid du Colombier " #define MEMLIM (2048)", 109600d97012SDavid du Colombier " #endif", 109700d97012SDavid du Colombier "", 109800d97012SDavid du Colombier " if (core_id == 0 && verbose)", 109900d97012SDavid du Colombier " { printf(\"cpu0: step 0: -DMEMLIM=%%d Mb minus hashtable+workqs (%%g + %%g Mb) leaves %%g Mb\\n\",", 110000d97012SDavid du Colombier " MEMLIM, ((double)n/(1048576.)), (NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.),", 110100d97012SDavid du Colombier " (memlim - memcnt - (double) n - (NCORE * LWQ_SIZE + GWQ_SIZE))/(1048576.));", 110200d97012SDavid du Colombier " }", 110300d97012SDavid du Colombier " #ifndef BITSTATE", 1104*de2caf28SDavid du Colombier " H_tab = (H_el **) prep_shmid_S((size_t) n); /* hash_table */", 110500d97012SDavid du Colombier " #endif", 110600d97012SDavid du Colombier " need_mem = memlim - memcnt - ((double) NCORE * LWQ_SIZE) - GWQ_SIZE;", 110700d97012SDavid du Colombier " if (need_mem <= 0.)", 110800d97012SDavid du Colombier " { Uerror(\"internal error -- shared state memory\");", 110900d97012SDavid du Colombier " }", 111000d97012SDavid du Colombier "", 111100d97012SDavid du Colombier " if (core_id == 0 && verbose)", 111200d97012SDavid du Colombier " { printf(\"cpu0: step 2: pre-allocate shared state memory %%g Mb\\n\",", 111300d97012SDavid du Colombier " need_mem/(1048576.));", 111400d97012SDavid du Colombier " }", 111500d97012SDavid du Colombier "#ifdef SEP_HEAP", 111600d97012SDavid du Colombier " SEG_SIZE = need_mem / NCORE;", 111700d97012SDavid du Colombier " if (verbose && core_id == 0)", 111800d97012SDavid du Colombier " { printf(\"cpu0: setting segsize to %%6g MB\\n\",", 111900d97012SDavid du Colombier " SEG_SIZE/(1048576.));", 112000d97012SDavid du Colombier " }", 112100d97012SDavid du Colombier " #if defined(CYGWIN) || defined(__CYGWIN__)", 112200d97012SDavid du Colombier " if (SEG_SIZE > 512.*1024.*1024.)", 112300d97012SDavid du Colombier " { printf(\"warning: reducing SEG_SIZE of %%g MB to 512MB (exceeds max for Cygwin)\\n\",", 112400d97012SDavid du Colombier " SEG_SIZE/(1024.*1024.));", 112500d97012SDavid du Colombier " SEG_SIZE = 512.*1024.*1024.;", 112600d97012SDavid du Colombier " }", 112700d97012SDavid du Colombier " #endif", 112800d97012SDavid du Colombier "#endif", 112900d97012SDavid du Colombier " mem_reserved = need_mem;", 113000d97012SDavid du Colombier " while (need_mem > 1024.)", 113100d97012SDavid du Colombier " { get_mem = need_mem;", 113200d97012SDavid du Colombier "shm_more:", 113300d97012SDavid du Colombier " if (get_mem > (double) SEG_SIZE)", 113400d97012SDavid du Colombier " { get_mem = (double) SEG_SIZE;", 113500d97012SDavid du Colombier " }", 113600d97012SDavid du Colombier " if (get_mem <= 0.0) break;", 113700d97012SDavid du Colombier "", 113800d97012SDavid du Colombier " /* for allocating states: */", 113900d97012SDavid du Colombier " x = dc_mem_start = (volatile char *) prep_state_mem((size_t) get_mem);", 114000d97012SDavid du Colombier " if (x == NULL)", 114100d97012SDavid du Colombier " { if (shm_prep_result == NOT_AGAIN", 114200d97012SDavid du Colombier " || first_pool != NULL", 114300d97012SDavid du Colombier " || SEG_SIZE < (16. * 1048576.))", 114400d97012SDavid du Colombier " { break;", 114500d97012SDavid du Colombier " }", 114600d97012SDavid du Colombier " SEG_SIZE /= 2.;", 114700d97012SDavid du Colombier " if (verbose)", 1148*de2caf28SDavid du Colombier " { printf(\"pan: lowered segsize to %%f\\n\", SEG_SIZE);", 114900d97012SDavid du Colombier " }", 115000d97012SDavid du Colombier " if (SEG_SIZE >= 1024.)", 115100d97012SDavid du Colombier " { goto shm_more;", /* always terminates */ 115200d97012SDavid du Colombier " }", 115300d97012SDavid du Colombier " break;", 115400d97012SDavid du Colombier " }", 115500d97012SDavid du Colombier "", 115600d97012SDavid du Colombier " need_mem -= get_mem;", 115700d97012SDavid du Colombier " got_mem += get_mem;", 115800d97012SDavid du Colombier " if (first_pool == NULL)", 115900d97012SDavid du Colombier " { search_terminated = (volatile unsigned int *) x; /* comes first */", 116000d97012SDavid du Colombier " x += sizeof(void *); /* maintain alignment */", 116100d97012SDavid du Colombier "", 116200d97012SDavid du Colombier " is_alive = (volatile double *) x;", 116300d97012SDavid du Colombier " x += NCORE * sizeof(double);", 116400d97012SDavid du Colombier "", 116500d97012SDavid du Colombier " sh_lock = (volatile int *) x;", 116600d97012SDavid du Colombier " x += CS_NR * sizeof(void *);", /* allow 1 word per entry */ 116700d97012SDavid du Colombier "", 116800d97012SDavid du Colombier " grfree = (volatile int *) x;", 116900d97012SDavid du Colombier " x += sizeof(void *);", 117000d97012SDavid du Colombier " grfull = (volatile int *) x;", 117100d97012SDavid du Colombier " x += sizeof(void *);", 117200d97012SDavid du Colombier " grcnt = (volatile int *) x;", 117300d97012SDavid du Colombier " x += sizeof(void *);", 117400d97012SDavid du Colombier " grmax = (volatile int *) x;", 117500d97012SDavid du Colombier " x += sizeof(void *);", 117600d97012SDavid du Colombier " prfree = (volatile int *) x;", 117700d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 117800d97012SDavid du Colombier " prfull = (volatile int *) x;", 117900d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 118000d97012SDavid du Colombier " prcnt = (volatile int *) x;", 118100d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 118200d97012SDavid du Colombier " prmax = (volatile int *) x;", 118300d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 118400d97012SDavid du Colombier " gr_readmiss = (volatile double *) x;", 118500d97012SDavid du Colombier " x += sizeof(double);", 118600d97012SDavid du Colombier " gr_writemiss = (volatile double *) x;", 118700d97012SDavid du Colombier " x += sizeof(double);", 118800d97012SDavid du Colombier " #ifdef FULL_TRAIL", 118900d97012SDavid du Colombier " stack_last = (volatile Stack_Tree **) x;", 119000d97012SDavid du Colombier " x += NCORE * sizeof(Stack_Tree *);", 119100d97012SDavid du Colombier " #endif", 119200d97012SDavid du Colombier " if (((long)x)&(sizeof(void *)-1)) /* 64-bit word alignment */", 119300d97012SDavid du Colombier " { x += sizeof(void *)-(((long)x)&(sizeof(void *)-1));", 119400d97012SDavid du Colombier " }", 119500d97012SDavid du Colombier "", 119600d97012SDavid du Colombier " #ifdef COLLAPSE", 119700d97012SDavid du Colombier " ncomps = (unsigned long *) x;", 119800d97012SDavid du Colombier " x += (256+2) * sizeof(unsigned long);", 119900d97012SDavid du Colombier " #endif", 120000d97012SDavid du Colombier " }", 120100d97012SDavid du Colombier "", 120200d97012SDavid du Colombier " dc_shared = (sh_Allocater *) x; /* must be in shared memory */", 120300d97012SDavid du Colombier " x += sizeof(sh_Allocater);", 120400d97012SDavid du Colombier "", 120500d97012SDavid du Colombier " if (core_id == 0) /* root only */", 120600d97012SDavid du Colombier " { dc_shared->dc_id = shmid_M;", 120700d97012SDavid du Colombier " dc_shared->dc_start = dc_mem_start;", 120800d97012SDavid du Colombier " dc_shared->dc_arena = x;", 120900d97012SDavid du Colombier " dc_shared->pattern = 1234567; /* protection */", 121000d97012SDavid du Colombier " dc_shared->dc_size = (long) get_mem - (long) (x - dc_mem_start);", 121100d97012SDavid du Colombier " dc_shared->nxt = (long) 0;", 121200d97012SDavid du Colombier "", 121300d97012SDavid du Colombier " if (last_pool == NULL)", 121400d97012SDavid du Colombier " { first_pool = last_pool = dc_shared;", 121500d97012SDavid du Colombier " } else", 121600d97012SDavid du Colombier " { last_pool->nxt = dc_shared;", 121700d97012SDavid du Colombier " last_pool = dc_shared;", 121800d97012SDavid du Colombier " }", 121900d97012SDavid du Colombier " } else if (first_pool == NULL)", 122000d97012SDavid du Colombier " { first_pool = dc_shared;", 122100d97012SDavid du Colombier " } }", 122200d97012SDavid du Colombier "", 122300d97012SDavid du Colombier " if (need_mem > 1024.)", 122400d97012SDavid du Colombier " { printf(\"cpu0: could allocate only %%g Mb of shared memory (wanted %%g more)\\n\",", 122500d97012SDavid du Colombier " got_mem/(1048576.), need_mem/(1048576.));", 122600d97012SDavid du Colombier " }", 122700d97012SDavid du Colombier "", 122800d97012SDavid du Colombier " if (!first_pool)", 122900d97012SDavid du Colombier " { printf(\"cpu0: insufficient memory -- aborting.\\n\");", 123000d97012SDavid du Colombier " exit(1);", 123100d97012SDavid du Colombier " }", 123200d97012SDavid du Colombier " /* we are still single-threaded at this point, with core_id 0 */", 123300d97012SDavid du Colombier " dc_shared = first_pool;", 123400d97012SDavid du Colombier "", 123500d97012SDavid du Colombier "#endif", /* !SEP_STATE */ 123600d97012SDavid du Colombier "}", 123700d97012SDavid du Colombier "", 123800d97012SDavid du Colombier "void", 123900d97012SDavid du Colombier "cleanup_shm(int val)", 124000d97012SDavid du Colombier "{ volatile sh_Allocater *nxt_pool;", 124100d97012SDavid du Colombier " unsigned long cnt = 0;", 124200d97012SDavid du Colombier " int m;", 124300d97012SDavid du Colombier "", 124400d97012SDavid du Colombier " if (nibis != 0)", 124500d97012SDavid du Colombier " { printf(\"cpu%%d: Redundant call to cleanup_shm(%%d)\\n\", core_id, val);", 124600d97012SDavid du Colombier " return;", 124700d97012SDavid du Colombier " } else", 124800d97012SDavid du Colombier " { nibis = 1;", 124900d97012SDavid du Colombier " }", 125000d97012SDavid du Colombier " if (search_terminated != NULL)", 125100d97012SDavid du Colombier " { *search_terminated |= 16; /* cleanup_shm */", 125200d97012SDavid du Colombier " }", 125300d97012SDavid du Colombier "", 125400d97012SDavid du Colombier " for (m = 0; m < NR_QS; m++)", 125500d97012SDavid du Colombier " { if (shmdt((void *) shared_mem[m]) > 0)", 125600d97012SDavid du Colombier " { perror(\"shmdt detaching from shared queues\");", 125700d97012SDavid du Colombier " } }", 125800d97012SDavid du Colombier "", 125900d97012SDavid du Colombier "#ifdef SEP_STATE", 126000d97012SDavid du Colombier " if (shmdt((void *) shmid_X) != 0)", 126100d97012SDavid du Colombier " { perror(\"shmdt detaching from shared state memory\");", 126200d97012SDavid du Colombier " }", 126300d97012SDavid du Colombier "#else", 126400d97012SDavid du Colombier " #ifdef BITSTATE", 126500d97012SDavid du Colombier " if (SS > 0 && shmdt((void *) SS) != 0)", 126600d97012SDavid du Colombier " { if (verbose)", 126700d97012SDavid du Colombier " { perror(\"shmdt detaching from shared bitstate arena\");", 126800d97012SDavid du Colombier " } }", 126900d97012SDavid du Colombier " #else", 127000d97012SDavid du Colombier " if (core_id == 0)", 127100d97012SDavid du Colombier " { /* before detaching: */", 127200d97012SDavid du Colombier " for (nxt_pool = dc_shared; nxt_pool != NULL; nxt_pool = nxt_pool->nxt)", 127300d97012SDavid du Colombier " { cnt += nxt_pool->dc_size;", 127400d97012SDavid du Colombier " }", 127500d97012SDavid du Colombier " if (verbose)", 127600d97012SDavid du Colombier " { printf(\"cpu0: done, %%ld Mb of shared state memory left\\n\",", 127700d97012SDavid du Colombier " cnt / (long)(1048576));", 127800d97012SDavid du Colombier " } }", 127900d97012SDavid du Colombier "", 128000d97012SDavid du Colombier " if (shmdt((void *) H_tab) != 0)", 128100d97012SDavid du Colombier " { perror(\"shmdt detaching from shared hashtable\");", 128200d97012SDavid du Colombier " }", 128300d97012SDavid du Colombier "", 128400d97012SDavid du Colombier " for (last_pool = first_pool; last_pool != NULL; last_pool = nxt_pool)", 128500d97012SDavid du Colombier " { nxt_pool = last_pool->nxt;", 128600d97012SDavid du Colombier " if (shmdt((void *) last_pool->dc_start) != 0)", 128700d97012SDavid du Colombier " { perror(\"shmdt detaching from shared state memory\");", 128800d97012SDavid du Colombier " } }", 128900d97012SDavid du Colombier " first_pool = last_pool = NULL; /* precaution */", 129000d97012SDavid du Colombier " #endif", 129100d97012SDavid du Colombier "#endif", 129200d97012SDavid du Colombier " /* detached from shared memory - so cannot use cpu_printf */", 129300d97012SDavid du Colombier " if (verbose)", 129400d97012SDavid du Colombier " { printf(\"cpu%%d: done -- got %%ld states from queue\\n\",", 129500d97012SDavid du Colombier " core_id, nstates_get);", 129600d97012SDavid du Colombier " }", 129700d97012SDavid du Colombier "}", 129800d97012SDavid du Colombier "", 129900d97012SDavid du Colombier "extern void give_up(int);", 130000d97012SDavid du Colombier "extern void Read_Queue(int);", 130100d97012SDavid du Colombier "", 130200d97012SDavid du Colombier "void", 130300d97012SDavid du Colombier "mem_get(void)", 130400d97012SDavid du Colombier "{ SM_frame *f;", 130500d97012SDavid du Colombier " int is_parent;", 130600d97012SDavid du Colombier "", 130700d97012SDavid du Colombier "#if defined(MA) && !defined(SEP_STATE)", 130800d97012SDavid du Colombier " #error MA without SEP_STATE is not supported with multi-core", 130900d97012SDavid du Colombier "#endif", 131000d97012SDavid du Colombier "#ifdef BFS", 1311*de2caf28SDavid du Colombier " #error instead of -DNCORE -DBFS use -DBFS_PAR", 131200d97012SDavid du Colombier "#endif", 131300d97012SDavid du Colombier "#ifdef SC", 131400d97012SDavid du Colombier " #error SC is not supported with multi-core", 131500d97012SDavid du Colombier "#endif", 131600d97012SDavid du Colombier " init_shm(); /* we are single threaded when this starts */", 131700d97012SDavid du Colombier "", 131800d97012SDavid du Colombier " if (core_id == 0 && verbose)", 131900d97012SDavid du Colombier " { printf(\"cpu0: step 4: calling fork()\\n\");", 132000d97012SDavid du Colombier " }", 132100d97012SDavid du Colombier " fflush(stdout);", 132200d97012SDavid du Colombier "", 132300d97012SDavid du Colombier "/* if NCORE > 1 the child or the parent should fork N-1 more times", 132400d97012SDavid du Colombier " * the parent is the only process with core_id == 0 and is_parent > 0", 132500d97012SDavid du Colombier " * the workers have is_parent = 0 and core_id = 1..NCORE-1", 132600d97012SDavid du Colombier " */", 132700d97012SDavid du Colombier " if (core_id == 0)", 132800d97012SDavid du Colombier " { worker_pids[0] = getpid(); /* for completeness */", 132900d97012SDavid du Colombier " while (++core_id < NCORE) /* first worker sees core_id = 1 */", 133000d97012SDavid du Colombier " { is_parent = fork();", 133100d97012SDavid du Colombier " if (is_parent == -1)", 133200d97012SDavid du Colombier " { Uerror(\"fork failed\");", 133300d97012SDavid du Colombier " }", 133400d97012SDavid du Colombier " if (is_parent == 0) /* this is a worker process */", 133500d97012SDavid du Colombier " { if (proxy_pid == core_id) /* always non-zero */", 133600d97012SDavid du Colombier " { start_proxy(\"-r\", 0); /* no return */", 133700d97012SDavid du Colombier " }", 133800d97012SDavid du Colombier " goto adapt; /* root process continues spawning */", 133900d97012SDavid du Colombier " }", 134000d97012SDavid du Colombier " worker_pids[core_id] = is_parent;", 134100d97012SDavid du Colombier " }", 134200d97012SDavid du Colombier " /* note that core_id is now NCORE */", 134300d97012SDavid du Colombier " if (proxy_pid > 0 && proxy_pid < NCORE)", /* add send-half of proxy */ 134400d97012SDavid du Colombier " { proxy_pid_snd = fork();", 134500d97012SDavid du Colombier " if (proxy_pid_snd == -1)", 134600d97012SDavid du Colombier " { Uerror(\"proxy fork failed\");", 134700d97012SDavid du Colombier " }", 134800d97012SDavid du Colombier " if (proxy_pid_snd == 0)", 134900d97012SDavid du Colombier " { start_proxy(\"-s\", worker_pids[proxy_pid]); /* no return */", 135000d97012SDavid du Colombier " } } /* else continue */", 135100d97012SDavid du Colombier 135200d97012SDavid du Colombier " if (is_parent > 0)", 135300d97012SDavid du Colombier " { core_id = 0; /* reset core_id for root process */", 135400d97012SDavid du Colombier " }", 135500d97012SDavid du Colombier " } else /* worker */", 135600d97012SDavid du Colombier " { static char db0[16]; /* good for up to 10^6 cores */", 135700d97012SDavid du Colombier " static char db1[16];", 135800d97012SDavid du Colombier "adapt: tprefix = db0; sprefix = db1;", 135900d97012SDavid du Colombier " sprintf(tprefix, \"cpu%%d_trail\", core_id);", 136000d97012SDavid du Colombier " sprintf(sprefix, \"cpu%%d_rst\", core_id);", 136100d97012SDavid du Colombier " memcnt = 0; /* count only additionally allocated memory */", 136200d97012SDavid du Colombier " }", 136300d97012SDavid du Colombier " signal(SIGINT, give_up);", 136400d97012SDavid du Colombier "", 136500d97012SDavid du Colombier " if (proxy_pid == 0) /* not in a cluster setup, pan_proxy must attach */", 136600d97012SDavid du Colombier " { rm_shared_segments(); /* mark all shared segments for removal on exit */", 136700d97012SDavid du Colombier " }", /* doing it early means less chance of being unable to do this */ 136800d97012SDavid du Colombier " if (verbose)", 136900d97012SDavid du Colombier " { cpu_printf(\"starting core_id %%d -- pid %%d\\n\", core_id, getpid());", 137000d97012SDavid du Colombier " }", 137100d97012SDavid du Colombier 137200d97012SDavid du Colombier "#if defined(SEP_HEAP) && !defined(SEP_STATE)", /* set my_heap and adjust dc_shared */ 137300d97012SDavid du Colombier " { int i;", 137400d97012SDavid du Colombier " volatile sh_Allocater *ptr;", 137500d97012SDavid du Colombier " ptr = first_pool;", 137600d97012SDavid du Colombier " for (i = 0; i < NCORE && ptr != NULL; i++)", 137700d97012SDavid du Colombier " { if (i == core_id)", 137800d97012SDavid du Colombier " { my_heap = (char *) ptr->dc_arena;", 137900d97012SDavid du Colombier " my_size = (long) ptr->dc_size;", 138000d97012SDavid du Colombier " if (verbose)", 138100d97012SDavid du Colombier " cpu_printf(\"local heap %%ld MB\\n\", my_size/(1048576));", 138200d97012SDavid du Colombier " break;", 138300d97012SDavid du Colombier " }", 138400d97012SDavid du Colombier " ptr = ptr->nxt; /* local */", 138500d97012SDavid du Colombier " }", 138600d97012SDavid du Colombier " if (my_heap == NULL)", 138700d97012SDavid du Colombier " { printf(\"cpu%%d: no local heap\\n\", core_id);", 138800d97012SDavid du Colombier " pan_exit(1);", 138900d97012SDavid du Colombier " } /* else */", 139000d97012SDavid du Colombier " #if defined(CYGWIN) || defined(__CYGWIN__)", 139100d97012SDavid du Colombier " ptr = first_pool;", 139200d97012SDavid du Colombier " for (i = 0; i < NCORE && ptr != NULL; i++)", 139300d97012SDavid du Colombier " { ptr = ptr->nxt; /* local */", 139400d97012SDavid du Colombier " }", 139500d97012SDavid du Colombier " dc_shared = ptr; /* any remainder */", 139600d97012SDavid du Colombier " #else", 139700d97012SDavid du Colombier " dc_shared = NULL; /* used all mem for local heaps */", 139800d97012SDavid du Colombier " #endif", 139900d97012SDavid du Colombier " }", 140000d97012SDavid du Colombier "#endif", 140100d97012SDavid du Colombier 140200d97012SDavid du Colombier " if (core_id == 0 && !remote_party)", 140300d97012SDavid du Colombier " { new_state(); /* cpu0 explores root */", 140400d97012SDavid du Colombier " if (verbose)", 140500d97012SDavid du Colombier " cpu_printf(\"done with 1st dfs, nstates %%g (put %%d states), read q\\n\",", 140600d97012SDavid du Colombier " nstates, nstates_put);", 140700d97012SDavid du Colombier " dfs_phase2 = 1;", 140800d97012SDavid du Colombier " }", 140900d97012SDavid du Colombier " Read_Queue(core_id); /* all cores */", 141000d97012SDavid du Colombier "", 141100d97012SDavid du Colombier " if (verbose)", 141200d97012SDavid du Colombier " { cpu_printf(\"put %%6d states into queue -- got %%6d\\n\",", 141300d97012SDavid du Colombier " nstates_put, nstates_get);", 141400d97012SDavid du Colombier " }", 141500d97012SDavid du Colombier " if (proxy_pid != 0)", 141600d97012SDavid du Colombier " { rm_shared_segments();", 141700d97012SDavid du Colombier " }", 141800d97012SDavid du Colombier " done = 1;", 141900d97012SDavid du Colombier " wrapup();", 142000d97012SDavid du Colombier " exit(0);", 142100d97012SDavid du Colombier "}", 142200d97012SDavid du Colombier "", 142300d97012SDavid du Colombier "#else", 142400d97012SDavid du Colombier "int unpack_state(SM_frame *, int);", 142500d97012SDavid du Colombier "#endif", 142600d97012SDavid du Colombier "", 1427*de2caf28SDavid du Colombier "H_el *", 142800d97012SDavid du Colombier "grab_shared(int n)", 142900d97012SDavid du Colombier "{", 143000d97012SDavid du Colombier "#ifndef SEP_STATE", 143100d97012SDavid du Colombier " char *rval = (char *) 0;", 143200d97012SDavid du Colombier "", 143300d97012SDavid du Colombier " if (n == 0)", 143400d97012SDavid du Colombier " { printf(\"cpu%%d: grab shared zero\\n\", core_id); fflush(stdout);", 1435*de2caf28SDavid du Colombier " return (H_el *) rval;", 143600d97012SDavid du Colombier " } else if (n&(sizeof(void *)-1))", 143700d97012SDavid du Colombier " { n += sizeof(void *)-(n&(sizeof(void *)-1)); /* alignment */", 143800d97012SDavid du Colombier " }", 143900d97012SDavid du Colombier "", 144000d97012SDavid du Colombier "#ifdef SEP_HEAP", 144100d97012SDavid du Colombier " /* no locking */", 144200d97012SDavid du Colombier " if (my_heap != NULL && my_size > n)", 144300d97012SDavid du Colombier " { rval = my_heap;", 144400d97012SDavid du Colombier " my_heap += n;", 144500d97012SDavid du Colombier " my_size -= n;", 144600d97012SDavid du Colombier " goto done;", 144700d97012SDavid du Colombier " }", 144800d97012SDavid du Colombier "#endif", 144900d97012SDavid du Colombier "", 145000d97012SDavid du Colombier " if (!dc_shared)", 145100d97012SDavid du Colombier " { sudden_stop(\"pan: out of memory\");", 145200d97012SDavid du Colombier " }", 145300d97012SDavid du Colombier "", 145400d97012SDavid du Colombier " /* another lock is always already in effect when this is called */", 145500d97012SDavid du Colombier " /* but not always the same lock -- i.e., on different parts of the hashtable */", 145600d97012SDavid du Colombier " enter_critical(GLOBAL_LOCK); /* this must be independently mutex */", 145700d97012SDavid du Colombier "#if defined(SEP_HEAP) && !defined(WIN32) && !defined(WIN64)", 145800d97012SDavid du Colombier " { static int noted = 0;", 145900d97012SDavid du Colombier " if (!noted)", 146000d97012SDavid du Colombier " { noted = 1;", 146100d97012SDavid du Colombier " printf(\"cpu%%d: global heap has %%ld bytes left, needed %%d\\n\",", 146200d97012SDavid du Colombier " core_id, dc_shared?dc_shared->dc_size:0, n);", 146300d97012SDavid du Colombier " } }", 146400d97012SDavid du Colombier "#endif", 146500d97012SDavid du Colombier "#if 0", /* for debugging */ 146600d97012SDavid du Colombier " if (dc_shared->pattern != 1234567)", 146700d97012SDavid du Colombier " { leave_critical(GLOBAL_LOCK);", 146800d97012SDavid du Colombier " Uerror(\"overrun -- memory corruption\");", 146900d97012SDavid du Colombier " }", 147000d97012SDavid du Colombier "#endif", 147100d97012SDavid du Colombier " if (dc_shared->dc_size < n)", 147200d97012SDavid du Colombier " { if (verbose)", 147300d97012SDavid du Colombier " { printf(\"Next Pool %%g Mb + %%d\\n\", memcnt/(1048576.), n);", 147400d97012SDavid du Colombier " }", 147500d97012SDavid du Colombier " if (dc_shared->nxt == NULL", 147600d97012SDavid du Colombier " || dc_shared->nxt->dc_arena == NULL", 147700d97012SDavid du Colombier " || dc_shared->nxt->dc_size < n)", 147800d97012SDavid du Colombier " { printf(\"cpu%%d: memcnt %%g Mb + wanted %%d bytes more\\n\",", 147900d97012SDavid du Colombier " core_id, memcnt / (1048576.), n);", 148000d97012SDavid du Colombier " leave_critical(GLOBAL_LOCK);", 148100d97012SDavid du Colombier " sudden_stop(\"out of memory -- aborting\");", 148200d97012SDavid du Colombier " wrapup(); /* exits */", 148300d97012SDavid du Colombier " } else", 148400d97012SDavid du Colombier " { dc_shared = (sh_Allocater *) dc_shared->nxt;", 148500d97012SDavid du Colombier " } }", 148600d97012SDavid du Colombier "", 148700d97012SDavid du Colombier " rval = (char *) dc_shared->dc_arena;", 148800d97012SDavid du Colombier " dc_shared->dc_arena += n;", 148900d97012SDavid du Colombier " dc_shared->dc_size -= (long) n;", 149000d97012SDavid du Colombier "#if 0", 149100d97012SDavid du Colombier " if (VVERBOSE)", 149200d97012SDavid du Colombier " printf(\"cpu%%d grab shared (%%d bytes) -- %%ld left\\n\",", 149300d97012SDavid du Colombier " core_id, n, dc_shared->dc_size);", 149400d97012SDavid du Colombier "#endif", 149500d97012SDavid du Colombier " leave_critical(GLOBAL_LOCK);", 149600d97012SDavid du Colombier "done:", 149700d97012SDavid du Colombier " memset(rval, 0, n);", 149800d97012SDavid du Colombier " memcnt += (double) n;", 149900d97012SDavid du Colombier "", 1500*de2caf28SDavid du Colombier " return (H_el *) rval;", 150100d97012SDavid du Colombier "#else", 1502*de2caf28SDavid du Colombier " return (H_el *) emalloc(n);", 150300d97012SDavid du Colombier "#endif", 150400d97012SDavid du Colombier "}", 150500d97012SDavid du Colombier "", 150600d97012SDavid du Colombier "SM_frame *", 150700d97012SDavid du Colombier "Get_Full_Frame(int n)", 150800d97012SDavid du Colombier "{ SM_frame *f;", 150900d97012SDavid du Colombier " double cnt_start = frame_wait;", 151000d97012SDavid du Colombier "", 151100d97012SDavid du Colombier " f = &m_workq[n][prfull[n]];", 151200d97012SDavid du Colombier " while (f->m_vsize == 0) /* await full slot LOCK : full frame */", 151300d97012SDavid du Colombier " { iam_alive();", 151400d97012SDavid du Colombier "#ifndef NGQ", 151500d97012SDavid du Colombier " #ifndef SAFETY", 151600d97012SDavid du Colombier " if (!a_cycles || core_id != 0)", 151700d97012SDavid du Colombier " #endif", 151800d97012SDavid du Colombier " if (*grcnt > 0) /* accessed outside lock, but safe even if wrong */", 151900d97012SDavid du Colombier " { enter_critical(GQ_RD); /* gq - read access */", 152000d97012SDavid du Colombier " if (*grcnt > 0) /* could have changed */", 152100d97012SDavid du Colombier " { f = &m_workq[NCORE][*grfull]; /* global q */", 152200d97012SDavid du Colombier " if (f->m_vsize == 0)", 152300d97012SDavid du Colombier " { /* writer is still filling the slot */", 152400d97012SDavid du Colombier " *gr_writemiss++;", 152500d97012SDavid du Colombier " f = &m_workq[n][prfull[n]]; /* reset */", 152600d97012SDavid du Colombier " } else", 152700d97012SDavid du Colombier " { *grfull = (*grfull+1) %% (GN_FRAMES);", 152800d97012SDavid du Colombier " enter_critical(GQ_WR);", 152900d97012SDavid du Colombier " *grcnt = *grcnt - 1;", 153000d97012SDavid du Colombier " leave_critical(GQ_WR);", 153100d97012SDavid du Colombier " leave_critical(GQ_RD);", 153200d97012SDavid du Colombier " return f;", 153300d97012SDavid du Colombier " } }", 153400d97012SDavid du Colombier " leave_critical(GQ_RD);", 153500d97012SDavid du Colombier " }", 153600d97012SDavid du Colombier "#endif", 153700d97012SDavid du Colombier " if (frame_wait++ - cnt_start > Delay)", 153800d97012SDavid du Colombier " { if (0)", /* too frequent to enable this one */ 153900d97012SDavid du Colombier " { cpu_printf(\"timeout on q%%d -- %%u -- query %%d\\n\",", 154000d97012SDavid du Colombier " n, f, query_in_progress);", 154100d97012SDavid du Colombier " }", 154200d97012SDavid du Colombier " return (SM_frame *) 0; /* timeout */", 154300d97012SDavid du Colombier " } }", 154400d97012SDavid du Colombier " iam_alive();", 154500d97012SDavid du Colombier " if (VVERBOSE) cpu_printf(\"got frame from q%%d\\n\", n);", 154600d97012SDavid du Colombier " prfull[n] = (prfull[n] + 1) %% (LN_FRAMES);", 154700d97012SDavid du Colombier " enter_critical(QLOCK(n));", 154800d97012SDavid du Colombier " prcnt[n]--; /* lock out increments */", 154900d97012SDavid du Colombier " leave_critical(QLOCK(n));", 155000d97012SDavid du Colombier " return f;", 155100d97012SDavid du Colombier "}", 155200d97012SDavid du Colombier "", 155300d97012SDavid du Colombier "SM_frame *", 155400d97012SDavid du Colombier "Get_Free_Frame(int n)", 155500d97012SDavid du Colombier "{ SM_frame *f;", 155600d97012SDavid du Colombier " double cnt_start = free_wait;", 155700d97012SDavid du Colombier "", 155800d97012SDavid du Colombier " if (VVERBOSE) { cpu_printf(\"get free frame from q%%d\\n\", n); }", 155900d97012SDavid du Colombier "", 156000d97012SDavid du Colombier " if (n == NCORE) /* global q */", 156100d97012SDavid du Colombier " { f = &(m_workq[n][lrfree]);", 156200d97012SDavid du Colombier " } else", 156300d97012SDavid du Colombier " { f = &(m_workq[n][prfree[n]]);", 156400d97012SDavid du Colombier " }", 156500d97012SDavid du Colombier " while (f->m_vsize != 0) /* await free slot LOCK : free slot */", 156600d97012SDavid du Colombier " { iam_alive();", 156700d97012SDavid du Colombier " if (free_wait++ - cnt_start > OneSecond)", 156800d97012SDavid du Colombier " { if (verbose)", 156900d97012SDavid du Colombier " { cpu_printf(\"timeout waiting for free slot q%%d\\n\", n);", 157000d97012SDavid du Colombier " }", 157100d97012SDavid du Colombier " cnt_start = free_wait;", 157200d97012SDavid du Colombier " if (someone_crashed(1))", 157300d97012SDavid du Colombier " { printf(\"cpu%%d: search terminated\\n\", core_id);", 157400d97012SDavid du Colombier " sudden_stop(\"get free frame\");", 157500d97012SDavid du Colombier " pan_exit(1);", 157600d97012SDavid du Colombier " } } }", 157700d97012SDavid du Colombier " if (n != NCORE)", 157800d97012SDavid du Colombier " { prfree[n] = (prfree[n] + 1) %% (LN_FRAMES);", 157900d97012SDavid du Colombier " enter_critical(QLOCK(n));", 158000d97012SDavid du Colombier " prcnt[n]++; /* lock out decrements */", 158100d97012SDavid du Colombier " if (prmax[n] < prcnt[n])", 158200d97012SDavid du Colombier " { prmax[n] = prcnt[n];", 158300d97012SDavid du Colombier " }", 158400d97012SDavid du Colombier " leave_critical(QLOCK(n));", 158500d97012SDavid du Colombier " }", 158600d97012SDavid du Colombier " return f;", 158700d97012SDavid du Colombier "}", 158800d97012SDavid du Colombier "", 158900d97012SDavid du Colombier "#ifndef NGQ", 159000d97012SDavid du Colombier "int", 159100d97012SDavid du Colombier "GlobalQ_HasRoom(void)", 159200d97012SDavid du Colombier "{ int rval = 0;", 159300d97012SDavid du Colombier "", 159400d97012SDavid du Colombier " gq_tries++;", 159500d97012SDavid du Colombier " if (*grcnt < GN_FRAMES) /* there seems to be room */", 159600d97012SDavid du Colombier " { enter_critical(GQ_WR); /* gq write access */", 159700d97012SDavid du Colombier " if (*grcnt < GN_FRAMES)", 159800d97012SDavid du Colombier " { if (m_workq[NCORE][*grfree].m_vsize != 0)", 159900d97012SDavid du Colombier " { /* can happen if reader is slow emptying slot */", 160000d97012SDavid du Colombier " *gr_readmiss++;", 1601*de2caf28SDavid du Colombier " goto out; /* don't wait: release lock and return */", 160200d97012SDavid du Colombier " }", 160300d97012SDavid du Colombier " lrfree = *grfree; /* Get_Free_Frame use lrfree in this mode */", 160400d97012SDavid du Colombier " *grfree = (*grfree + 1) %% GN_FRAMES;", /* next process looks at next slot */ 160500d97012SDavid du Colombier " *grcnt = *grcnt + 1; /* count nr of slots filled -- no additional lock needed */", 160600d97012SDavid du Colombier " if (*grmax < *grcnt) *grmax = *grcnt;", 160700d97012SDavid du Colombier " leave_critical(GQ_WR); /* for short lock duration */", 160800d97012SDavid du Colombier " gq_hasroom++;", 160900d97012SDavid du Colombier " mem_put(NCORE); /* copy state into reserved slot */", 1610*de2caf28SDavid du Colombier " rval = 1; /* successful handoff */", 161100d97012SDavid du Colombier " } else", 161200d97012SDavid du Colombier " { gq_hasnoroom++;", 161300d97012SDavid du Colombier "out: leave_critical(GQ_WR);", /* should be rare */ 161400d97012SDavid du Colombier " } }", 161500d97012SDavid du Colombier " return rval;", 161600d97012SDavid du Colombier "}", 161700d97012SDavid du Colombier "#endif", 161800d97012SDavid du Colombier "", 161900d97012SDavid du Colombier "int", 162000d97012SDavid du Colombier "unpack_state(SM_frame *f, int from_q)", 162100d97012SDavid du Colombier "{ int i, j;", 1622*de2caf28SDavid du Colombier " static H_el D_State;", 162300d97012SDavid du Colombier "", 162400d97012SDavid du Colombier " if (f->m_vsize > 0)", 162500d97012SDavid du Colombier " { boq = f->m_boq;", 162600d97012SDavid du Colombier " if (boq > 256)", 162700d97012SDavid du Colombier " { cpu_printf(\"saw control %%d, expected state\\n\", boq);", 162800d97012SDavid du Colombier " return 0;", 162900d97012SDavid du Colombier " }", 163000d97012SDavid du Colombier " vsize = f->m_vsize;", 163100d97012SDavid du Colombier "correct:", 163200d97012SDavid du Colombier " memcpy((uchar *) &now, (uchar *) f->m_now, vsize);", 1633*de2caf28SDavid du Colombier " #if !defined(NOCOMP) && !defined(HC)", 163400d97012SDavid du Colombier " for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)", 1635*de2caf28SDavid du Colombier " { Mask[i] = (f->m_mask[i/8] & (1<<j)) ? 1 : 0;", 163600d97012SDavid du Colombier " }", 1637*de2caf28SDavid du Colombier " #endif", 163800d97012SDavid du Colombier " if (now._nr_pr > 0)", 163900d97012SDavid du Colombier " { memcpy((uchar *) proc_offset, (uchar *) f->m_p_offset, now._nr_pr * sizeof(OFFT));", 164000d97012SDavid du Colombier " memcpy((uchar *) proc_skip, (uchar *) f->m_p_skip, now._nr_pr * sizeof(uchar));", 164100d97012SDavid du Colombier " }", 164200d97012SDavid du Colombier " if (now._nr_qs > 0)", 164300d97012SDavid du Colombier " { memcpy((uchar *) q_offset, (uchar *) f->m_q_offset, now._nr_qs * sizeof(OFFT));", 164400d97012SDavid du Colombier " memcpy((uchar *) q_skip, (uchar *) f->m_q_skip, now._nr_qs * sizeof(uchar));", 164500d97012SDavid du Colombier " }", 164600d97012SDavid du Colombier "#ifndef NOVSZ", 164700d97012SDavid du Colombier " if (vsize != now._vsz)", 164800d97012SDavid du Colombier " { cpu_printf(\"vsize %%d != now._vsz %%d (type %%d) %%d\\n\",", 164900d97012SDavid du Colombier " vsize, now._vsz, f->m_boq, f->m_vsize);", 165000d97012SDavid du Colombier " vsize = now._vsz;", 165100d97012SDavid du Colombier " goto correct; /* rare event: a race */", 165200d97012SDavid du Colombier " }", 165300d97012SDavid du Colombier "#endif", 165400d97012SDavid du Colombier " hmax = max(hmax, vsize);", 165500d97012SDavid du Colombier "", 165600d97012SDavid du Colombier " if (f != &cur_Root)", 165700d97012SDavid du Colombier " { memcpy((uchar *) &cur_Root, (uchar *) f, sizeof(SM_frame));", 165800d97012SDavid du Colombier " }", 165900d97012SDavid du Colombier "", 166000d97012SDavid du Colombier " if (((now._a_t) & 1) == 1) /* i.e., when starting nested DFS */", 166100d97012SDavid du Colombier " { A_depth = depthfound = 0;", 166200d97012SDavid du Colombier " memcpy((uchar *)&A_Root, (uchar *)&now, vsize);", 166300d97012SDavid du Colombier " }", 166400d97012SDavid du Colombier " nr_handoffs = f->nr_handoffs;", 166500d97012SDavid du Colombier " } else", 166600d97012SDavid du Colombier " { cpu_printf(\"pan: state empty\\n\");", 166700d97012SDavid du Colombier " }", 166800d97012SDavid du Colombier "", 166900d97012SDavid du Colombier " depth = 0;", 167000d97012SDavid du Colombier " trpt = &trail[1];", 167100d97012SDavid du Colombier " trpt->tau = f->m_tau;", 167200d97012SDavid du Colombier " trpt->o_pm = f->m_o_pm;", 167300d97012SDavid du Colombier "", 167400d97012SDavid du Colombier " (trpt-1)->ostate = &D_State; /* stub */", 167500d97012SDavid du Colombier " trpt->ostate = &D_State;", 167600d97012SDavid du Colombier "", 167700d97012SDavid du Colombier "#ifdef FULL_TRAIL", 167800d97012SDavid du Colombier " if (upto > 0)", 167900d97012SDavid du Colombier " { stack_last[core_id] = (Stack_Tree *) f->m_stack;", 168000d97012SDavid du Colombier " }", 168100d97012SDavid du Colombier " #if defined(VERBOSE)", 168200d97012SDavid du Colombier " if (stack_last[core_id])", 168300d97012SDavid du Colombier " { cpu_printf(\"%%d: UNPACK -- SET m_stack %%u (%%d,%%d)\\n\",", 168400d97012SDavid du Colombier " depth, stack_last[core_id], stack_last[core_id]->pr,", 168500d97012SDavid du Colombier " stack_last[core_id]->t_id);", 168600d97012SDavid du Colombier " }", 168700d97012SDavid du Colombier " #endif", 168800d97012SDavid du Colombier "#endif", 168900d97012SDavid du Colombier "", 169000d97012SDavid du Colombier " if (!trpt->o_t)", 169100d97012SDavid du Colombier " { static Trans D_Trans;", 169200d97012SDavid du Colombier " trpt->o_t = &D_Trans;", 169300d97012SDavid du Colombier " }", 169400d97012SDavid du Colombier "", 169500d97012SDavid du Colombier " #ifdef VERI", 169600d97012SDavid du Colombier " if ((trpt->tau & 4) != 4)", 169700d97012SDavid du Colombier " { trpt->tau |= 4; /* the claim moves first */", 169800d97012SDavid du Colombier " cpu_printf(\"warning: trpt was not up to date\\n\");", 169900d97012SDavid du Colombier " }", 170000d97012SDavid du Colombier " #endif", 170100d97012SDavid du Colombier "", 170200d97012SDavid du Colombier " for (i = 0; i < (int) now._nr_pr; i++)", 170300d97012SDavid du Colombier " { P0 *ptr = (P0 *) pptr(i);", 170400d97012SDavid du Colombier " #ifndef NP", 170500d97012SDavid du Colombier " if (accpstate[ptr->_t][ptr->_p])", 170600d97012SDavid du Colombier " { trpt->o_pm |= 2;", 170700d97012SDavid du Colombier " }", 170800d97012SDavid du Colombier " #else", 170900d97012SDavid du Colombier " if (progstate[ptr->_t][ptr->_p])", 171000d97012SDavid du Colombier " { trpt->o_pm |= 4;", 171100d97012SDavid du Colombier " }", 171200d97012SDavid du Colombier " #endif", 171300d97012SDavid du Colombier " }", 171400d97012SDavid du Colombier "", 171500d97012SDavid du Colombier " #ifdef EVENT_TRACE", 171600d97012SDavid du Colombier " #ifndef NP", 171700d97012SDavid du Colombier " if (accpstate[EVENT_TRACE][now._event])", 171800d97012SDavid du Colombier " { trpt->o_pm |= 2;", 171900d97012SDavid du Colombier " }", 172000d97012SDavid du Colombier " #else", 172100d97012SDavid du Colombier " if (progstate[EVENT_TRACE][now._event])", 172200d97012SDavid du Colombier " { trpt->o_pm |= 4;", 172300d97012SDavid du Colombier " }", 172400d97012SDavid du Colombier " #endif", 172500d97012SDavid du Colombier " #endif", 172600d97012SDavid du Colombier "", 172700d97012SDavid du Colombier " #if defined(C_States) && (HAS_TRACK==1)", 172800d97012SDavid du Colombier " /* restore state of tracked C objects */", 172900d97012SDavid du Colombier " c_revert((uchar *) &(now.c_state[0]));", 173000d97012SDavid du Colombier " #if (HAS_STACK==1)", 173100d97012SDavid du Colombier " c_unstack((uchar *) f->m_c_stack); /* unmatched tracked data */", 173200d97012SDavid du Colombier " #endif", 173300d97012SDavid du Colombier " #endif", 173400d97012SDavid du Colombier " return 1;", 173500d97012SDavid du Colombier "}", 173600d97012SDavid du Colombier "", 173700d97012SDavid du Colombier "void", 173800d97012SDavid du Colombier "write_root(void) /* for trail file */", 173900d97012SDavid du Colombier "{ int fd;", 174000d97012SDavid du Colombier "", 174100d97012SDavid du Colombier " if (iterative == 0 && Nr_Trails > 1)", 174200d97012SDavid du Colombier " sprintf(fnm, \"%%s%%d.%%s\", TrailFile, Nr_Trails-1, sprefix);", 174300d97012SDavid du Colombier " else", 174400d97012SDavid du Colombier " sprintf(fnm, \"%%s.%%s\", TrailFile, sprefix);", 174500d97012SDavid du Colombier "", 174600d97012SDavid du Colombier " if (cur_Root.m_vsize == 0)", 174700d97012SDavid du Colombier " { (void) unlink(fnm); /* remove possible old copy */", 174800d97012SDavid du Colombier " return; /* its the default initial state */", 174900d97012SDavid du Colombier " }", 175000d97012SDavid du Colombier "", 175100d97012SDavid du Colombier " if ((fd = creat(fnm, TMODE)) < 0)", 175200d97012SDavid du Colombier " { char *q;", 175300d97012SDavid du Colombier " if ((q = strchr(TrailFile, \'.\')))", 175400d97012SDavid du Colombier " { *q = \'\\0\'; /* strip .pml */", 175500d97012SDavid du Colombier " if (iterative == 0 && Nr_Trails-1 > 0)", 175600d97012SDavid du Colombier " sprintf(fnm, \"%%s%%d.%%s\", TrailFile, Nr_Trails-1, sprefix);", 175700d97012SDavid du Colombier " else", 175800d97012SDavid du Colombier " sprintf(fnm, \"%%s.%%s\", TrailFile, sprefix);", 175900d97012SDavid du Colombier " *q = \'.\';", 176000d97012SDavid du Colombier " fd = creat(fnm, TMODE);", 176100d97012SDavid du Colombier " }", 176200d97012SDavid du Colombier " if (fd < 0)", 176300d97012SDavid du Colombier " { cpu_printf(\"pan: cannot create %%s\\n\", fnm);", 176400d97012SDavid du Colombier " perror(\"cause\");", 176500d97012SDavid du Colombier " return;", 176600d97012SDavid du Colombier " } }", 176700d97012SDavid du Colombier "", 176800d97012SDavid du Colombier " if (write(fd, &cur_Root, sizeof(SM_frame)) != sizeof(SM_frame))", 176900d97012SDavid du Colombier " { cpu_printf(\"pan: error writing %%s\\n\", fnm);", 177000d97012SDavid du Colombier " } else", 177100d97012SDavid du Colombier " { cpu_printf(\"pan: wrote %%s\\n\", fnm);", 177200d97012SDavid du Colombier " }", 177300d97012SDavid du Colombier " close(fd);", 177400d97012SDavid du Colombier "}", 177500d97012SDavid du Colombier "", 177600d97012SDavid du Colombier "void", 177700d97012SDavid du Colombier "set_root(void)", 177800d97012SDavid du Colombier "{ int fd;", 177900d97012SDavid du Colombier " char *q;", 178000d97012SDavid du Colombier " char MyFile[512];", /* enough to hold a reasonable pathname */ 178100d97012SDavid du Colombier " char MySuffix[16];", 178200d97012SDavid du Colombier " char *ssuffix = \"rst\";", 178300d97012SDavid du Colombier " int try_core = 1;", 178400d97012SDavid du Colombier "", 178500d97012SDavid du Colombier " strcpy(MyFile, TrailFile);", 178600d97012SDavid du Colombier "try_again:", 178700d97012SDavid du Colombier " if (whichtrail > 0)", 178800d97012SDavid du Colombier " { sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, ssuffix);", 178900d97012SDavid du Colombier " fd = open(fnm, O_RDONLY, 0);", 179000d97012SDavid du Colombier " if (fd < 0 && (q = strchr(MyFile, \'.\')))", 179100d97012SDavid du Colombier " { *q = \'\\0\'; /* strip .pml */", 179200d97012SDavid du Colombier " sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, ssuffix);", 179300d97012SDavid du Colombier " *q = \'.\';", 179400d97012SDavid du Colombier " fd = open(fnm, O_RDONLY, 0);", 179500d97012SDavid du Colombier " }", 179600d97012SDavid du Colombier " } else", 179700d97012SDavid du Colombier " { sprintf(fnm, \"%%s.%%s\", MyFile, ssuffix);", 179800d97012SDavid du Colombier " fd = open(fnm, O_RDONLY, 0);", 179900d97012SDavid du Colombier " if (fd < 0 && (q = strchr(MyFile, \'.\')))", 180000d97012SDavid du Colombier " { *q = \'\\0\'; /* strip .pml */", 180100d97012SDavid du Colombier " sprintf(fnm, \"%%s.%%s\", MyFile, ssuffix);", 180200d97012SDavid du Colombier " *q = \'.\';", 180300d97012SDavid du Colombier " fd = open(fnm, O_RDONLY, 0);", 180400d97012SDavid du Colombier " } }", 180500d97012SDavid du Colombier "", 180600d97012SDavid du Colombier " if (fd < 0)", 180700d97012SDavid du Colombier " { if (try_core < NCORE)", 180800d97012SDavid du Colombier " { ssuffix = MySuffix;", 180900d97012SDavid du Colombier " sprintf(ssuffix, \"cpu%%d_rst\", try_core++);", 181000d97012SDavid du Colombier " goto try_again;", 181100d97012SDavid du Colombier " }", 181200d97012SDavid du Colombier " cpu_printf(\"no file '%%s.rst' or '%%s' (not an error)\\n\", MyFile, fnm);", 181300d97012SDavid du Colombier " } else", 181400d97012SDavid du Colombier " { if (read(fd, &cur_Root, sizeof(SM_frame)) != sizeof(SM_frame))", 181500d97012SDavid du Colombier " { cpu_printf(\"read error %%s\\n\", fnm);", 181600d97012SDavid du Colombier " close(fd);", 181700d97012SDavid du Colombier " pan_exit(1);", 181800d97012SDavid du Colombier " }", 181900d97012SDavid du Colombier " close(fd);", 182000d97012SDavid du Colombier " (void) unpack_state(&cur_Root, -2);", 182100d97012SDavid du Colombier "#ifdef SEP_STATE", 182200d97012SDavid du Colombier " cpu_printf(\"partial trail -- last few steps only\\n\");", 182300d97012SDavid du Colombier "#endif", 182400d97012SDavid du Colombier " cpu_printf(\"restored root from '%%s'\\n\", fnm);", 182500d97012SDavid du Colombier " printf(\"=====State:=====\\n\");", 182600d97012SDavid du Colombier " { int i, j; P0 *z;", 182700d97012SDavid du Colombier " for (i = 0; i < now._nr_pr; i++)", 182800d97012SDavid du Colombier " { z = (P0 *)pptr(i);", 182900d97012SDavid du Colombier " printf(\"proc %%2d (%%s) \", i, procname[z->_t]);", 183000d97012SDavid du Colombier 183100d97012SDavid du Colombier " for (j = 0; src_all[j].src; j++)", 183200d97012SDavid du Colombier " if (src_all[j].tp == (int) z->_t)", 183300d97012SDavid du Colombier " { printf(\" %%s:%%d \",", 183400d97012SDavid du Colombier " PanSource, src_all[j].src[z->_p]);", 183500d97012SDavid du Colombier " break;", 183600d97012SDavid du Colombier " }", 183700d97012SDavid du Colombier " printf(\"(state %%d)\\n\", z->_p);", 183800d97012SDavid du Colombier " c_locals(i, z->_t);", 183900d97012SDavid du Colombier " }", 184000d97012SDavid du Colombier " c_globals();", 184100d97012SDavid du Colombier " }", 184200d97012SDavid du Colombier " printf(\"================\\n\");", 184300d97012SDavid du Colombier " }", 184400d97012SDavid du Colombier "}", 184500d97012SDavid du Colombier "", 184600d97012SDavid du Colombier "#ifdef USE_DISK", 184700d97012SDavid du Colombier "unsigned long dsk_written, dsk_drained;", 184800d97012SDavid du Colombier "void mem_drain(void);", 184900d97012SDavid du Colombier "#endif", 185000d97012SDavid du Colombier "", 185100d97012SDavid du Colombier "void", 185200d97012SDavid du Colombier "m_clear_frame(SM_frame *f)", /* clear room for stats */ 185300d97012SDavid du Colombier "{ int i, clr_sz = sizeof(SM_results);", 185400d97012SDavid du Colombier "", 185500d97012SDavid du Colombier " for (i = 0; i <= _NP_; i++) /* all proctypes */", 185600d97012SDavid du Colombier " { clr_sz += NrStates[i]*sizeof(uchar);", 185700d97012SDavid du Colombier " }", 185800d97012SDavid du Colombier " memset(f, 0, clr_sz);", 185900d97012SDavid du Colombier " /* caution if sizeof(SM_results) > sizeof(SM_frame) */", 186000d97012SDavid du Colombier "}", 186100d97012SDavid du Colombier "", 186200d97012SDavid du Colombier "#define TargetQ_Full(n) (m_workq[n][prfree[n]].m_vsize != 0)", /* no free slot */ 186300d97012SDavid du Colombier "#define TargetQ_NotFull(n) (m_workq[n][prfree[n]].m_vsize == 0)", /* avoiding prcnt */ 186400d97012SDavid du Colombier "", 186500d97012SDavid du Colombier "int", 186600d97012SDavid du Colombier "AllQueuesEmpty(void)", 186700d97012SDavid du Colombier "{ int q;", 186800d97012SDavid du Colombier "#ifndef NGQ", 186900d97012SDavid du Colombier " if (*grcnt != 0)", 187000d97012SDavid du Colombier " { return 0;", 187100d97012SDavid du Colombier " }", 187200d97012SDavid du Colombier "#endif", 187300d97012SDavid du Colombier " for (q = 0; q < NCORE; q++)", 187400d97012SDavid du Colombier " { if (prcnt[q] != 0)", /* not locked, ok if race */ 187500d97012SDavid du Colombier " { return 0;", 187600d97012SDavid du Colombier " } }", 187700d97012SDavid du Colombier " return 1;", 187800d97012SDavid du Colombier "}", 187900d97012SDavid du Colombier "", 188000d97012SDavid du Colombier "void", 188100d97012SDavid du Colombier "Read_Queue(int q)", 188200d97012SDavid du Colombier "{ SM_frame *f, *of;", 188300d97012SDavid du Colombier " int remember, target_q;", 188400d97012SDavid du Colombier " SM_results *r;", 188500d97012SDavid du Colombier " double patience = 0.0;", 188600d97012SDavid du Colombier "", 188700d97012SDavid du Colombier " target_q = (q + 1) %% NCORE;", 188800d97012SDavid du Colombier "", 188900d97012SDavid du Colombier " for (;;)", 189000d97012SDavid du Colombier " { f = Get_Full_Frame(q);", 189100d97012SDavid du Colombier " if (!f) /* 1 second timeout -- and trigger for Query */", 189200d97012SDavid du Colombier " { if (someone_crashed(2))", 189300d97012SDavid du Colombier " { printf(\"cpu%%d: search terminated [code %%d]\\n\",", 189400d97012SDavid du Colombier " core_id, search_terminated?*search_terminated:-1);", 189500d97012SDavid du Colombier " sudden_stop(\"\");", 189600d97012SDavid du Colombier " pan_exit(1);", 189700d97012SDavid du Colombier " }", 189800d97012SDavid du Colombier "#ifdef TESTING", 189900d97012SDavid du Colombier " /* to profile with cc -pg and gprof pan.exe -- set handoff depth beyond maxdepth */", 190000d97012SDavid du Colombier " exit(0);", 190100d97012SDavid du Colombier "#endif", 190200d97012SDavid du Colombier " remember = *grfree;", 190300d97012SDavid du Colombier " if (core_id == 0 /* root can initiate termination */", 190400d97012SDavid du Colombier " && remote_party == 0 /* and only the original root */", 190500d97012SDavid du Colombier " && query_in_progress == 0 /* unless its already in progress */", 190600d97012SDavid du Colombier " && AllQueuesEmpty())", 190700d97012SDavid du Colombier " { f = Get_Free_Frame(target_q);", 190800d97012SDavid du Colombier " query_in_progress = 1; /* only root process can do this */", 190900d97012SDavid du Colombier " if (!f) { Uerror(\"Fatal1: no free slot\"); }", 191000d97012SDavid du Colombier " f->m_boq = QUERY; /* initiate Query */", 191100d97012SDavid du Colombier " if (verbose)", 191200d97012SDavid du Colombier " { cpu_printf(\"snd QUERY to q%%d (%%d) into slot %%d\\n\",", 191300d97012SDavid du Colombier " target_q, nstates_get + 1, prfree[target_q]-1);", 191400d97012SDavid du Colombier " }", 191500d97012SDavid du Colombier " f->m_vsize = remember + 1;", 191600d97012SDavid du Colombier " /* number will not change unless we receive more states */", 191700d97012SDavid du Colombier " } else if (patience++ > OneHour) /* one hour watchdog timer */", 191800d97012SDavid du Colombier " { cpu_printf(\"timeout -- giving up\\n\");", 191900d97012SDavid du Colombier " sudden_stop(\"queue timeout\");", 192000d97012SDavid du Colombier " pan_exit(1);", 192100d97012SDavid du Colombier " }", 192200d97012SDavid du Colombier " if (0) cpu_printf(\"timed out -- try again\\n\");", 192300d97012SDavid du Colombier " continue; ", 192400d97012SDavid du Colombier " }", 192500d97012SDavid du Colombier " patience = 0.0; /* reset watchdog */", 192600d97012SDavid du Colombier "", 192700d97012SDavid du Colombier " if (f->m_boq == QUERY)", 192800d97012SDavid du Colombier " { if (verbose)", 192900d97012SDavid du Colombier " { cpu_printf(\"got QUERY on q%%d (%%d <> %%d) from slot %%d\\n\",", 193000d97012SDavid du Colombier " q, f->m_vsize, nstates_put + 1, prfull[q]-1);", 193100d97012SDavid du Colombier " snapshot();", 193200d97012SDavid du Colombier " }", 193300d97012SDavid du Colombier " remember = f->m_vsize;", 193400d97012SDavid du Colombier " f->m_vsize = 0; /* release slot */", 193500d97012SDavid du Colombier "", 193600d97012SDavid du Colombier " if (core_id == 0 && remote_party == 0) /* original root cpu0 */", 193700d97012SDavid du Colombier " { if (query_in_progress == 1 /* didn't send more states in the interim */", 193800d97012SDavid du Colombier " && *grfree + 1 == remember) /* no action on global queue meanwhile */", 193900d97012SDavid du Colombier " { if (verbose) cpu_printf(\"Termination detected\\n\");", 194000d97012SDavid du Colombier " if (TargetQ_Full(target_q))", 194100d97012SDavid du Colombier " { if (verbose)", 194200d97012SDavid du Colombier " cpu_printf(\"warning: target q is full\\n\");", 194300d97012SDavid du Colombier " }", 194400d97012SDavid du Colombier " f = Get_Free_Frame(target_q);", 194500d97012SDavid du Colombier " if (!f) { Uerror(\"Fatal2: no free slot\"); }", 194600d97012SDavid du Colombier " m_clear_frame(f);", 194700d97012SDavid du Colombier " f->m_boq = QUIT; /* send final Quit, collect stats */", 194800d97012SDavid du Colombier " f->m_vsize = 111; /* anything non-zero will do */", 194900d97012SDavid du Colombier " if (verbose)", 195000d97012SDavid du Colombier " cpu_printf(\"put QUIT on q%%d\\n\", target_q);", 195100d97012SDavid du Colombier " } else", 195200d97012SDavid du Colombier " { if (verbose) cpu_printf(\"Stale Query\\n\");", 195300d97012SDavid du Colombier "#ifdef USE_DISK", 195400d97012SDavid du Colombier " mem_drain();", 195500d97012SDavid du Colombier "#endif", 195600d97012SDavid du Colombier " }", 195700d97012SDavid du Colombier " query_in_progress = 0;", 195800d97012SDavid du Colombier " } else", 195900d97012SDavid du Colombier " { if (TargetQ_Full(target_q))", 196000d97012SDavid du Colombier " { if (verbose)", 196100d97012SDavid du Colombier " cpu_printf(\"warning: forward query - target q full\\n\");", 196200d97012SDavid du Colombier " }", 196300d97012SDavid du Colombier " f = Get_Free_Frame(target_q);", 196400d97012SDavid du Colombier " if (verbose)", 196500d97012SDavid du Colombier " cpu_printf(\"snd QUERY response to q%%d (%%d <> %%d) in slot %%d\\n\",", 196600d97012SDavid du Colombier " target_q, remember, *grfree + 1, prfree[target_q]-1);", 196700d97012SDavid du Colombier " if (!f) { Uerror(\"Fatal4: no free slot\"); }", 196800d97012SDavid du Colombier "", 196900d97012SDavid du Colombier " if (*grfree + 1 == remember) /* no action on global queue */", 197000d97012SDavid du Colombier " { f->m_boq = QUERY; /* forward query, to root */", 197100d97012SDavid du Colombier " f->m_vsize = remember;", 197200d97012SDavid du Colombier " } else", 197300d97012SDavid du Colombier " { f->m_boq = QUERY_F; /* no match -- busy */", 197400d97012SDavid du Colombier " f->m_vsize = 112; /* anything non-zero */", 197500d97012SDavid du Colombier "#ifdef USE_DISK", 197600d97012SDavid du Colombier " if (dsk_written != dsk_drained)", 197700d97012SDavid du Colombier " { mem_drain();", 197800d97012SDavid du Colombier " }", 197900d97012SDavid du Colombier "#endif", 198000d97012SDavid du Colombier " } }", 198100d97012SDavid du Colombier " continue;", 198200d97012SDavid du Colombier " }", 198300d97012SDavid du Colombier "", 198400d97012SDavid du Colombier " if (f->m_boq == QUERY_F)", 198500d97012SDavid du Colombier " { if (verbose)", 198600d97012SDavid du Colombier " { cpu_printf(\"got QUERY_F on q%%d from slot %%d\\n\", q, prfull[q]-1);", 198700d97012SDavid du Colombier " }", 198800d97012SDavid du Colombier " f->m_vsize = 0; /* release slot */", 198900d97012SDavid du Colombier "", 199000d97012SDavid du Colombier " if (core_id == 0 && remote_party == 0) /* original root cpu0 */", 199100d97012SDavid du Colombier " { if (verbose) cpu_printf(\"No Match on Query\\n\");", 199200d97012SDavid du Colombier " query_in_progress = 0;", 199300d97012SDavid du Colombier " } else", 199400d97012SDavid du Colombier " { if (TargetQ_Full(target_q))", 199500d97012SDavid du Colombier " { if (verbose) cpu_printf(\"warning: forwarding query_f, target queue full\\n\");", 199600d97012SDavid du Colombier " }", 199700d97012SDavid du Colombier " f = Get_Free_Frame(target_q);", 199800d97012SDavid du Colombier " if (verbose) cpu_printf(\"forward QUERY_F to q%%d into slot %%d\\n\",", 199900d97012SDavid du Colombier " target_q, prfree[target_q]-1);", 200000d97012SDavid du Colombier " if (!f) { Uerror(\"Fatal5: no free slot\"); }", 200100d97012SDavid du Colombier " f->m_boq = QUERY_F; /* cannot terminate yet */", 200200d97012SDavid du Colombier " f->m_vsize = 113; /* anything non-zero */", 200300d97012SDavid du Colombier " }", 200400d97012SDavid du Colombier "#ifdef USE_DISK", 200500d97012SDavid du Colombier " if (dsk_written != dsk_drained)", 200600d97012SDavid du Colombier " { mem_drain();", 200700d97012SDavid du Colombier " }", 200800d97012SDavid du Colombier "#endif", 200900d97012SDavid du Colombier " continue;", 201000d97012SDavid du Colombier " }", 201100d97012SDavid du Colombier "", 201200d97012SDavid du Colombier " if (f->m_boq == QUIT)", 201300d97012SDavid du Colombier " { if (0) cpu_printf(\"done -- local memcnt %%g Mb\\n\", memcnt/(1048576.));", 201400d97012SDavid du Colombier " retrieve_info((SM_results *) f); /* collect and combine stats */", 201500d97012SDavid du Colombier " if (verbose)", 201600d97012SDavid du Colombier " { cpu_printf(\"received Quit\\n\");", 201700d97012SDavid du Colombier " snapshot();", 201800d97012SDavid du Colombier " }", 201900d97012SDavid du Colombier " f->m_vsize = 0; /* release incoming slot */", 202000d97012SDavid du Colombier " if (core_id != 0)", 202100d97012SDavid du Colombier " { f = Get_Free_Frame(target_q); /* new outgoing slot */", 202200d97012SDavid du Colombier " if (!f) { Uerror(\"Fatal6: no free slot\"); }", 202300d97012SDavid du Colombier " m_clear_frame(f); /* start with zeroed stats */", 202400d97012SDavid du Colombier " record_info((SM_results *) f);", 202500d97012SDavid du Colombier " f->m_boq = QUIT; /* forward combined results */", 202600d97012SDavid du Colombier " f->m_vsize = 114; /* anything non-zero */", 202700d97012SDavid du Colombier " if (verbose>1)", 202800d97012SDavid du Colombier " cpu_printf(\"fwd Results to q%%d\\n\", target_q);", 202900d97012SDavid du Colombier " }", 203000d97012SDavid du Colombier " break; /* successful termination */", 203100d97012SDavid du Colombier " }", 203200d97012SDavid du Colombier "", 203300d97012SDavid du Colombier " /* else: 0<= boq <= 255, means STATE transfer */", 203400d97012SDavid du Colombier " if (unpack_state(f, q) != 0)", 203500d97012SDavid du Colombier " { nstates_get++;", 203600d97012SDavid du Colombier " f->m_vsize = 0; /* release slot */", 203700d97012SDavid du Colombier " if (VVERBOSE) cpu_printf(\"Got state\\n\");", 203800d97012SDavid du Colombier "", 203900d97012SDavid du Colombier " if (search_terminated != NULL", 204000d97012SDavid du Colombier " && *search_terminated == 0)", 204100d97012SDavid du Colombier " { new_state(); /* explore successors */", 204200d97012SDavid du Colombier " memset((uchar *) &cur_Root, 0, sizeof(SM_frame)); /* avoid confusion */", 204300d97012SDavid du Colombier " } else", 204400d97012SDavid du Colombier " { pan_exit(0);", 204500d97012SDavid du Colombier " }", 204600d97012SDavid du Colombier " } else", 204700d97012SDavid du Colombier " { pan_exit(0);", 204800d97012SDavid du Colombier " } }", 204900d97012SDavid du Colombier " if (verbose) cpu_printf(\"done got %%d put %%d\\n\", nstates_get, nstates_put);", 205000d97012SDavid du Colombier " sleep_report();", 205100d97012SDavid du Colombier "}", 205200d97012SDavid du Colombier "", 205300d97012SDavid du Colombier "void", 205400d97012SDavid du Colombier "give_up(int unused_x)", 205500d97012SDavid du Colombier "{", 205600d97012SDavid du Colombier " if (search_terminated != NULL)", 205700d97012SDavid du Colombier " { *search_terminated |= 32; /* give_up */", 205800d97012SDavid du Colombier " }", 205900d97012SDavid du Colombier " if (!writing_trail)", 206000d97012SDavid du Colombier " { was_interrupted = 1;", 206100d97012SDavid du Colombier " snapshot();", 206200d97012SDavid du Colombier " cpu_printf(\"Give Up\\n\");", 206300d97012SDavid du Colombier " sleep_report();", 206400d97012SDavid du Colombier " pan_exit(1);", 206500d97012SDavid du Colombier " } else /* we are already terminating */", 206600d97012SDavid du Colombier " { cpu_printf(\"SIGINT\\n\");", 206700d97012SDavid du Colombier " }", 206800d97012SDavid du Colombier "}", 206900d97012SDavid du Colombier "", 207000d97012SDavid du Colombier "void", 207100d97012SDavid du Colombier "check_overkill(void)", 207200d97012SDavid du Colombier "{", 207300d97012SDavid du Colombier " vmax_seen = (vmax_seen + 7)/ 8;", 207400d97012SDavid du Colombier " vmax_seen *= 8; /* round up to a multiple of 8 */", 207500d97012SDavid du Colombier "", 207600d97012SDavid du Colombier " if (core_id == 0", 207700d97012SDavid du Colombier " && !remote_party", 207800d97012SDavid du Colombier " && nstates_put > 0", 207900d97012SDavid du Colombier " && VMAX - vmax_seen > 8)", 208000d97012SDavid du Colombier " {", 208100d97012SDavid du Colombier "#ifdef BITSTATE", 208200d97012SDavid du Colombier " printf(\"cpu0: max VMAX value seen in this run: \");", 208300d97012SDavid du Colombier "#else", 208400d97012SDavid du Colombier " printf(\"cpu0: recommend recompiling with \");", 208500d97012SDavid du Colombier "#endif", 208600d97012SDavid du Colombier " printf(\"-DVMAX=%%d\\n\", vmax_seen);", 208700d97012SDavid du Colombier " }", 208800d97012SDavid du Colombier "}", 208900d97012SDavid du Colombier "", 209000d97012SDavid du Colombier "void", 209100d97012SDavid du Colombier "mem_put(int q) /* handoff state to other cpu, workq q */", 209200d97012SDavid du Colombier "{ SM_frame *f;", 209300d97012SDavid du Colombier " int i, j;", 209400d97012SDavid du Colombier "", 209500d97012SDavid du Colombier " if (vsize > VMAX)", 209600d97012SDavid du Colombier " { vsize = (vsize + 7)/8; vsize *= 8; /* round up */", 209700d97012SDavid du Colombier " printf(\"pan: recompile with -DVMAX=N with N >= %%d\\n\", (int) vsize);", 209800d97012SDavid du Colombier " Uerror(\"aborting\");", 209900d97012SDavid du Colombier " }", 210000d97012SDavid du Colombier " if (now._nr_pr > PMAX)", 210100d97012SDavid du Colombier " { printf(\"pan: recompile with -DPMAX=N with N >= %%d\\n\", now._nr_pr);", 210200d97012SDavid du Colombier " Uerror(\"aborting\");", 210300d97012SDavid du Colombier " }", 210400d97012SDavid du Colombier " if (now._nr_qs > QMAX)", 210500d97012SDavid du Colombier " { printf(\"pan: recompile with -DQMAX=N with N >= %%d\\n\", now._nr_qs);", 210600d97012SDavid du Colombier " Uerror(\"aborting\");", 210700d97012SDavid du Colombier " }", 210800d97012SDavid du Colombier " if (vsize > vmax_seen) vmax_seen = vsize;", 210900d97012SDavid du Colombier " if (now._nr_pr > pmax_seen) pmax_seen = now._nr_pr;", 211000d97012SDavid du Colombier " if (now._nr_qs > qmax_seen) qmax_seen = now._nr_qs;", 211100d97012SDavid du Colombier "", 211200d97012SDavid du Colombier " f = Get_Free_Frame(q); /* not called in likely deadlock states */", 211300d97012SDavid du Colombier " if (!f) { Uerror(\"Fatal3: no free slot\"); }", 211400d97012SDavid du Colombier "", 211500d97012SDavid du Colombier " if (VVERBOSE) cpu_printf(\"putting state into q%%d\\n\", q);", 211600d97012SDavid du Colombier "", 211700d97012SDavid du Colombier " memcpy((uchar *) f->m_now, (uchar *) &now, vsize);", 2118*de2caf28SDavid du Colombier "#if !defined(NOCOMP) && !defined(HC)", 2119*de2caf28SDavid du Colombier " memset((uchar *) f->m_mask, 0, (VMAX+7)/8 * sizeof(char));", 212000d97012SDavid du Colombier " for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)", 212100d97012SDavid du Colombier " { if (Mask[i])", 2122*de2caf28SDavid du Colombier " { f->m_mask[i/8] |= (1<<j);", 212300d97012SDavid du Colombier " } }", 2124*de2caf28SDavid du Colombier "#endif", 212500d97012SDavid du Colombier " if (now._nr_pr > 0)", 212600d97012SDavid du Colombier " { memcpy((uchar *) f->m_p_offset, (uchar *) proc_offset, now._nr_pr * sizeof(OFFT));", 212700d97012SDavid du Colombier " memcpy((uchar *) f->m_p_skip, (uchar *) proc_skip, now._nr_pr * sizeof(uchar));", 212800d97012SDavid du Colombier " }", 212900d97012SDavid du Colombier " if (now._nr_qs > 0)", 213000d97012SDavid du Colombier " { memcpy((uchar *) f->m_q_offset, (uchar *) q_offset, now._nr_qs * sizeof(OFFT));", 213100d97012SDavid du Colombier " memcpy((uchar *) f->m_q_skip, (uchar *) q_skip, now._nr_qs * sizeof(uchar));", 213200d97012SDavid du Colombier " }", 213300d97012SDavid du Colombier "#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)", 213400d97012SDavid du Colombier " c_stack((uchar *) f->m_c_stack); /* save unmatched tracked data */", 213500d97012SDavid du Colombier "#endif", 213600d97012SDavid du Colombier "#ifdef FULL_TRAIL", 213700d97012SDavid du Colombier " f->m_stack = stack_last[core_id];", 213800d97012SDavid du Colombier "#endif", 213900d97012SDavid du Colombier " f->nr_handoffs = nr_handoffs+1;", 214000d97012SDavid du Colombier " f->m_tau = trpt->tau;", 214100d97012SDavid du Colombier " f->m_o_pm = trpt->o_pm;", 214200d97012SDavid du Colombier " f->m_boq = boq;", 214300d97012SDavid du Colombier " f->m_vsize = vsize; /* must come last - now the other cpu can see it */", 214400d97012SDavid du Colombier "", 214500d97012SDavid du Colombier " if (query_in_progress == 1)", 214600d97012SDavid du Colombier " query_in_progress = 2; /* make sure we know, if a query makes the rounds */", 214700d97012SDavid du Colombier " nstates_put++;", 214800d97012SDavid du Colombier "}", 214900d97012SDavid du Colombier "", 215000d97012SDavid du Colombier "#ifdef USE_DISK", 215100d97012SDavid du Colombier "int Dsk_W_Nr, Dsk_R_Nr;", 215200d97012SDavid du Colombier "int dsk_file = -1, dsk_read = -1;", 215300d97012SDavid du Colombier "unsigned long dsk_written, dsk_drained;", 215400d97012SDavid du Colombier "char dsk_name[512];", 215500d97012SDavid du Colombier "", 215600d97012SDavid du Colombier "#ifndef BFS_DISK", 215700d97012SDavid du Colombier "#if defined(WIN32) || defined(WIN64)", 215800d97012SDavid du Colombier " #define RFLAGS (O_RDONLY|O_BINARY)", 215900d97012SDavid du Colombier " #define WFLAGS (O_CREAT|O_WRONLY|O_TRUNC|O_BINARY)", 216000d97012SDavid du Colombier "#else", 216100d97012SDavid du Colombier " #define RFLAGS (O_RDONLY)", 216200d97012SDavid du Colombier " #define WFLAGS (O_CREAT|O_WRONLY|O_TRUNC)", 216300d97012SDavid du Colombier "#endif", 216400d97012SDavid du Colombier "#endif", 216500d97012SDavid du Colombier "", 216600d97012SDavid du Colombier "void", 216700d97012SDavid du Colombier "dsk_stats(void)", 216800d97012SDavid du Colombier "{ int i;", 216900d97012SDavid du Colombier "", 217000d97012SDavid du Colombier " if (dsk_written > 0)", 217100d97012SDavid du Colombier " { cpu_printf(\"dsk_written %%d states in %%d files\\ncpu%%d: dsk_drained %%6d states\\n\",", 217200d97012SDavid du Colombier " dsk_written, Dsk_W_Nr, core_id, dsk_drained);", 217300d97012SDavid du Colombier " close(dsk_read);", 217400d97012SDavid du Colombier " close(dsk_file);", 217500d97012SDavid du Colombier " for (i = 0; i < Dsk_W_Nr; i++)", 217600d97012SDavid du Colombier " { sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", i, core_id);", 217700d97012SDavid du Colombier " unlink(dsk_name);", 217800d97012SDavid du Colombier " } }", 217900d97012SDavid du Colombier "}", 218000d97012SDavid du Colombier "", 218100d97012SDavid du Colombier "void", 218200d97012SDavid du Colombier "mem_drain(void)", 218300d97012SDavid du Colombier "{ SM_frame *f, g;", 218400d97012SDavid du Colombier " int q = (core_id + 1) %% NCORE; /* target q */", 218500d97012SDavid du Colombier " int sz;", 218600d97012SDavid du Colombier "", 218700d97012SDavid du Colombier " if (dsk_read < 0", 218800d97012SDavid du Colombier " || dsk_written <= dsk_drained)", 218900d97012SDavid du Colombier " { return;", 219000d97012SDavid du Colombier " }", 219100d97012SDavid du Colombier "", 219200d97012SDavid du Colombier " while (dsk_written > dsk_drained", 219300d97012SDavid du Colombier " && TargetQ_NotFull(q))", 219400d97012SDavid du Colombier " { f = Get_Free_Frame(q);", 219500d97012SDavid du Colombier " if (!f) { Uerror(\"Fatal: unhandled condition\"); }", 219600d97012SDavid du Colombier "", 219700d97012SDavid du Colombier " if ((dsk_drained+1)%%MAX_DSK_FILE == 0) /* 100K states max per file */", 219800d97012SDavid du Colombier " { (void) close(dsk_read); /* close current read handle */", 219900d97012SDavid du Colombier " sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_R_Nr++, core_id);", 220000d97012SDavid du Colombier " (void) unlink(dsk_name); /* remove current file */", 220100d97012SDavid du Colombier " sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_R_Nr, core_id);", 220200d97012SDavid du Colombier " cpu_printf(\"reading %%s\\n\", dsk_name);", 220300d97012SDavid du Colombier " dsk_read = open(dsk_name, RFLAGS); /* open next file */", 220400d97012SDavid du Colombier " if (dsk_read < 0)", 220500d97012SDavid du Colombier " { Uerror(\"could not open dsk file\");", 220600d97012SDavid du Colombier " } }", 220700d97012SDavid du Colombier " if (read(dsk_read, &g, sizeof(SM_frame)) != sizeof(SM_frame))", 220800d97012SDavid du Colombier " { Uerror(\"bad dsk file read\");", 220900d97012SDavid du Colombier " }", 221000d97012SDavid du Colombier " sz = g.m_vsize;", 221100d97012SDavid du Colombier " g.m_vsize = 0;", 221200d97012SDavid du Colombier " memcpy(f, &g, sizeof(SM_frame));", 221300d97012SDavid du Colombier " f->m_vsize = sz; /* last */", 221400d97012SDavid du Colombier "", 221500d97012SDavid du Colombier " dsk_drained++;", 221600d97012SDavid du Colombier " }", 221700d97012SDavid du Colombier "}", 221800d97012SDavid du Colombier "", 221900d97012SDavid du Colombier "void", 222000d97012SDavid du Colombier "mem_file(void)", 222100d97012SDavid du Colombier "{ SM_frame f;", 222200d97012SDavid du Colombier " int i, j, q = (core_id + 1) %% NCORE; /* target q */", 222300d97012SDavid du Colombier "", 222400d97012SDavid du Colombier " if (vsize > VMAX)", 222500d97012SDavid du Colombier " { printf(\"pan: recompile with -DVMAX=N with N >= %%d\\n\", vsize);", 222600d97012SDavid du Colombier " Uerror(\"aborting\");", 222700d97012SDavid du Colombier " }", 222800d97012SDavid du Colombier " if (now._nr_pr > PMAX)", 222900d97012SDavid du Colombier " { printf(\"pan: recompile with -DPMAX=N with N >= %%d\\n\", now._nr_pr);", 223000d97012SDavid du Colombier " Uerror(\"aborting\");", 223100d97012SDavid du Colombier " }", 223200d97012SDavid du Colombier " if (now._nr_qs > QMAX)", 223300d97012SDavid du Colombier " { printf(\"pan: recompile with -DQMAX=N with N >= %%d\\n\", now._nr_qs);", 223400d97012SDavid du Colombier " Uerror(\"aborting\");", 223500d97012SDavid du Colombier " }", 223600d97012SDavid du Colombier "", 223700d97012SDavid du Colombier " if (VVERBOSE) cpu_printf(\"filing state for q%%d\\n\", q);", 223800d97012SDavid du Colombier "", 223900d97012SDavid du Colombier " memcpy((uchar *) f.m_now, (uchar *) &now, vsize);", 2240*de2caf28SDavid du Colombier "#if !defined(NOCOMP) && !defined(HC)", 2241*de2caf28SDavid du Colombier " memset((uchar *) f.m_mask, 0, (VMAX+7)/8 * sizeof(char));", 224200d97012SDavid du Colombier " for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)", 224300d97012SDavid du Colombier " { if (Mask[i])", 2244*de2caf28SDavid du Colombier " { f.m_mask[i/8] |= (1<<j);", 224500d97012SDavid du Colombier " } }", 2246*de2caf28SDavid du Colombier "#endif", 224700d97012SDavid du Colombier " if (now._nr_pr > 0)", 224800d97012SDavid du Colombier " { memcpy((uchar *)f.m_p_offset, (uchar *)proc_offset, now._nr_pr*sizeof(OFFT));", 224900d97012SDavid du Colombier " memcpy((uchar *)f.m_p_skip, (uchar *)proc_skip, now._nr_pr*sizeof(uchar));", 225000d97012SDavid du Colombier " }", 225100d97012SDavid du Colombier " if (now._nr_qs > 0)", 225200d97012SDavid du Colombier " { memcpy((uchar *) f.m_q_offset, (uchar *) q_offset, now._nr_qs*sizeof(OFFT));", 225300d97012SDavid du Colombier " memcpy((uchar *) f.m_q_skip, (uchar *) q_skip, now._nr_qs*sizeof(uchar));", 225400d97012SDavid du Colombier " }", 225500d97012SDavid du Colombier "#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)", 225600d97012SDavid du Colombier " c_stack((uchar *) f.m_c_stack); /* save unmatched tracked data */", 225700d97012SDavid du Colombier "#endif", 225800d97012SDavid du Colombier "#ifdef FULL_TRAIL", 225900d97012SDavid du Colombier " f.m_stack = stack_last[core_id];", 226000d97012SDavid du Colombier "#endif", 226100d97012SDavid du Colombier " f.nr_handoffs = nr_handoffs+1;", 226200d97012SDavid du Colombier " f.m_tau = trpt->tau;", 226300d97012SDavid du Colombier " f.m_o_pm = trpt->o_pm;", 226400d97012SDavid du Colombier " f.m_boq = boq;", 226500d97012SDavid du Colombier " f.m_vsize = vsize;", 226600d97012SDavid du Colombier "", 226700d97012SDavid du Colombier " if (query_in_progress == 1)", 226800d97012SDavid du Colombier " { query_in_progress = 2;", 226900d97012SDavid du Colombier " }", 227000d97012SDavid du Colombier " if (dsk_file < 0)", 227100d97012SDavid du Colombier " { sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_W_Nr, core_id);", 227200d97012SDavid du Colombier " dsk_file = open(dsk_name, WFLAGS, 0644);", 227300d97012SDavid du Colombier " dsk_read = open(dsk_name, RFLAGS);", 227400d97012SDavid du Colombier " if (dsk_file < 0 || dsk_read < 0)", 227500d97012SDavid du Colombier " { cpu_printf(\"File: <%%s>\\n\", dsk_name);", 227600d97012SDavid du Colombier " Uerror(\"cannot open diskfile\");", 227700d97012SDavid du Colombier " }", 227800d97012SDavid du Colombier " Dsk_W_Nr++; /* nr of next file to open */", 227900d97012SDavid du Colombier " cpu_printf(\"created temporary diskfile %%s\\n\", dsk_name);", 228000d97012SDavid du Colombier " } else if ((dsk_written+1)%%MAX_DSK_FILE == 0)", 228100d97012SDavid du Colombier " { close(dsk_file); /* close write handle */", 228200d97012SDavid du Colombier " sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_W_Nr++, core_id);", 228300d97012SDavid du Colombier " dsk_file = open(dsk_name, WFLAGS, 0644);", 228400d97012SDavid du Colombier " if (dsk_file < 0)", 228500d97012SDavid du Colombier " { cpu_printf(\"File: <%%s>\\n\", dsk_name);", 228600d97012SDavid du Colombier " Uerror(\"aborting: cannot open new diskfile\");", 228700d97012SDavid du Colombier " }", 228800d97012SDavid du Colombier " cpu_printf(\"created temporary diskfile %%s\\n\", dsk_name);", 228900d97012SDavid du Colombier " }", 229000d97012SDavid du Colombier " if (write(dsk_file, &f, sizeof(SM_frame)) != sizeof(SM_frame))", 229100d97012SDavid du Colombier " { Uerror(\"aborting -- disk write failed (disk full?)\");", 229200d97012SDavid du Colombier " }", 229300d97012SDavid du Colombier " nstates_put++;", 229400d97012SDavid du Colombier " dsk_written++;", 229500d97012SDavid du Colombier "}", 229600d97012SDavid du Colombier "#endif", 229700d97012SDavid du Colombier "", 229800d97012SDavid du Colombier "int", 229900d97012SDavid du Colombier "mem_hand_off(void)", 230000d97012SDavid du Colombier "{", 230100d97012SDavid du Colombier " if (search_terminated == NULL", 230200d97012SDavid du Colombier " || *search_terminated != 0) /* not a full crash check */", 230300d97012SDavid du Colombier " { pan_exit(0);", 230400d97012SDavid du Colombier " }", 230500d97012SDavid du Colombier " iam_alive(); /* on every transition of Down */", 230600d97012SDavid du Colombier "#ifdef USE_DISK", 230700d97012SDavid du Colombier " mem_drain(); /* maybe call this also on every Up */", 230800d97012SDavid du Colombier "#endif", 230900d97012SDavid du Colombier " if (depth > z_handoff /* above handoff limit */", 231000d97012SDavid du Colombier "#ifndef SAFETY", 231100d97012SDavid du Colombier " && !a_cycles /* not in liveness mode */", 231200d97012SDavid du Colombier "#endif", 231300d97012SDavid du Colombier "#if SYNC", 231400d97012SDavid du Colombier " && boq == -1 /* not mid-rv */", 231500d97012SDavid du Colombier "#endif", 231600d97012SDavid du Colombier "#ifdef VERI", 231700d97012SDavid du Colombier " && (trpt->tau&4) /* claim moves first */", 231800d97012SDavid du Colombier " && !((trpt-1)->tau&128) /* not a stutter move */", 231900d97012SDavid du Colombier "#endif", 232000d97012SDavid du Colombier " && !(trpt->tau&8)) /* not an atomic move */", 232100d97012SDavid du Colombier " { int q = (core_id + 1) %% NCORE; /* circular handoff */", 232200d97012SDavid du Colombier " #ifdef GENEROUS", 232300d97012SDavid du Colombier " if (prcnt[q] < LN_FRAMES)", /* not the best strategy */ 232400d97012SDavid du Colombier " #else", 232500d97012SDavid du Colombier " if (TargetQ_NotFull(q)", 232600d97012SDavid du Colombier " && (dfs_phase2 == 0 || prcnt[core_id] > 0))", /* not locked, ok if race */ 232700d97012SDavid du Colombier " #endif", 232800d97012SDavid du Colombier " { mem_put(q);", /* only 1 writer: lock-free */ 232900d97012SDavid du Colombier " return 1;", 233000d97012SDavid du Colombier " }", 233100d97012SDavid du Colombier " { int rval;", 233200d97012SDavid du Colombier " #ifndef NGQ", 233300d97012SDavid du Colombier " rval = GlobalQ_HasRoom();", 233400d97012SDavid du Colombier " #else", 233500d97012SDavid du Colombier " rval = 0;", 233600d97012SDavid du Colombier " #endif", 233700d97012SDavid du Colombier " #ifdef USE_DISK", 233800d97012SDavid du Colombier " if (rval == 0)", 233900d97012SDavid du Colombier " { void mem_file(void);", 234000d97012SDavid du Colombier " mem_file();", 234100d97012SDavid du Colombier " rval = 1;", 234200d97012SDavid du Colombier " }", 234300d97012SDavid du Colombier " #endif", 234400d97012SDavid du Colombier " return rval;", 234500d97012SDavid du Colombier " }", 234600d97012SDavid du Colombier " }", 234700d97012SDavid du Colombier " return 0; /* i.e., no handoff */", 234800d97012SDavid du Colombier "}", 234900d97012SDavid du Colombier "", 235000d97012SDavid du Colombier "void", 235100d97012SDavid du Colombier "mem_put_acc(void) /* liveness mode */", 235200d97012SDavid du Colombier "{ int q = (core_id + 1) %% NCORE;", 235300d97012SDavid du Colombier "", 235400d97012SDavid du Colombier " if (search_terminated == NULL", 235500d97012SDavid du Colombier " || *search_terminated != 0)", 235600d97012SDavid du Colombier " { pan_exit(0);", 235700d97012SDavid du Colombier " }", 235800d97012SDavid du Colombier "#ifdef USE_DISK", 235900d97012SDavid du Colombier " mem_drain();", 236000d97012SDavid du Colombier "#endif", 236100d97012SDavid du Colombier " /* some tortured use of preprocessing: */", 236200d97012SDavid du Colombier "#if !defined(NGQ) || defined(USE_DISK)", 236300d97012SDavid du Colombier " if (TargetQ_Full(q))", 236400d97012SDavid du Colombier " {", 236500d97012SDavid du Colombier "#endif", 236600d97012SDavid du Colombier "#ifndef NGQ", 236700d97012SDavid du Colombier " if (GlobalQ_HasRoom())", 236800d97012SDavid du Colombier " { return;", 236900d97012SDavid du Colombier " }", 237000d97012SDavid du Colombier "#endif", 237100d97012SDavid du Colombier "#ifdef USE_DISK", 237200d97012SDavid du Colombier " mem_file();", 237300d97012SDavid du Colombier " } else", 237400d97012SDavid du Colombier "#else", 237500d97012SDavid du Colombier " #if !defined(NGQ) || defined(USE_DISK)", 237600d97012SDavid du Colombier " }", 237700d97012SDavid du Colombier " #endif", 237800d97012SDavid du Colombier "#endif", 237900d97012SDavid du Colombier " { mem_put(q);", 238000d97012SDavid du Colombier " }", 238100d97012SDavid du Colombier "}", 238200d97012SDavid du Colombier "", 238300d97012SDavid du Colombier "#if defined(WIN32) || defined(WIN64)", /* visual studio */ 238400d97012SDavid du Colombier "void", 238500d97012SDavid du Colombier "init_shm(void) /* initialize shared work-queues */", 238600d97012SDavid du Colombier "{ char key[512];", 238700d97012SDavid du Colombier " int n, m;", 238800d97012SDavid du Colombier " int must_exit = 0;", 238900d97012SDavid du Colombier "", 239000d97012SDavid du Colombier " if (core_id == 0 && verbose)", 239100d97012SDavid du Colombier " { printf(\"cpu0: step 3: allocate shared work-queues %%g Mb\\n\",", 239200d97012SDavid du Colombier " ((double) NCORE * LWQ_SIZE + GWQ_SIZE) / (1048576.));", 239300d97012SDavid du Colombier " }", 239400d97012SDavid du Colombier " for (m = 0; m < NR_QS; m++) /* last q is global 1 */", 239500d97012SDavid du Colombier " { double qsize = (m == NCORE) ? GWQ_SIZE : LWQ_SIZE;", 239600d97012SDavid du Colombier " sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, m);", 239700d97012SDavid du Colombier " if (core_id == 0)", /* root process creates shared memory segments */ 239800d97012SDavid du Colombier " { shmid[m] = CreateFileMapping(", 239900d97012SDavid du Colombier " INVALID_HANDLE_VALUE, /* use paging file */", 240000d97012SDavid du Colombier " NULL, /* default security */", 240100d97012SDavid du Colombier " PAGE_READWRITE, /* access permissions */", 240200d97012SDavid du Colombier " 0, /* high-order 4 bytes */", 240300d97012SDavid du Colombier " qsize, /* low-order bytes, size in bytes */", 240400d97012SDavid du Colombier " key); /* name */", 240500d97012SDavid du Colombier " } else /* worker nodes just open these segments */", 240600d97012SDavid du Colombier " { shmid[m] = OpenFileMapping(", 240700d97012SDavid du Colombier " FILE_MAP_ALL_ACCESS, /* read/write access */", 240800d97012SDavid du Colombier " FALSE, /* children do not inherit handle */", 240900d97012SDavid du Colombier " key);", 241000d97012SDavid du Colombier " }", 241100d97012SDavid du Colombier " if (shmid[m] == NULL)", 241200d97012SDavid du Colombier " { fprintf(stderr, \"cpu%%d: could not create or open shared queues\\n\",", 241300d97012SDavid du Colombier " core_id);", 241400d97012SDavid du Colombier " must_exit = 1;", 241500d97012SDavid du Colombier " break;", 241600d97012SDavid du Colombier " }", 241700d97012SDavid du Colombier " /* attach: */", 241800d97012SDavid du Colombier " shared_mem[m] = (char *) MapViewOfFile(shmid[m], FILE_MAP_ALL_ACCESS, 0, 0, 0);", 241900d97012SDavid du Colombier " if (shared_mem[m] == NULL)", 242000d97012SDavid du Colombier " { fprintf(stderr, \"cpu%%d: cannot attach shared q%%d (%%d Mb)\\n\",", 242100d97012SDavid du Colombier " core_id, m+1, (int) (qsize/(1048576.)));", 242200d97012SDavid du Colombier " must_exit = 1;", 242300d97012SDavid du Colombier " break;", 242400d97012SDavid du Colombier " }", 242500d97012SDavid du Colombier "", 242600d97012SDavid du Colombier " memcnt += qsize;", 242700d97012SDavid du Colombier "", 242800d97012SDavid du Colombier " m_workq[m] = (SM_frame *) shared_mem[m];", 242900d97012SDavid du Colombier " if (core_id == 0)", 243000d97012SDavid du Colombier " { int nframes = (m == NCORE) ? GN_FRAMES : LN_FRAMES;", 243100d97012SDavid du Colombier " for (n = 0; n < nframes; n++)", 243200d97012SDavid du Colombier " { m_workq[m][n].m_vsize = 0;", 243300d97012SDavid du Colombier " m_workq[m][n].m_boq = 0;", 243400d97012SDavid du Colombier " } } }", 243500d97012SDavid du Colombier "", 243600d97012SDavid du Colombier " if (must_exit)", 243700d97012SDavid du Colombier " { fprintf(stderr, \"pan: check './pan --' for usage details\\n\");", 243800d97012SDavid du Colombier " pan_exit(1); /* calls cleanup_shm */", 243900d97012SDavid du Colombier " }", 244000d97012SDavid du Colombier "}", 244100d97012SDavid du Colombier "", 244200d97012SDavid du Colombier "static uchar *", 244300d97012SDavid du Colombier "prep_shmid_S(size_t n) /* either sets SS or H_tab, WIN32/WIN64 */", 244400d97012SDavid du Colombier "{ char *rval;", 244500d97012SDavid du Colombier "#ifndef SEP_STATE", 244600d97012SDavid du Colombier " char key[512];", 244700d97012SDavid du Colombier "", 244800d97012SDavid du Colombier " if (verbose && core_id == 0)", 244900d97012SDavid du Colombier " {", 245000d97012SDavid du Colombier " #ifdef BITSTATE", 245100d97012SDavid du Colombier " printf(\"cpu0: step 1: allocate shared bitstate %%g Mb\\n\",", 245200d97012SDavid du Colombier " (double) n / (1048576.));", 245300d97012SDavid du Colombier " #else", 245400d97012SDavid du Colombier " printf(\"cpu0: step 1: allocate shared hastable %%g Mb\\n\",", 245500d97012SDavid du Colombier " (double) n / (1048576.));", 245600d97012SDavid du Colombier " #endif", 245700d97012SDavid du Colombier " }", 245800d97012SDavid du Colombier " #ifdef MEMLIM", 245900d97012SDavid du Colombier " if (memcnt + (double) n > memlim)", 246000d97012SDavid du Colombier " { printf(\"cpu%%d: S %%8g + %%d Kb exceeds memory limit of %%8g Mb\\n\",", 246100d97012SDavid du Colombier " core_id, memcnt/1024., n/1024, memlim/(1048576.));", 246200d97012SDavid du Colombier " printf(\"cpu%%d: insufficient memory -- aborting\\n\", core_id);", 246300d97012SDavid du Colombier " exit(1);", 246400d97012SDavid du Colombier " }", 246500d97012SDavid du Colombier " #endif", 246600d97012SDavid du Colombier "", 246700d97012SDavid du Colombier " /* make key different from queues: */", 246800d97012SDavid du Colombier " sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, NCORE+2); /* different from qs */", 246900d97012SDavid du Colombier "", 247000d97012SDavid du Colombier " if (core_id == 0) /* root */", 247100d97012SDavid du Colombier " { shmid_S = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,", 247200d97012SDavid du Colombier "#ifdef WIN64", 247300d97012SDavid du Colombier " PAGE_READWRITE, (n>>32), (n & 0xffffffff), key);", 247400d97012SDavid du Colombier "#else", 247500d97012SDavid du Colombier " PAGE_READWRITE, 0, n, key);", 247600d97012SDavid du Colombier "#endif", 247700d97012SDavid du Colombier " memcnt += (double) n;", 247800d97012SDavid du Colombier " } else /* worker */", 247900d97012SDavid du Colombier " { shmid_S = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, key);", 248000d97012SDavid du Colombier " }", 248100d97012SDavid du Colombier 248200d97012SDavid du Colombier " if (shmid_S == NULL)", 248300d97012SDavid du Colombier " {", 248400d97012SDavid du Colombier " #ifdef BITSTATE", 248500d97012SDavid du Colombier " fprintf(stderr, \"cpu%%d: cannot %%s shared bitstate\",", 248600d97012SDavid du Colombier " core_id, core_id?\"open\":\"create\");", 248700d97012SDavid du Colombier " #else", 248800d97012SDavid du Colombier " fprintf(stderr, \"cpu%%d: cannot %%s shared hashtable\",", 248900d97012SDavid du Colombier " core_id, core_id?\"open\":\"create\");", 249000d97012SDavid du Colombier " #endif", 249100d97012SDavid du Colombier " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");", 249200d97012SDavid du Colombier " pan_exit(1);", 249300d97012SDavid du Colombier " }", 249400d97012SDavid du Colombier "", 249500d97012SDavid du Colombier " rval = (char *) MapViewOfFile(shmid_S, FILE_MAP_ALL_ACCESS, 0, 0, 0); /* attach */", 249600d97012SDavid du Colombier " if ((char *) rval == NULL)", 249700d97012SDavid du Colombier " { fprintf(stderr, \"cpu%%d: cannot attach shared bitstate or hashtable\\n\", core_id);", 249800d97012SDavid du Colombier " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");", 249900d97012SDavid du Colombier " pan_exit(1);", 250000d97012SDavid du Colombier " }", 250100d97012SDavid du Colombier "#else", 250200d97012SDavid du Colombier " rval = (char *) emalloc(n);", 250300d97012SDavid du Colombier "#endif", 250400d97012SDavid du Colombier " return (uchar *) rval;", 250500d97012SDavid du Colombier "}", 250600d97012SDavid du Colombier "", 250700d97012SDavid du Colombier "static uchar *", 250800d97012SDavid du Colombier "prep_state_mem(size_t n) /* WIN32/WIN64 sets memory arena for states */", 250900d97012SDavid du Colombier "{ char *rval;", 251000d97012SDavid du Colombier " char key[512];", 251100d97012SDavid du Colombier " static int cnt = 3; /* start larger than earlier ftok calls */", 251200d97012SDavid du Colombier "", 251300d97012SDavid du Colombier " if (verbose && core_id == 0)", 251400d97012SDavid du Colombier " { printf(\"cpu0: step 2+: pre-allocate memory arena %%d of %%g Mb\\n\",", 251500d97012SDavid du Colombier " cnt-3, (double) n / (1048576.));", 251600d97012SDavid du Colombier " }", 251700d97012SDavid du Colombier " #ifdef MEMLIM", 251800d97012SDavid du Colombier " if (memcnt + (double) n > memlim)", 251900d97012SDavid du Colombier " { printf(\"cpu%%d: error: M %%.0f + %%.0f exceeds memory limit of %%.0f Kb\\n\",", 252000d97012SDavid du Colombier " core_id, memcnt/1024.0, (double) n/1024.0, memlim/1024.0);", 252100d97012SDavid du Colombier " return NULL;", 252200d97012SDavid du Colombier " }", 252300d97012SDavid du Colombier " #endif", 252400d97012SDavid du Colombier "", 252500d97012SDavid du Colombier " sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, NCORE+cnt); cnt++;", 252600d97012SDavid du Colombier "", 252700d97012SDavid du Colombier " if (core_id == 0)", 252800d97012SDavid du Colombier " { shmid_M = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,", 252900d97012SDavid du Colombier "#ifdef WIN64", 253000d97012SDavid du Colombier " PAGE_READWRITE, (n>>32), (n & 0xffffffff), key);", 253100d97012SDavid du Colombier "#else", 253200d97012SDavid du Colombier " PAGE_READWRITE, 0, n, key);", 253300d97012SDavid du Colombier "#endif", 253400d97012SDavid du Colombier " } else", 253500d97012SDavid du Colombier " { shmid_M = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, key);", 253600d97012SDavid du Colombier " }", 253700d97012SDavid du Colombier " if (shmid_M == NULL)", 253800d97012SDavid du Colombier " { printf(\"cpu%%d: failed to get pool of shared memory nr %%d of size %%d\\n\",", 253900d97012SDavid du Colombier " core_id, cnt-3, n);", 254000d97012SDavid du Colombier " printf(\"pan: check './pan --' for usage details\\n\");", 254100d97012SDavid du Colombier " return NULL;", 254200d97012SDavid du Colombier " }", 254300d97012SDavid du Colombier " rval = (char *) MapViewOfFile(shmid_M, FILE_MAP_ALL_ACCESS, 0, 0, 0); /* attach */", 254400d97012SDavid du Colombier "", 254500d97012SDavid du Colombier " if (rval == NULL)", 254600d97012SDavid du Colombier " { printf(\"cpu%%d: failed to attach pool of shared memory nr %%d of size %%d\\n\",", 254700d97012SDavid du Colombier " core_id, cnt-3, n);", 254800d97012SDavid du Colombier " return NULL;", 254900d97012SDavid du Colombier " }", 255000d97012SDavid du Colombier " return (uchar *) rval;", 255100d97012SDavid du Colombier "}", 255200d97012SDavid du Colombier "", 255300d97012SDavid du Colombier "void", 255400d97012SDavid du Colombier "init_HT(unsigned long n) /* WIN32/WIN64 version */", 255500d97012SDavid du Colombier "{ volatile char *x;", 255600d97012SDavid du Colombier " double get_mem;", 255700d97012SDavid du Colombier "#ifndef SEP_STATE", 255800d97012SDavid du Colombier " char *dc_mem_start;", 255900d97012SDavid du Colombier "#endif", 256000d97012SDavid du Colombier " if (verbose) printf(\"cpu%%d: initialization for Windows\\n\", core_id);", 256100d97012SDavid du Colombier "", 256200d97012SDavid du Colombier "#ifdef SEP_STATE", 256300d97012SDavid du Colombier " #ifndef MEMLIM", 256400d97012SDavid du Colombier " if (verbose)", 256500d97012SDavid du Colombier " { printf(\"cpu0: steps 0,1: no -DMEMLIM set\\n\");", 256600d97012SDavid du Colombier " }", 256700d97012SDavid du Colombier " #else", 256800d97012SDavid du Colombier " if (verbose)", 256900d97012SDavid du Colombier " printf(\"cpu0: steps 0,1: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb)\\n\",", 257000d97012SDavid du Colombier " MEMLIM, ((double)n/(1048576.)), ((double) NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.));", 257100d97012SDavid du Colombier "#endif", 257200d97012SDavid du Colombier " get_mem = NCORE * sizeof(double) + (1 + CS_NR) * sizeof(void *)+ 4*sizeof(void *) + 2*sizeof(double);", 257300d97012SDavid du Colombier " /* NCORE * is_alive + search_terminated + CS_NR * sh_lock + 6 gr vars */", 257400d97012SDavid du Colombier " get_mem += 4 * NCORE * sizeof(void *);", /* prfree, prfull, prcnt, prmax */ 257500d97012SDavid du Colombier " #ifdef FULL_TRAIL", 257600d97012SDavid du Colombier " get_mem += (NCORE) * sizeof(Stack_Tree *);", 257700d97012SDavid du Colombier " /* NCORE * stack_last */", 257800d97012SDavid du Colombier " #endif", 257900d97012SDavid du Colombier " x = (volatile char *) prep_state_mem((size_t) get_mem);", 258000d97012SDavid du Colombier " shmid_X = (void *) x;", 258100d97012SDavid du Colombier " if (x == NULL)", 258200d97012SDavid du Colombier " { printf(\"cpu0: could not allocate shared memory, see ./pan --\\n\");", 258300d97012SDavid du Colombier " exit(1);", 258400d97012SDavid du Colombier " }", 258500d97012SDavid du Colombier " search_terminated = (volatile unsigned int *) x; /* comes first */", 258600d97012SDavid du Colombier " x += sizeof(void *); /* maintain alignment */", 258700d97012SDavid du Colombier "", 258800d97012SDavid du Colombier " is_alive = (volatile double *) x;", 258900d97012SDavid du Colombier " x += NCORE * sizeof(double);", 259000d97012SDavid du Colombier "", 259100d97012SDavid du Colombier " sh_lock = (volatile int *) x;", 259200d97012SDavid du Colombier " x += CS_NR * sizeof(void *); /* allow 1 word per entry */", 259300d97012SDavid du Colombier "", 259400d97012SDavid du Colombier " grfree = (volatile int *) x;", 259500d97012SDavid du Colombier " x += sizeof(void *);", 259600d97012SDavid du Colombier " grfull = (volatile int *) x;", 259700d97012SDavid du Colombier " x += sizeof(void *);", 259800d97012SDavid du Colombier " grcnt = (volatile int *) x;", 259900d97012SDavid du Colombier " x += sizeof(void *);", 260000d97012SDavid du Colombier " grmax = (volatile int *) x;", 260100d97012SDavid du Colombier " x += sizeof(void *);", 260200d97012SDavid du Colombier " prfree = (volatile int *) x;", 260300d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 260400d97012SDavid du Colombier " prfull = (volatile int *) x;", 260500d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 260600d97012SDavid du Colombier " prcnt = (volatile int *) x;", 260700d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 260800d97012SDavid du Colombier " prmax = (volatile int *) x;", 260900d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 261000d97012SDavid du Colombier " gr_readmiss = (volatile double *) x;", 261100d97012SDavid du Colombier " x += sizeof(double);", 261200d97012SDavid du Colombier " gr_writemiss = (volatile double *) x;", 261300d97012SDavid du Colombier " x += sizeof(double);", 261400d97012SDavid du Colombier "", 261500d97012SDavid du Colombier " #ifdef FULL_TRAIL", 261600d97012SDavid du Colombier " stack_last = (volatile Stack_Tree **) x;", 261700d97012SDavid du Colombier " x += NCORE * sizeof(Stack_Tree *);", 261800d97012SDavid du Colombier " #endif", 261900d97012SDavid du Colombier "", 262000d97012SDavid du Colombier " #ifndef BITSTATE", 2621*de2caf28SDavid du Colombier " H_tab = (H_el **) emalloc(n);", 262200d97012SDavid du Colombier " #endif", 262300d97012SDavid du Colombier "#else", 262400d97012SDavid du Colombier " #ifndef MEMLIM", 262500d97012SDavid du Colombier " #warning MEMLIM not set", /* cannot happen */ 262600d97012SDavid du Colombier " #define MEMLIM (2048)", 262700d97012SDavid du Colombier " #endif", 262800d97012SDavid du Colombier "", 262900d97012SDavid du Colombier " if (core_id == 0 && verbose)", 263000d97012SDavid du Colombier " printf(\"cpu0: step 0: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb) = %%g Mb for state storage\\n\",", 263100d97012SDavid du Colombier " MEMLIM, ((double)n/(1048576.)), ((double) NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.),", 263200d97012SDavid du Colombier " (memlim - memcnt - (double) n - ((double) NCORE * LWQ_SIZE + GWQ_SIZE))/(1048576.));", 263300d97012SDavid du Colombier " #ifndef BITSTATE", 2634*de2caf28SDavid du Colombier " H_tab = (H_el **) prep_shmid_S((size_t) n); /* hash_table */", 263500d97012SDavid du Colombier " #endif", 263600d97012SDavid du Colombier " get_mem = memlim - memcnt - ((double) NCORE) * LWQ_SIZE - GWQ_SIZE;", 263700d97012SDavid du Colombier " if (get_mem <= 0)", 263800d97012SDavid du Colombier " { Uerror(\"internal error -- shared state memory\");", 263900d97012SDavid du Colombier " }", 264000d97012SDavid du Colombier "", 264100d97012SDavid du Colombier " if (core_id == 0 && verbose)", 264200d97012SDavid du Colombier " { printf(\"cpu0: step 2: shared state memory %%g Mb\\n\",", 264300d97012SDavid du Colombier " get_mem/(1048576.));", 264400d97012SDavid du Colombier " }", 264500d97012SDavid du Colombier " x = dc_mem_start = (char *) prep_state_mem((size_t) get_mem); /* for states */", 264600d97012SDavid du Colombier " if (x == NULL)", 264700d97012SDavid du Colombier " { printf(\"cpu%%d: insufficient memory -- aborting\\n\", core_id);", 264800d97012SDavid du Colombier " exit(1);", 264900d97012SDavid du Colombier " }", 265000d97012SDavid du Colombier "", 265100d97012SDavid du Colombier " search_terminated = (volatile unsigned int *) x; /* comes first */", 265200d97012SDavid du Colombier " x += sizeof(void *); /* maintain alignment */", 265300d97012SDavid du Colombier "", 265400d97012SDavid du Colombier " is_alive = (volatile double *) x;", 265500d97012SDavid du Colombier " x += NCORE * sizeof(double);", 265600d97012SDavid du Colombier "", 265700d97012SDavid du Colombier " sh_lock = (volatile int *) x;", 265800d97012SDavid du Colombier " x += CS_NR * sizeof(int);", 265900d97012SDavid du Colombier "", 266000d97012SDavid du Colombier " grfree = (volatile int *) x;", 266100d97012SDavid du Colombier " x += sizeof(void *);", 266200d97012SDavid du Colombier " grfull = (volatile int *) x;", 266300d97012SDavid du Colombier " x += sizeof(void *);", 266400d97012SDavid du Colombier " grcnt = (volatile int *) x;", 266500d97012SDavid du Colombier " x += sizeof(void *);", 266600d97012SDavid du Colombier " grmax = (volatile int *) x;", 266700d97012SDavid du Colombier " x += sizeof(void *);", 266800d97012SDavid du Colombier " prfree = (volatile int *) x;", 266900d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 267000d97012SDavid du Colombier " prfull = (volatile int *) x;", 267100d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 267200d97012SDavid du Colombier " prcnt = (volatile int *) x;", 267300d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 267400d97012SDavid du Colombier " prmax = (volatile int *) x;", 267500d97012SDavid du Colombier " x += NCORE * sizeof(void *);", 267600d97012SDavid du Colombier " gr_readmiss = (volatile double *) x;", 267700d97012SDavid du Colombier " x += sizeof(double);", 267800d97012SDavid du Colombier " gr_writemiss = (volatile double *) x;", 267900d97012SDavid du Colombier " x += sizeof(double);", 268000d97012SDavid du Colombier "", 268100d97012SDavid du Colombier " #ifdef FULL_TRAIL", 268200d97012SDavid du Colombier " stack_last = (volatile Stack_Tree **) x;", 268300d97012SDavid du Colombier " x += NCORE * sizeof(Stack_Tree *);", 268400d97012SDavid du Colombier " #endif", 268500d97012SDavid du Colombier " if (((long)x)&(sizeof(void *)-1)) /* word alignment */", 268600d97012SDavid du Colombier " { x += sizeof(void *)-(((long)x)&(sizeof(void *)-1)); /* 64-bit align */", 268700d97012SDavid du Colombier " }", 268800d97012SDavid du Colombier "", 268900d97012SDavid du Colombier " #ifdef COLLAPSE", 269000d97012SDavid du Colombier " ncomps = (unsigned long *) x;", 269100d97012SDavid du Colombier " x += (256+2) * sizeof(unsigned long);", 269200d97012SDavid du Colombier " #endif", 269300d97012SDavid du Colombier "", 269400d97012SDavid du Colombier " dc_shared = (sh_Allocater *) x; /* in shared memory */", 269500d97012SDavid du Colombier " x += sizeof(sh_Allocater);", 269600d97012SDavid du Colombier "", 269700d97012SDavid du Colombier " if (core_id == 0) /* root only */", 269800d97012SDavid du Colombier " { dc_shared->dc_id = shmid_M;", 269900d97012SDavid du Colombier " dc_shared->dc_start = (void *) dc_mem_start;", 270000d97012SDavid du Colombier " dc_shared->dc_arena = x;", 270100d97012SDavid du Colombier " dc_shared->pattern = 1234567;", 270200d97012SDavid du Colombier " dc_shared->dc_size = (long) get_mem - (long) (x - dc_mem_start);", 270300d97012SDavid du Colombier " dc_shared->nxt = NULL;", 270400d97012SDavid du Colombier " }", 270500d97012SDavid du Colombier "#endif", 270600d97012SDavid du Colombier "}", 270700d97012SDavid du Colombier "", 270800d97012SDavid du Colombier "#if defined(WIN32) || defined(WIN64) || defined(__i386__) || defined(__x86_64__)", 270900d97012SDavid du Colombier "extern BOOLEAN InterlockedBitTestAndSet(LONG volatile* Base, LONG Bit);", 271000d97012SDavid du Colombier "int", 271100d97012SDavid du Colombier "tas(volatile LONG *s)", /* atomic test and set */ 271200d97012SDavid du Colombier "{ return InterlockedBitTestAndSet(s, 1);", 271300d97012SDavid du Colombier "}", 271400d97012SDavid du Colombier "#else", 271500d97012SDavid du Colombier " #error missing definition of test and set operation for this platform", 271600d97012SDavid du Colombier "#endif", 271700d97012SDavid du Colombier "", 271800d97012SDavid du Colombier "void", 271900d97012SDavid du Colombier "cleanup_shm(int val)", 272000d97012SDavid du Colombier "{ int m;", 272100d97012SDavid du Colombier " static int nibis = 0;", 272200d97012SDavid du Colombier "", 272300d97012SDavid du Colombier " if (nibis != 0)", 272400d97012SDavid du Colombier " { printf(\"cpu%%d: Redundant call to cleanup_shm(%%d)\\n\", core_id, val);", 272500d97012SDavid du Colombier " return;", 272600d97012SDavid du Colombier " } else", 272700d97012SDavid du Colombier " { nibis = 1;", 272800d97012SDavid du Colombier " }", 272900d97012SDavid du Colombier " if (search_terminated != NULL)", 273000d97012SDavid du Colombier " { *search_terminated |= 16; /* cleanup_shm */", 273100d97012SDavid du Colombier " }", 273200d97012SDavid du Colombier "", 273300d97012SDavid du Colombier " for (m = 0; m < NR_QS; m++)", 273400d97012SDavid du Colombier " { if (shmid[m] != NULL)", 273500d97012SDavid du Colombier " { UnmapViewOfFile((char *) shared_mem[m]);", 273600d97012SDavid du Colombier " CloseHandle(shmid[m]);", 273700d97012SDavid du Colombier " } }", 273800d97012SDavid du Colombier "#ifdef SEP_STATE", 273900d97012SDavid du Colombier " UnmapViewOfFile((void *) shmid_X);", 274000d97012SDavid du Colombier " CloseHandle((void *) shmid_M);", 274100d97012SDavid du Colombier "#else", 274200d97012SDavid du Colombier " #ifdef BITSTATE", 274300d97012SDavid du Colombier " if (shmid_S != NULL)", 274400d97012SDavid du Colombier " { UnmapViewOfFile(SS);", 274500d97012SDavid du Colombier " CloseHandle(shmid_S);", 274600d97012SDavid du Colombier " }", 274700d97012SDavid du Colombier " #else", 274800d97012SDavid du Colombier " if (core_id == 0 && verbose)", 274900d97012SDavid du Colombier " { printf(\"cpu0: done, %%ld Mb of shared state memory left\\n\",", 275000d97012SDavid du Colombier " dc_shared->dc_size / (long)(1048576));", 275100d97012SDavid du Colombier " }", 275200d97012SDavid du Colombier " if (shmid_S != NULL)", 275300d97012SDavid du Colombier " { UnmapViewOfFile(H_tab);", 275400d97012SDavid du Colombier " CloseHandle(shmid_S);", 275500d97012SDavid du Colombier " }", 275600d97012SDavid du Colombier " shmid_M = (void *) (dc_shared->dc_id);", 275700d97012SDavid du Colombier " UnmapViewOfFile((char *) dc_shared->dc_start);", 275800d97012SDavid du Colombier " CloseHandle(shmid_M);", 275900d97012SDavid du Colombier " #endif", 276000d97012SDavid du Colombier "#endif", 276100d97012SDavid du Colombier " /* detached from shared memory - so cannot use cpu_printf */", 276200d97012SDavid du Colombier " if (verbose)", 276300d97012SDavid du Colombier " { printf(\"cpu%%d: done -- got %%d states from queue\\n\",", 276400d97012SDavid du Colombier " core_id, nstates_get);", 276500d97012SDavid du Colombier " }", 276600d97012SDavid du Colombier "}", 276700d97012SDavid du Colombier "", 276800d97012SDavid du Colombier "void", 276900d97012SDavid du Colombier "mem_get(void)", 277000d97012SDavid du Colombier "{ SM_frame *f;", 277100d97012SDavid du Colombier " int is_parent;", 277200d97012SDavid du Colombier "", 277300d97012SDavid du Colombier "#if defined(MA) && !defined(SEP_STATE)", 277400d97012SDavid du Colombier " #error MA requires SEP_STATE in multi-core mode", 277500d97012SDavid du Colombier "#endif", 277600d97012SDavid du Colombier "#ifdef BFS", 2777*de2caf28SDavid du Colombier " #error instead of -DNCORE -DBFS use -DBFS_PAR", 277800d97012SDavid du Colombier "#endif", 277900d97012SDavid du Colombier "#ifdef SC", 278000d97012SDavid du Colombier " #error SC is not supported in multi-core mode", 278100d97012SDavid du Colombier "#endif", 278200d97012SDavid du Colombier " init_shm(); /* we are single threaded when this starts */", 278300d97012SDavid du Colombier " signal(SIGINT, give_up); /* windows control-c interrupt */", 278400d97012SDavid du Colombier "", 278500d97012SDavid du Colombier " if (core_id == 0 && verbose)", 278600d97012SDavid du Colombier " { printf(\"cpu0: step 4: creating additional workers (proxy %%d)\\n\",", 278700d97012SDavid du Colombier " proxy_pid);", 278800d97012SDavid du Colombier " }", 278900d97012SDavid du Colombier "#if 0", 279000d97012SDavid du Colombier " if NCORE > 1 the child or the parent should fork N-1 more times", 279100d97012SDavid du Colombier " the parent is the only process with core_id == 0 and is_parent > 0", 279200d97012SDavid du Colombier " the others (workers) have is_parent = 0 and core_id = 1..NCORE-1", 279300d97012SDavid du Colombier "#endif", 279400d97012SDavid du Colombier " if (core_id == 0) /* root starts up the workers */", 279500d97012SDavid du Colombier " { worker_pids[0] = (DWORD) getpid(); /* for completeness */", 279600d97012SDavid du Colombier " while (++core_id < NCORE) /* first worker sees core_id = 1 */", 279700d97012SDavid du Colombier " { char cmdline[64];", 279800d97012SDavid du Colombier " STARTUPINFO si = { sizeof(si) };", 279900d97012SDavid du Colombier " PROCESS_INFORMATION pi;", 280000d97012SDavid du Colombier "", 280100d97012SDavid du Colombier " if (proxy_pid == core_id) /* always non-zero */", 280200d97012SDavid du Colombier " { sprintf(cmdline, \"pan_proxy.exe -r %%s-Q%%d -Z%%d\",", 280300d97012SDavid du Colombier " o_cmdline, getpid(), core_id);", 280400d97012SDavid du Colombier " } else", 280500d97012SDavid du Colombier " { sprintf(cmdline, \"pan.exe %%s-Q%%d -Z%%d\",", 280600d97012SDavid du Colombier " o_cmdline, getpid(), core_id);", 280700d97012SDavid du Colombier " }", 280800d97012SDavid du Colombier " if (verbose) printf(\"cpu%%d: spawn %%s\\n\", core_id, cmdline);", 280900d97012SDavid du Colombier "", 281000d97012SDavid du Colombier " is_parent = CreateProcess(0, cmdline, 0, 0, FALSE, 0, 0, 0, &si, &pi);", 281100d97012SDavid du Colombier " if (is_parent == 0)", 281200d97012SDavid du Colombier " { Uerror(\"fork failed\");", 281300d97012SDavid du Colombier " }", 281400d97012SDavid du Colombier " worker_pids[core_id] = pi.dwProcessId;", 281500d97012SDavid du Colombier " worker_handles[core_id] = pi.hProcess;", 281600d97012SDavid du Colombier " if (verbose)", 281700d97012SDavid du Colombier " { cpu_printf(\"created core %%d, pid %%d\\n\",", 281800d97012SDavid du Colombier " core_id, pi.dwProcessId);", 281900d97012SDavid du Colombier " }", 282000d97012SDavid du Colombier " if (proxy_pid == core_id) /* we just created the receive half */", 282100d97012SDavid du Colombier " { /* add proxy send, store pid in proxy_pid_snd */", 282200d97012SDavid du Colombier " sprintf(cmdline, \"pan_proxy.exe -s %%s-Q%%d -Z%%d -Y%%d\",", 282300d97012SDavid du Colombier " o_cmdline, getpid(), core_id, worker_pids[proxy_pid]);", 282400d97012SDavid du Colombier " if (verbose) printf(\"cpu%%d: spawn %%s\\n\", core_id, cmdline);", 282500d97012SDavid du Colombier " is_parent = CreateProcess(0, cmdline, 0,0, FALSE, 0,0,0, &si, &pi);", 282600d97012SDavid du Colombier " if (is_parent == 0)", 282700d97012SDavid du Colombier " { Uerror(\"fork failed\");", 282800d97012SDavid du Colombier " }", 282900d97012SDavid du Colombier " proxy_pid_snd = pi.dwProcessId;", 283000d97012SDavid du Colombier " proxy_handle_snd = pi.hProcess;", 283100d97012SDavid du Colombier " if (verbose)", 283200d97012SDavid du Colombier " { cpu_printf(\"created core %%d, pid %%d (send proxy)\\n\",", 283300d97012SDavid du Colombier " core_id, pi.dwProcessId);", 283400d97012SDavid du Colombier " } } }", 283500d97012SDavid du Colombier " core_id = 0; /* reset core_id for root process */", 283600d97012SDavid du Colombier " } else /* worker */", 283700d97012SDavid du Colombier " { static char db0[16]; /* good for up to 10^6 cores */", 283800d97012SDavid du Colombier " static char db1[16];", 283900d97012SDavid du Colombier " tprefix = db0; sprefix = db1;", 284000d97012SDavid du Colombier " sprintf(tprefix, \"cpu%%d_trail\", core_id); /* avoid conflicts on file access */", 284100d97012SDavid du Colombier " sprintf(sprefix, \"cpu%%d_rst\", core_id);", 284200d97012SDavid du Colombier " memcnt = 0; /* count only additionally allocated memory */", 284300d97012SDavid du Colombier " }", 284400d97012SDavid du Colombier " if (verbose)", 284500d97012SDavid du Colombier " { cpu_printf(\"starting core_id %%d -- pid %%d\\n\", core_id, getpid());", 284600d97012SDavid du Colombier " }", 284700d97012SDavid du Colombier " if (core_id == 0 && !remote_party)", 284800d97012SDavid du Colombier " { new_state(); /* root starts the search */", 284900d97012SDavid du Colombier " if (verbose)", 285000d97012SDavid du Colombier " cpu_printf(\"done with 1st dfs, nstates %%g (put %%d states), start reading q\\n\",", 285100d97012SDavid du Colombier " nstates, nstates_put);", 285200d97012SDavid du Colombier " dfs_phase2 = 1;", 285300d97012SDavid du Colombier " }", 285400d97012SDavid du Colombier " Read_Queue(core_id); /* all cores */", 285500d97012SDavid du Colombier "", 285600d97012SDavid du Colombier " if (verbose)", 285700d97012SDavid du Colombier " { cpu_printf(\"put %%6d states into queue -- got %%6d\\n\",", 285800d97012SDavid du Colombier " nstates_put, nstates_get);", 285900d97012SDavid du Colombier " }", 286000d97012SDavid du Colombier " done = 1;", 286100d97012SDavid du Colombier " wrapup();", 286200d97012SDavid du Colombier " exit(0);", 286300d97012SDavid du Colombier "}", 286400d97012SDavid du Colombier "#endif", /* WIN32 || WIN64 */ 286500d97012SDavid du Colombier "", 286600d97012SDavid du Colombier "#ifdef BITSTATE", 286700d97012SDavid du Colombier "void", 286800d97012SDavid du Colombier "init_SS(unsigned long n)", 286900d97012SDavid du Colombier "{", 287000d97012SDavid du Colombier " SS = (uchar *) prep_shmid_S((size_t) n);", 287100d97012SDavid du Colombier " init_HT(0L);", /* locks and shared memory for Stack_Tree allocations */ 287200d97012SDavid du Colombier "}", 287300d97012SDavid du Colombier "#endif", /* BITSTATE */ 287400d97012SDavid du Colombier "", 287500d97012SDavid du Colombier "#endif", /* NCORE>1 */ 287600d97012SDavid du Colombier 0, 287700d97012SDavid du Colombier }; 2878