xref: /plan9-contrib/sys/src/cmd/spin/pangen6.h (revision de2caf28f9ba1a56e70be94a699435d36eb50311)
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