pangen6.h 89 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840
  1. /***** spin: pangen6.h *****/
  2. /* Copyright (c) 2006-2007 by the California Institute of Technology. */
  3. /* ALL RIGHTS RESERVED. United States Government Sponsorship acknowledged */
  4. /* Supporting routines for a multi-core extension of the SPIN software */
  5. /* Developed as part of Reliable Software Engineering Project ESAS/6G */
  6. /* Like all SPIN Software this software is for educational purposes only. */
  7. /* No guarantee whatsoever is expressed or implied by the distribution of */
  8. /* this code. Permission is given to distribute this code provided that */
  9. /* this introductory message is not removed and no monies are exchanged. */
  10. /* Any commercial use must be negotiated with the Office of Technology */
  11. /* Transfer at the California Institute of Technology. */
  12. /* Software written by Gerard J. Holzmann. For tool documentation see: */
  13. /* http://spinroot.com/ */
  14. /* Bug-reports and/or questions can be send to: bugs@spinroot.com */
  15. static char *Code2c[] = { /* multi-core option - Spin 5.0 and later */
  16. "#if NCORE>1",
  17. "#if defined(WIN32) || defined(WIN64)",
  18. " #ifndef _CONSOLE",
  19. " #define _CONSOLE",
  20. " #endif",
  21. " #ifdef WIN64",
  22. " #undef long",
  23. " #endif",
  24. " #include <windows.h>",
  25. " #ifdef WIN64",
  26. " #define long long long",
  27. " #endif",
  28. "#else",
  29. " #include <sys/ipc.h>",
  30. " #include <sys/sem.h>",
  31. " #include <sys/shm.h>",
  32. "#endif",
  33. "",
  34. "/* code common to cygwin/linux and win32/win64: */",
  35. "",
  36. "#ifdef VERBOSE",
  37. " #define VVERBOSE (1)",
  38. "#else",
  39. " #define VVERBOSE (0)",
  40. "#endif",
  41. "",
  42. "/* the following values must be larger than 256 and must fit in an int */",
  43. "#define QUIT 1024 /* terminate now command */",
  44. "#define QUERY 512 /* termination status query message */",
  45. "#define QUERY_F 513 /* query failed, cannot quit */",
  46. "",
  47. "#define GN_FRAMES (int) (GWQ_SIZE / (double) sizeof(SM_frame))",
  48. "#define LN_FRAMES (int) (LWQ_SIZE / (double) sizeof(SM_frame))",
  49. "",
  50. "#ifndef VMAX",
  51. " #define VMAX VECTORSZ",
  52. "#endif",
  53. "#ifndef PMAX",
  54. " #define PMAX 64",
  55. "#endif",
  56. "#ifndef QMAX",
  57. " #define QMAX 64",
  58. "#endif",
  59. "",
  60. "#if VECTORSZ>32000",
  61. " #define OFFT int",
  62. "#else",
  63. " #define OFFT short",
  64. "#endif",
  65. "",
  66. "#ifdef SET_SEG_SIZE",
  67. " /* no longer usefule -- being recomputed for local heap size anyway */",
  68. " double SEG_SIZE = (((double) SET_SEG_SIZE) * 1048576.);",
  69. "#else",
  70. " double SEG_SIZE = (1048576.*1024.); /* 1GB default shared memory pool segments */",
  71. "#endif",
  72. "",
  73. "double LWQ_SIZE = 0.; /* initialized in main */",
  74. "",
  75. "#ifdef SET_WQ_SIZE",
  76. " #ifdef NGQ",
  77. " #warning SET_WQ_SIZE applies to global queue -- ignored",
  78. " double GWQ_SIZE = 0.;",
  79. " #else",
  80. " double GWQ_SIZE = (((double) SET_WQ_SIZE) * 1048576.);",
  81. " /* must match the value in pan_proxy.c, if used */",
  82. " #endif",
  83. "#else",
  84. " #ifdef NGQ",
  85. " double GWQ_SIZE = 0.;",
  86. " #else",
  87. " double GWQ_SIZE = (128.*1048576.); /* 128 MB default queue sizes */",
  88. " #endif",
  89. "#endif",
  90. "",
  91. "/* Crash Detection Parameters */",
  92. "#ifndef ONESECOND",
  93. " #define ONESECOND (1<<25)", /* name is somewhat of a misnomer */
  94. "#endif",
  95. "#ifndef SHORT_T",
  96. " #define SHORT_T (0.1)",
  97. "#endif",
  98. "#ifndef LONG_T",
  99. " #define LONG_T (600)",
  100. "#endif",
  101. "",
  102. "double OneSecond = (double) (ONESECOND); /* waiting for a free slot -- checks crash */",
  103. "double TenSeconds = 10. * (ONESECOND); /* waiting for a lock -- check for a crash */",
  104. "",
  105. "/* Termination Detection Params -- waiting for new state input in Get_Full_Frame */",
  106. "double Delay = ((double) SHORT_T) * (ONESECOND); /* termination detection trigger */",
  107. "double OneHour = ((double) LONG_T) * (ONESECOND); /* timeout termination detection */",
  108. "",
  109. "typedef struct SM_frame SM_frame;",
  110. "typedef struct SM_results SM_results;",
  111. "typedef struct sh_Allocater sh_Allocater;",
  112. "",
  113. "struct SM_frame { /* about 6K per slot */",
  114. " volatile int m_vsize; /* 0 means free slot */",
  115. " volatile int m_boq; /* >500 is a control message */",
  116. "#ifdef FULL_TRAIL",
  117. " volatile struct Stack_Tree *m_stack; /* ptr to previous state */",
  118. "#endif",
  119. " volatile uchar m_tau;",
  120. " volatile uchar m_o_pm;",
  121. " volatile int nr_handoffs; /* to compute real_depth */",
  122. " volatile char m_now [VMAX];",
  123. " volatile char m_Mask [(VMAX + 7)/8];",
  124. " volatile OFFT m_p_offset[PMAX];",
  125. " volatile OFFT m_q_offset[QMAX];",
  126. " volatile uchar m_p_skip [PMAX];",
  127. " volatile uchar m_q_skip [QMAX];",
  128. "#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)",
  129. " volatile uchar m_c_stack [StackSize];",
  130. /* captures contents of c_stack[] for unmatched objects */
  131. "#endif",
  132. "};",
  133. "",
  134. "int proxy_pid; /* id of proxy if nonzero -- receive half */",
  135. "int store_proxy_pid;",
  136. "short remote_party;",
  137. "int proxy_pid_snd; /* id of proxy if nonzero -- send half */",
  138. "char o_cmdline[512]; /* to pass options to children */",
  139. "",
  140. "int iamin[CS_NR+NCORE]; /* non-shared */",
  141. "",
  142. "#if defined(WIN32) || defined(WIN64)",
  143. "int tas(volatile LONG *);",
  144. "",
  145. "HANDLE proxy_handle_snd; /* for Windows Create and Terminate */",
  146. "",
  147. "struct sh_Allocater { /* shared memory for states */",
  148. " volatile char *dc_arena; /* to allocate states from */",
  149. " volatile long pattern; /* to detect overruns */",
  150. " volatile long dc_size; /* nr of bytes left */",
  151. " volatile void *dc_start; /* where memory segment starts */",
  152. " volatile void *dc_id; /* to attach, detach, remove shared memory segments */",
  153. " volatile sh_Allocater *nxt; /* linked list of pools */",
  154. "};",
  155. "DWORD worker_pids[NCORE]; /* root mem of pids of all workers created */",
  156. "HANDLE worker_handles[NCORE]; /* for windows Create and Terminate */",
  157. "void * shmid [NR_QS]; /* return value from CreateFileMapping */",
  158. "void * shmid_M; /* shared mem for state allocation in hashtable */",
  159. "",
  160. "#ifdef SEP_STATE",
  161. " void *shmid_X;",
  162. "#else",
  163. " void *shmid_S; /* shared bitstate arena or hashtable */",
  164. "#endif",
  165. "#else",
  166. "int tas(volatile int *);",
  167. "",
  168. "struct sh_Allocater { /* shared memory for states */",
  169. " volatile char *dc_arena; /* to allocate states from */",
  170. " volatile long pattern; /* to detect overruns */",
  171. " volatile long dc_size; /* nr of bytes left */",
  172. " volatile char *dc_start; /* where memory segment starts */",
  173. " volatile int dc_id; /* to attach, detach, remove shared memory segments */",
  174. " volatile sh_Allocater *nxt; /* linked list of pools */",
  175. "};",
  176. "",
  177. "int worker_pids[NCORE]; /* root mem of pids of all workers created */",
  178. "int shmid [NR_QS]; /* return value from shmget */",
  179. "int nibis = 0; /* set after shared mem has been released */",
  180. "int shmid_M; /* shared mem for state allocation in hashtable */",
  181. "#ifdef SEP_STATE",
  182. " long shmid_X;",
  183. "#else",
  184. " int shmid_S; /* shared bitstate arena or hashtable */",
  185. " volatile sh_Allocater *first_pool; /* of shared state memory */",
  186. " volatile sh_Allocater *last_pool;",
  187. "#endif", /* SEP_STATE */
  188. "#endif", /* WIN32 || WIN64 */
  189. "",
  190. "struct SM_results { /* for shuttling back final stats */",
  191. " volatile int m_vsize; /* avoid conflicts with frames */",
  192. " volatile int m_boq; /* these 2 fields are not written in record_info */",
  193. " /* probably not all fields really need to be volatile */",
  194. " volatile double m_memcnt;",
  195. " volatile double m_nstates;",
  196. " volatile double m_truncs;",
  197. " volatile double m_truncs2;",
  198. " volatile double m_nShadow;",
  199. " volatile double m_nlinks;",
  200. " volatile double m_ngrabs;",
  201. " volatile double m_nlost;",
  202. " volatile double m_hcmp;",
  203. " volatile double m_frame_wait;",
  204. " volatile int m_hmax;",
  205. " volatile int m_svmax;",
  206. " volatile int m_smax;",
  207. " volatile int m_mreached;",
  208. " volatile int m_errors;",
  209. " volatile int m_VMAX;",
  210. " volatile short m_PMAX;",
  211. " volatile short m_QMAX;",
  212. " volatile uchar m_R; /* reached info for all proctypes */",
  213. "};",
  214. "",
  215. "int core_id = 0; /* internal process nr, to know which q to use */",
  216. "unsigned long nstates_put = 0; /* statistics */",
  217. "unsigned long nstates_get = 0;",
  218. "int query_in_progress = 0; /* termination detection */",
  219. "",
  220. "double free_wait = 0.; /* waiting for a free frame */",
  221. "double frame_wait = 0.; /* waiting for a full frame */",
  222. "double lock_wait = 0.; /* waiting for access to cs */",
  223. "double glock_wait[3]; /* waiting for access to global lock */",
  224. "",
  225. "char *sprefix = \"rst\";",
  226. "uchar was_interrupted, issued_kill, writing_trail;",
  227. "",
  228. "static SM_frame cur_Root; /* current root, to be safe with error trails */",
  229. "",
  230. "SM_frame *m_workq [NR_QS]; /* per cpu work queues + global q */",
  231. "char *shared_mem[NR_QS]; /* return value from shmat */",
  232. "#ifdef SEP_HEAP",
  233. "char *my_heap;",
  234. "long my_size;",
  235. "#endif",
  236. "volatile sh_Allocater *dc_shared; /* assigned at initialization */",
  237. "",
  238. "static int vmax_seen, pmax_seen, qmax_seen;",
  239. "static double gq_tries, gq_hasroom, gq_hasnoroom;",
  240. "",
  241. "volatile int *prfree;", /* [NCORE] */
  242. "volatile int *prfull;", /* [NCORE] */
  243. "volatile int *prcnt;", /* [NCORE] */
  244. "volatile int *prmax;", /* [NCORE] */
  245. "",
  246. "volatile int *sh_lock; /* mutual exclusion locks - in shared memory */",
  247. "volatile double *is_alive; /* to detect when processes crash */",
  248. "volatile int *grfree, *grfull, *grcnt, *grmax; /* access to shared global q */",
  249. "volatile double *gr_readmiss, *gr_writemiss;",
  250. "static int lrfree; /* used for temporary recording of slot */",
  251. "static int dfs_phase2;",
  252. "",
  253. "void mem_put(int); /* handoff state to other cpu */",
  254. "void mem_put_acc(void); /* liveness mode */",
  255. "void mem_get(void); /* get state from work queue */",
  256. "void sudden_stop(char *);",
  257. "#if 0",
  258. "void enter_critical(int);",
  259. "void leave_critical(int);",
  260. "#endif",
  261. "",
  262. "void",
  263. "record_info(SM_results *r)",
  264. "{ int i;",
  265. " uchar *ptr;",
  266. "",
  267. "#ifdef SEP_STATE",
  268. " if (0)",
  269. " { cpu_printf(\"nstates %%g nshadow %%g -- memory %%-6.3f Mb\\n\",",
  270. " nstates, nShadow, memcnt/(1048576.));",
  271. " }",
  272. " r->m_memcnt = 0;",
  273. "#else",
  274. " #ifdef BITSTATE",
  275. " r->m_memcnt = 0; /* it's shared */",
  276. " #endif",
  277. " r->m_memcnt = memcnt;",
  278. "#endif",
  279. " if (a_cycles && core_id == 1)",
  280. " { r->m_nstates = nstates;",
  281. " r->m_nShadow = nstates;",
  282. " } else",
  283. " { r->m_nstates = nstates;",
  284. " r->m_nShadow = nShadow;",
  285. " }",
  286. " r->m_truncs = truncs;",
  287. " r->m_truncs2 = truncs2;",
  288. " r->m_nlinks = nlinks;",
  289. " r->m_ngrabs = ngrabs;",
  290. " r->m_nlost = nlost;",
  291. " r->m_hcmp = hcmp;",
  292. " r->m_frame_wait = frame_wait;",
  293. " r->m_hmax = hmax;",
  294. " r->m_svmax = svmax;",
  295. " r->m_smax = smax;",
  296. " r->m_mreached = mreached;",
  297. " r->m_errors = errors;",
  298. " r->m_VMAX = vmax_seen;",
  299. " r->m_PMAX = (short) pmax_seen;",
  300. " r->m_QMAX = (short) qmax_seen;",
  301. " ptr = (uchar *) &(r->m_R);",
  302. " for (i = 0; i <= _NP_; i++) /* all proctypes */",
  303. " { memcpy(ptr, reached[i], NrStates[i]*sizeof(uchar));",
  304. " ptr += NrStates[i]*sizeof(uchar);",
  305. " }",
  306. " if (verbose>1)",
  307. " { cpu_printf(\"Put Results nstates %%g (sz %%d)\\n\", nstates, ptr - &(r->m_R));",
  308. " }",
  309. "}",
  310. "",
  311. "void snapshot(void);",
  312. "",
  313. "void",
  314. "retrieve_info(SM_results *r)",
  315. "{ int i, j;",
  316. " volatile uchar *ptr;",
  317. "",
  318. " snapshot(); /* for a final report */",
  319. "",
  320. " enter_critical(GLOBAL_LOCK);",
  321. "#ifdef SEP_HEAP",
  322. " if (verbose)",
  323. " { printf(\"cpu%%d: local heap-left %%ld KB (%%d MB)\\n\",",
  324. " core_id, (long) (my_size/1024), (int) (my_size/1048576));",
  325. " }",
  326. "#endif",
  327. " if (verbose && core_id == 0)",
  328. " { printf(\"qmax: \");",
  329. " for (i = 0; i < NCORE; i++)",
  330. " { printf(\"%%d \", prmax[i]);",
  331. " }",
  332. "#ifndef NGQ",
  333. " printf(\"G: %%d\", *grmax);",
  334. "#endif",
  335. " printf(\"\\n\");",
  336. " }",
  337. " leave_critical(GLOBAL_LOCK);",
  338. "",
  339. " memcnt += r->m_memcnt;",
  340. " nstates += r->m_nstates;",
  341. " nShadow += r->m_nShadow;",
  342. " truncs += r->m_truncs;",
  343. " truncs2 += r->m_truncs2;",
  344. " nlinks += r->m_nlinks;",
  345. " ngrabs += r->m_ngrabs;",
  346. " nlost += r->m_nlost;",
  347. " hcmp += r->m_hcmp;",
  348. " /* frame_wait += r->m_frame_wait; */",
  349. " errors += r->m_errors;",
  350. "",
  351. " if (hmax < r->m_hmax) hmax = r->m_hmax;",
  352. " if (svmax < r->m_svmax) svmax = r->m_svmax;",
  353. " if (smax < r->m_smax) smax = r->m_smax;",
  354. " if (mreached < r->m_mreached) mreached = r->m_mreached;",
  355. "",
  356. " if (vmax_seen < r->m_VMAX) vmax_seen = r->m_VMAX;",
  357. " if (pmax_seen < (int) r->m_PMAX) pmax_seen = (int) r->m_PMAX;",
  358. " if (qmax_seen < (int) r->m_QMAX) qmax_seen = (int) r->m_QMAX;",
  359. "",
  360. " ptr = &(r->m_R);",
  361. " for (i = 0; i <= _NP_; i++) /* all proctypes */",
  362. " { for (j = 0; j < NrStates[i]; j++)",
  363. " { if (*(ptr + j) != 0)",
  364. " { reached[i][j] = 1;",
  365. " } }",
  366. " ptr += NrStates[i]*sizeof(uchar);",
  367. " }",
  368. " if (verbose>1)",
  369. " { cpu_printf(\"Got Results (%%d)\\n\", (int) (ptr - &(r->m_R)));",
  370. " snapshot();",
  371. " }",
  372. "}",
  373. "",
  374. "#if !defined(WIN32) && !defined(WIN64)",
  375. "static void",
  376. "rm_shared_segments(void)",
  377. "{ int m;",
  378. " volatile sh_Allocater *nxt_pool;",
  379. " /*",
  380. " * mark all shared memory segments for removal ",
  381. " * the actual removes wont happen intil last process dies or detaches",
  382. " * the shmctl calls can return -1 if not all procs have detached yet",
  383. " */",
  384. " for (m = 0; m < NR_QS; m++) /* +1 for global q */",
  385. " { if (shmid[m] != -1)",
  386. " { (void) shmctl(shmid[m], IPC_RMID, NULL);",
  387. " } }",
  388. "#ifdef SEP_STATE",
  389. " if (shmid_M != -1)",
  390. " { (void) shmctl(shmid_M, IPC_RMID, NULL);",
  391. " }",
  392. "#else",
  393. " if (shmid_S != -1)",
  394. " { (void) shmctl(shmid_S, IPC_RMID, NULL);",
  395. " }",
  396. " for (last_pool = first_pool; last_pool != NULL; last_pool = nxt_pool)",
  397. " { shmid_M = (int) (last_pool->dc_id);",
  398. " nxt_pool = last_pool->nxt; /* as a pre-caution only */",
  399. " if (shmid_M != -1)",
  400. " { (void) shmctl(shmid_M, IPC_RMID, NULL);",
  401. " } }",
  402. "#endif",
  403. "}",
  404. "#endif",
  405. "",
  406. "void",
  407. "sudden_stop(char *s)",
  408. "{ char b[64];",
  409. " int i;",
  410. "",
  411. " printf(\"cpu%%d: stop - %%s\\n\", core_id, s);",
  412. "#if !defined(WIN32) && !defined(WIN64)",
  413. " if (proxy_pid != 0)",
  414. " { rm_shared_segments();",
  415. " }",
  416. "#endif",
  417. " if (search_terminated != NULL)",
  418. " { if (*search_terminated != 0)",
  419. " { if (verbose)",
  420. " { printf(\"cpu%%d: termination initiated (%%d)\\n\",",
  421. " core_id, *search_terminated);",
  422. " }",
  423. " } else",
  424. " { if (verbose)",
  425. " { printf(\"cpu%%d: initiated termination\\n\", core_id);",
  426. " }",
  427. " *search_terminated |= 8; /* sudden_stop */",
  428. " }",
  429. " if (core_id == 0)",
  430. " { if (((*search_terminated) & 4) /* uerror in one of the cpus */",
  431. " && !((*search_terminated) & (8|32|128|256))) /* abnormal stop */",
  432. " { if (errors == 0) errors++; /* we know there is at least 1 */",
  433. " }",
  434. " wrapup(); /* incomplete stats, but at least something */",
  435. " }",
  436. " return;",
  437. " } /* else: should rarely happen, take more drastic measures */",
  438. "",
  439. " if (core_id == 0) /* local root process */",
  440. " { for (i = 1; i < NCORE; i++) /* not for 0 of course */",
  441. " {",
  442. "#if defined(WIN32) || defined(WIN64)",
  443. " DWORD dwExitCode = 0;",
  444. " GetExitCodeProcess(worker_handles[i], &dwExitCode);",
  445. " if (dwExitCode == STILL_ACTIVE)",
  446. " { TerminateProcess(worker_handles[i], 0);",
  447. " }",
  448. " printf(\"cpu0: terminate %%d %%d\\n\",",
  449. " worker_pids[i], (dwExitCode == STILL_ACTIVE));",
  450. "#else",
  451. " sprintf(b, \"kill -%%d %%d\", SIGKILL, worker_pids[i]);",
  452. " system(b); /* if this is a proxy: receive half */",
  453. " printf(\"cpu0: %%s\\n\", b);",
  454. "#endif",
  455. " }",
  456. " issued_kill++;",
  457. " } else",
  458. " { /* on WIN32/WIN64 -- these merely kills the root process... */",
  459. " if (was_interrupted == 0)", /* 2=SIGINT to root to trigger stop */
  460. " { sprintf(b, \"kill -%%d %%d\", SIGINT, worker_pids[0]);",
  461. " system(b); /* warn the root process */",
  462. " printf(\"cpu%%d: %%s\\n\", core_id, b);",
  463. " issued_kill++;",
  464. " } }",
  465. "}",
  466. "",
  467. "#define iam_alive() is_alive[core_id]++", /* for crash detection */
  468. "",
  469. "extern int crash_test(double);",
  470. "extern void crash_reset(void);",
  471. "",
  472. "int",
  473. "someone_crashed(int wait_type)",
  474. "{ static double last_value = 0.0;",
  475. " static int count = 0;",
  476. "",
  477. " if (search_terminated == NULL",
  478. " || *search_terminated != 0)",
  479. " {",
  480. " if (!(*search_terminated & (8|32|128|256)))",
  481. " { if (count++ < 100*NCORE)",
  482. " { return 0;",
  483. " } }",
  484. " return 1;",
  485. " }",
  486. " /* check left neighbor only */",
  487. " if (last_value == is_alive[(core_id + NCORE - 1) %% NCORE])",
  488. " { if (count++ >= 100) /* to avoid unnecessary checks */",
  489. " { return 1;",
  490. " }",
  491. " return 0;",
  492. " }",
  493. " last_value = is_alive[(core_id + NCORE - 1) %% NCORE];",
  494. " count = 0;",
  495. " crash_reset();",
  496. " return 0;",
  497. "}",
  498. "",
  499. "void",
  500. "sleep_report(void)",
  501. "{",
  502. " enter_critical(GLOBAL_LOCK);",
  503. " if (verbose)",
  504. " {",
  505. "#ifdef NGQ",
  506. " printf(\"cpu%%d: locks: global %%g\\tother %%g\\t\",",
  507. " core_id, glock_wait[0], lock_wait - glock_wait[0]);",
  508. "#else",
  509. " printf(\"cpu%%d: locks: GL %%g, RQ %%g, WQ %%g, HT %%g\\t\",",
  510. " core_id, glock_wait[0], glock_wait[1], glock_wait[2],",
  511. " lock_wait - glock_wait[0] - glock_wait[1] - glock_wait[2]);",
  512. "#endif",
  513. " printf(\"waits: states %%g slots %%g\\n\", frame_wait, free_wait);",
  514. "#ifndef NGQ",
  515. " printf(\"cpu%%d: gq [tries %%g, room %%g, noroom %%g]\\n\", core_id, gq_tries, gq_hasroom, gq_hasnoroom);",
  516. " if (core_id == 0 && (*gr_readmiss >= 1.0 || *gr_readmiss >= 1.0 || *grcnt != 0))",
  517. " printf(\"cpu0: gq [readmiss: %%g, writemiss: %%g cnt %%d]\\n\", *gr_readmiss, *gr_writemiss, *grcnt);",
  518. "#endif",
  519. " }",
  520. " if (free_wait > 1000000.)",
  521. " #ifndef NGQ",
  522. " if (!a_cycles)",
  523. " { printf(\"hint: this search may be faster with a larger work-queue\\n\");",
  524. " printf(\" (-DSET_WQ_SIZE=N with N>%%g), and/or with -DUSE_DISK\\n\",",
  525. " GWQ_SIZE/sizeof(SM_frame));",
  526. " printf(\" or with a larger value for -zN (N>%%ld)\\n\", z_handoff);",
  527. " #else",
  528. " { printf(\"hint: this search may be faster if compiled without -DNGQ, with -DUSE_DISK, \");",
  529. " printf(\"or with a larger -zN (N>%%d)\\n\", z_handoff);",
  530. " #endif",
  531. " }",
  532. " leave_critical(GLOBAL_LOCK);",
  533. "}",
  534. "",
  535. "#ifndef MAX_DSK_FILE",
  536. " #define MAX_DSK_FILE 1000000 /* default is max 1M states per file */",
  537. "#endif",
  538. "",
  539. "void",
  540. "multi_usage(FILE *fd)",
  541. "{ static int warned = 0;",
  542. " if (warned > 0) { return; } else { warned++; }",
  543. " fprintf(fd, \"\\n\");",
  544. " fprintf(fd, \"Defining multi-core mode:\\n\\n\");",
  545. " fprintf(fd, \" -DDUAL_CORE --> same as -DNCORE=2\\n\");",
  546. " fprintf(fd, \" -DQUAD_CORE --> same as -DNCORE=4\\n\");",
  547. " fprintf(fd, \" -DNCORE=N --> enables multi_core verification if N>1\\n\");",
  548. " fprintf(fd, \"\\n\");",
  549. " fprintf(fd, \"Additional directives supported in multi-core mode:\\n\\n\");",
  550. " fprintf(fd, \" -DSEP_STATE --> forces separate statespaces instead of a single shared state space\\n\");",
  551. " fprintf(fd, \" -DNUSE_DISK --> use disk for storing states when a work queue overflows\\n\");",
  552. " fprintf(fd, \" -DMAX_DSK_FILE --> max nr of states per diskfile (%%d)\\n\", MAX_DSK_FILE);",
  553. " fprintf(fd, \" -DFULL_TRAIL --> support full error trails (increases memory use)\\n\");",
  554. " fprintf(fd, \"\\n\");",
  555. " fprintf(fd, \"More advanced use (should rarely need changing):\\n\\n\");",
  556. " fprintf(fd, \" To change the nr of states that can be stored in the global queue\\n\");",
  557. " fprintf(fd, \" (lower numbers allow for more states to be stored, prefer multiples of 8):\\n\");",
  558. " fprintf(fd, \" -DVMAX=N --> upperbound on statevector for handoffs (N=%%d)\\n\", VMAX);",
  559. " fprintf(fd, \" -DPMAX=N --> upperbound on nr of procs (default: N=%%d)\\n\", PMAX);",
  560. " fprintf(fd, \" -DQMAX=N --> upperbound on nr of channels (default: N=%%d)\\n\", QMAX);",
  561. " fprintf(fd, \"\\n\");",
  562. #if 0
  563. "#if !defined(WIN32) && !defined(WIN64)",
  564. " fprintf(fd, \" To change the size of spin's individual shared memory segments for cygwin/linux:\\n\");",
  565. " fprintf(fd, \" -DSET_SEG_SIZE=N --> default %%g (Mbytes)\\n\", SEG_SIZE/(1048576.));",
  566. " fprintf(fd, \"\\n\");",
  567. "#endif",
  568. #endif
  569. " fprintf(fd, \" To set the total amount of memory reserved for the global workqueue:\\n\");",
  570. " fprintf(fd, \" -DSET_WQ_SIZE=N --> default: N=128 (defined in MBytes)\\n\\n\");",
  571. #if 0
  572. " fprintf(fd, \" To omit the global workqueue completely (bad idea):\\n\");",
  573. " fprintf(fd, \" -DNGQ\\n\\n\");",
  574. #endif
  575. " fprintf(fd, \" To force the use of a single global heap, instead of separate heaps:\\n\");",
  576. " fprintf(fd, \" -DGLOB_HEAP\\n\");",
  577. " fprintf(fd, \"\\n\");",
  578. " fprintf(fd, \" To define a fct to initialize data before spawning processes (use quotes):\\n\");",
  579. " fprintf(fd, \" \\\"-DC_INIT=fct()\\\"\\n\");",
  580. " fprintf(fd, \"\\n\");",
  581. " fprintf(fd, \" Timer settings for termination and crash detection:\\n\");",
  582. " fprintf(fd, \" -DSHORT_T=N --> timeout for termination detection trigger (N=%%g)\\n\", (double) SHORT_T);",
  583. " fprintf(fd, \" -DLONG_T=N --> timeout for giving up on termination detection (N=%%g)\\n\", (double) LONG_T);",
  584. " fprintf(fd, \" -DONESECOND --> (1<<29) --> timeout waiting for a free slot -- to check for crash\\n\");",
  585. " fprintf(fd, \" -DT_ALERT --> collect stats on crash alert timeouts\\n\\n\");",
  586. " fprintf(fd, \"Help with Linux/Windows/Cygwin configuration for multi-core:\\n\");",
  587. " fprintf(fd, \" http://spinroot.com/spin/multicore/V5_Readme.html\\n\");",
  588. " fprintf(fd, \"\\n\");",
  589. "}",
  590. "#if NCORE>1 && defined(FULL_TRAIL)",
  591. "typedef struct Stack_Tree {",
  592. " uchar pr; /* process that made transition */",
  593. " T_ID t_id; /* id of transition */",
  594. " volatile struct Stack_Tree *prv; /* backward link towards root */",
  595. "} Stack_Tree;",
  596. "",
  597. "struct H_el *grab_shared(int);",
  598. "volatile Stack_Tree **stack_last; /* in shared memory */",
  599. "char *stack_cache = NULL; /* local */",
  600. "int nr_cached = 0; /* local */",
  601. "",
  602. "#ifndef CACHE_NR",
  603. " #define CACHE_NR 1024",
  604. "#endif",
  605. "",
  606. "volatile Stack_Tree *",
  607. "stack_prefetch(void)",
  608. "{ volatile Stack_Tree *st;",
  609. "",
  610. " if (nr_cached == 0)",
  611. " { stack_cache = (char *) grab_shared(CACHE_NR * sizeof(Stack_Tree));",
  612. " nr_cached = CACHE_NR;",
  613. " }",
  614. " st = (volatile Stack_Tree *) stack_cache;",
  615. " stack_cache += sizeof(Stack_Tree);",
  616. " nr_cached--;",
  617. " return st;",
  618. "}",
  619. "",
  620. "void",
  621. "Push_Stack_Tree(short II, T_ID t_id)",
  622. "{ volatile Stack_Tree *st;",
  623. "",
  624. " st = (volatile Stack_Tree *) stack_prefetch();",
  625. " st->pr = II;",
  626. " st->t_id = t_id;",
  627. " st->prv = (Stack_Tree *) stack_last[core_id];",
  628. " stack_last[core_id] = st;",
  629. "}",
  630. "",
  631. "void",
  632. "Pop_Stack_Tree(void)",
  633. "{ volatile Stack_Tree *cf = stack_last[core_id];",
  634. "",
  635. " if (cf)",
  636. " { stack_last[core_id] = cf->prv;",
  637. " } else if (nr_handoffs * z_handoff + depth > 0)",
  638. " { printf(\"cpu%%d: error pop_stack_tree (depth %%d)\\n\",",
  639. " core_id, depth);",
  640. " }",
  641. "}",
  642. "#endif", /* NCORE>1 && FULL_TRAIL */
  643. "",
  644. "void",
  645. "e_critical(int which)",
  646. "{ double cnt_start;",
  647. "",
  648. " if (readtrail || iamin[which] > 0)",
  649. " { if (!readtrail && verbose)",
  650. " { printf(\"cpu%%d: Double Lock on %%d (now %%d)\\n\",",
  651. " core_id, which, iamin[which]+1);",
  652. " fflush(stdout);",
  653. " }",
  654. " iamin[which]++; /* local variable */",
  655. " return;",
  656. " }",
  657. "",
  658. " cnt_start = lock_wait;",
  659. "",
  660. " while (sh_lock != NULL) /* as long as we have shared memory */",
  661. " { int r = tas(&sh_lock[which]);",
  662. " if (r == 0)",
  663. " { iamin[which] = 1;",
  664. " return; /* locked */",
  665. " }",
  666. "",
  667. " lock_wait++;",
  668. "#ifndef NGQ",
  669. " if (which < 3) { glock_wait[which]++; }",
  670. "#else",
  671. " if (which == 0) { glock_wait[which]++; }",
  672. "#endif",
  673. " iam_alive();",
  674. "",
  675. " if (lock_wait - cnt_start > TenSeconds)",
  676. " { printf(\"cpu%%d: lock timeout on %%d\\n\", core_id, which);",
  677. " cnt_start = lock_wait;",
  678. " if (someone_crashed(1))",
  679. " { sudden_stop(\"lock timeout\");",
  680. " pan_exit(1);",
  681. " } } }",
  682. "}",
  683. "",
  684. "void",
  685. "x_critical(int which)",
  686. "{",
  687. " if (iamin[which] != 1)",
  688. " { if (iamin[which] > 1)",
  689. " { iamin[which]--; /* this is thread-local - no races on this one */",
  690. " if (!readtrail && verbose)",
  691. " { printf(\"cpu%%d: Partial Unlock on %%d (%%d more needed)\\n\",",
  692. " core_id, which, iamin[which]);",
  693. " fflush(stdout);",
  694. " }",
  695. " return;",
  696. " } else /* iamin[which] <= 0 */",
  697. " { if (!readtrail)",
  698. " { printf(\"cpu%%d: Invalid Unlock iamin[%%d] = %%d\\n\",",
  699. " core_id, which, iamin[which]);",
  700. " fflush(stdout);",
  701. " }",
  702. " return;",
  703. " } }",
  704. "",
  705. " if (sh_lock != NULL)",
  706. " { iamin[which] = 0;",
  707. " sh_lock[which] = 0; /* unlock */",
  708. " }",
  709. "}",
  710. "",
  711. "void",
  712. "#if defined(WIN32) || defined(WIN64)",
  713. "start_proxy(char *s, DWORD r_pid)",
  714. "#else",
  715. "start_proxy(char *s, int r_pid)",
  716. "#endif",
  717. "{ char Q_arg[16], Z_arg[16], Y_arg[16];",
  718. " char *args[32], *ptr;",
  719. " int argcnt = 0;",
  720. "",
  721. " sprintf(Q_arg, \"-Q%%d\", getpid());",
  722. " sprintf(Y_arg, \"-Y%%d\", r_pid);",
  723. " sprintf(Z_arg, \"-Z%%d\", proxy_pid /* core_id */);",
  724. "",
  725. " args[argcnt++] = \"proxy\";",
  726. " args[argcnt++] = s; /* -r or -s */",
  727. " args[argcnt++] = Q_arg;",
  728. " args[argcnt++] = Z_arg;",
  729. " args[argcnt++] = Y_arg;",
  730. "",
  731. " if (strlen(o_cmdline) > 0)",
  732. " { ptr = o_cmdline; /* assume args separated by spaces */",
  733. " do { args[argcnt++] = ptr++;",
  734. " if ((ptr = strchr(ptr, ' ')) != NULL)",
  735. " { while (*ptr == ' ')",
  736. " { *ptr++ = '\\0';",
  737. " }",
  738. " } else",
  739. " { break;",
  740. " }",
  741. " } while (argcnt < 31);",
  742. " }",
  743. " args[argcnt] = NULL;",
  744. "#if defined(WIN32) || defined(WIN64)",
  745. " execvp(\"pan_proxy\", args); /* no return */",
  746. "#else",
  747. " execvp(\"./pan_proxy\", args); /* no return */",
  748. "#endif",
  749. " Uerror(\"pan_proxy exec failed\");",
  750. "}",
  751. "/*** end of common code fragment ***/",
  752. "",
  753. "#if !defined(WIN32) && !defined(WIN64)",
  754. "void",
  755. "init_shm(void) /* initialize shared work-queues - linux/cygwin */",
  756. "{ key_t key[NR_QS];",
  757. " int n, m;",
  758. " int must_exit = 0;",
  759. "",
  760. " if (core_id == 0 && verbose)",
  761. " { printf(\"cpu0: step 3: allocate shared workqueues %%g MB\\n\",",
  762. " ((double) NCORE * LWQ_SIZE + GWQ_SIZE) / (1048576.) );",
  763. " }",
  764. " for (m = 0; m < NR_QS; m++) /* last q is the global q */",
  765. " { double qsize = (m == NCORE) ? GWQ_SIZE : LWQ_SIZE;",
  766. " key[m] = ftok(PanSource, m+1);", /* m must be nonzero, 1..NCORE */
  767. " if (key[m] == -1)",
  768. " { perror(\"ftok shared queues\"); must_exit = 1; break;",
  769. " }",
  770. "",
  771. " if (core_id == 0) /* root creates */",
  772. " { /* check for stale copy */",
  773. " shmid[m] = shmget(key[m], (size_t) qsize, 0600);",
  774. " if (shmid[m] != -1) /* yes there is one; remove it */",
  775. " { printf(\"cpu0: removing stale q%%d, status: %%d\\n\",",
  776. " m, shmctl(shmid[m], IPC_RMID, NULL));",
  777. " }",
  778. " shmid[m] = shmget(key[m], (size_t) qsize, 0600|IPC_CREAT|IPC_EXCL);",
  779. " memcnt += qsize;",
  780. " } else /* workers attach */",
  781. " { shmid[m] = shmget(key[m], (size_t) qsize, 0600);",
  782. " /* never called, since we create shm *before* we fork */",
  783. " }",
  784. " if (shmid[m] == -1)",
  785. " { perror(\"shmget shared queues\"); must_exit = 1; break;",
  786. " }",
  787. "",
  788. " shared_mem[m] = (char *) shmat(shmid[m], (void *) 0, 0); /* attach */",
  789. " if (shared_mem[m] == (char *) -1)",
  790. " { fprintf(stderr, \"error: cannot attach shared wq %%d (%%d Mb)\\n\",",
  791. " m+1, (int) (qsize/(1048576.)));",
  792. " perror(\"shmat shared queues\"); must_exit = 1; break;",
  793. " }",
  794. "",
  795. " m_workq[m] = (SM_frame *) shared_mem[m];",
  796. " if (core_id == 0)",
  797. " { int nframes = (m == NCORE) ? GN_FRAMES : LN_FRAMES;",
  798. " for (n = 0; n < nframes; n++)",
  799. " { m_workq[m][n].m_vsize = 0;",
  800. " m_workq[m][n].m_boq = 0;",
  801. " } } }",
  802. "",
  803. " if (must_exit)",
  804. " { rm_shared_segments();",
  805. " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
  806. " pan_exit(1); /* calls cleanup_shm */",
  807. " }",
  808. "}",
  809. "",
  810. "static uchar *",
  811. "prep_shmid_S(size_t n) /* either sets SS or H_tab, linux/cygwin */",
  812. "{ char *rval;",
  813. "#ifndef SEP_STATE",
  814. " key_t key;",
  815. "",
  816. " if (verbose && core_id == 0)",
  817. " {",
  818. " #ifdef BITSTATE",
  819. " printf(\"cpu0: step 1: allocate shared bitstate %%g Mb\\n\",",
  820. " (double) n / (1048576.));",
  821. " #else",
  822. " printf(\"cpu0: step 1: allocate shared hastable %%g Mb\\n\",",
  823. " (double) n / (1048576.));",
  824. " #endif",
  825. " }",
  826. " #ifdef MEMLIM", /* memlim has a value */
  827. " if (memcnt + (double) n > memlim)",
  828. " { printf(\"cpu0: S %%8g + %%d Kb exceeds memory limit of %%8g Mb\\n\",",
  829. " memcnt/1024., (int) (n/1024), memlim/(1048576.));",
  830. " printf(\"cpu0: insufficient memory -- aborting\\n\");",
  831. " exit(1);",
  832. " }",
  833. " #endif",
  834. "",
  835. " key = ftok(PanSource, NCORE+2); /* different from queues */",
  836. " if (key == -1)",
  837. " { perror(\"ftok shared bitstate or hashtable\");",
  838. " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
  839. " pan_exit(1);",
  840. " }",
  841. "",
  842. " if (core_id == 0) /* root */",
  843. " { shmid_S = shmget(key, n, 0600);",
  844. " if (shmid_S != -1)",
  845. " { printf(\"cpu0: removing stale segment, status: %%d\\n\",",
  846. " (int) shmctl(shmid_S, IPC_RMID, NULL));",
  847. " }",
  848. " shmid_S = shmget(key, n, 0600 | IPC_CREAT | IPC_EXCL);",
  849. " memcnt += (double) n;",
  850. " } else /* worker */",
  851. " { shmid_S = shmget(key, n, 0600);",
  852. " }",
  853. " if (shmid_S == -1)",
  854. " { perror(\"shmget shared bitstate or hashtable too large?\");",
  855. " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
  856. " pan_exit(1);",
  857. " }",
  858. "",
  859. " rval = (char *) shmat(shmid_S, (void *) 0, 0); /* attach */",
  860. " if ((char *) rval == (char *) -1)",
  861. " { perror(\"shmat shared bitstate or hashtable\");",
  862. " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
  863. " pan_exit(1);",
  864. " }",
  865. "#else",
  866. " rval = (char *) emalloc(n);",
  867. "#endif",
  868. " return (uchar *) rval;",
  869. "}",
  870. "",
  871. "#define TRY_AGAIN 1",
  872. "#define NOT_AGAIN 0",
  873. "",
  874. "static char shm_prep_result;",
  875. "",
  876. "static uchar *",
  877. "prep_state_mem(size_t n) /* sets memory arena for states linux/cygwin */",
  878. "{ char *rval;",
  879. " key_t key;",
  880. " static int cnt = 3; /* start larger than earlier ftok calls */",
  881. "",
  882. " shm_prep_result = NOT_AGAIN; /* default */",
  883. " if (verbose && core_id == 0)",
  884. " { printf(\"cpu0: step 2+: pre-allocate memory arena %%d of %%6.2g Mb\\n\",",
  885. " cnt-3, (double) n / (1048576.));",
  886. " }",
  887. " #ifdef MEMLIM",
  888. " if (memcnt + (double) n > memlim)",
  889. " { printf(\"cpu0: error: M %%.0f + %%.0f Kb exceeds memory limit of %%.0f Mb\\n\",",
  890. " memcnt/1024.0, (double) n/1024.0, memlim/(1048576.));",
  891. " return NULL;",
  892. " }",
  893. " #endif",
  894. "",
  895. " key = ftok(PanSource, NCORE+cnt); cnt++;", /* starts at NCORE+3 */
  896. " if (key == -1)",
  897. " { perror(\"ftok T\");",
  898. " printf(\"pan: check './pan --' for usage details\\n\");",
  899. " pan_exit(1);",
  900. " }",
  901. "",
  902. " if (core_id == 0)",
  903. " { shmid_M = shmget(key, n, 0600);",
  904. " if (shmid_M != -1)",
  905. " { printf(\"cpu0: removing stale memory segment %%d, status: %%d\\n\",",
  906. " cnt-3, shmctl(shmid_M, IPC_RMID, NULL));",
  907. " }",
  908. " shmid_M = shmget(key, n, 0600 | IPC_CREAT | IPC_EXCL);",
  909. " /* memcnt += (double) n; -- only amount actually used is counted */",
  910. " } else",
  911. " { shmid_M = shmget(key, n, 0600);",
  912. " ",
  913. " }",
  914. " if (shmid_M == -1)",
  915. " { if (verbose)",
  916. " { printf(\"error: failed to get pool of shared memory %%d of %%.0f Mb\\n\",",
  917. " cnt-3, ((double)n)/(1048576.));",
  918. " perror(\"state mem\");",
  919. " printf(\"pan: check './pan --' for usage details\\n\");",
  920. " }",
  921. " shm_prep_result = TRY_AGAIN;",
  922. " return NULL;",
  923. " }",
  924. " rval = (char *) shmat(shmid_M, (void *) 0, 0); /* attach */",
  925. "",
  926. " if ((char *) rval == (char *) -1)",
  927. " { printf(\"cpu%%d error: failed to attach pool of shared memory %%d of %%.0f Mb\\n\",",
  928. " core_id, cnt-3, ((double)n)/(1048576.));",
  929. " perror(\"state mem\");",
  930. " return NULL;",
  931. " }",
  932. " return (uchar *) rval;",
  933. "}",
  934. "",
  935. "void",
  936. "init_HT(unsigned long n) /* cygwin/linux version */",
  937. "{ volatile char *x;",
  938. " double get_mem;",
  939. "#ifndef SEP_STATE",
  940. " volatile char *dc_mem_start;",
  941. " double need_mem, got_mem = 0.;",
  942. "#endif",
  943. "",
  944. "#ifdef SEP_STATE",
  945. " #ifndef MEMLIM",
  946. " if (verbose)",
  947. " { printf(\"cpu0: steps 0,1: no -DMEMLIM set\\n\");", /* cannot happen */
  948. " }",
  949. " #else",
  950. " if (verbose)",
  951. " { printf(\"cpu0: steps 0,1: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb)\\n\",",
  952. " MEMLIM, ((double)n/(1048576.)), (((double) NCORE * LWQ_SIZE) + GWQ_SIZE) /(1048576.) );",
  953. " }",
  954. " #endif",
  955. " get_mem = NCORE * sizeof(double) + (1 + CS_NR) * sizeof(void *) + 4*sizeof(void *) + 2*sizeof(double);",
  956. " /* NCORE * is_alive + search_terminated + CS_NR * sh_lock + 6 gr vars */",
  957. " get_mem += 4 * NCORE * sizeof(void *); /* prfree, prfull, prcnt, prmax */",
  958. " #ifdef FULL_TRAIL",
  959. " get_mem += (NCORE) * sizeof(Stack_Tree *); /* NCORE * stack_last */",
  960. " #endif",
  961. " x = (volatile char *) prep_state_mem((size_t) get_mem); /* work queues and basic structs */",
  962. " shmid_X = (long) x;",
  963. " if (x == NULL)", /* do not repeat for smaller sizes */
  964. " { printf(\"cpu0: could not allocate shared memory, see ./pan --\\n\");",
  965. " exit(1);",
  966. " }",
  967. " search_terminated = (volatile unsigned int *) x; /* comes first */",
  968. " x += sizeof(void *); /* maintain alignment */",
  969. "",
  970. " is_alive = (volatile double *) x;",
  971. " x += NCORE * sizeof(double);",
  972. "",
  973. " sh_lock = (volatile int *) x;",
  974. " x += CS_NR * sizeof(void *);", /* allow 1 word per entry */
  975. "",
  976. " grfree = (volatile int *) x;",
  977. " x += sizeof(void *);",
  978. " grfull = (volatile int *) x;",
  979. " x += sizeof(void *);",
  980. " grcnt = (volatile int *) x;",
  981. " x += sizeof(void *);",
  982. " grmax = (volatile int *) x;",
  983. " x += sizeof(void *);",
  984. " prfree = (volatile int *) x;",
  985. " x += NCORE * sizeof(void *);",
  986. " prfull = (volatile int *) x;",
  987. " x += NCORE * sizeof(void *);",
  988. " prcnt = (volatile int *) x;",
  989. " x += NCORE * sizeof(void *);",
  990. " prmax = (volatile int *) x;",
  991. " x += NCORE * sizeof(void *);",
  992. " gr_readmiss = (volatile double *) x;",
  993. " x += sizeof(double);",
  994. " gr_writemiss = (volatile double *) x;",
  995. " x += sizeof(double);",
  996. "",
  997. " #ifdef FULL_TRAIL",
  998. " stack_last = (volatile Stack_Tree **) x;",
  999. " x += NCORE * sizeof(Stack_Tree *);",
  1000. " #endif",
  1001. "",
  1002. " #ifndef BITSTATE",
  1003. " H_tab = (struct H_el **) emalloc(n);",
  1004. " #endif",
  1005. "#else",
  1006. " #ifndef MEMLIM",
  1007. " #warning MEMLIM not set", /* cannot happen */
  1008. " #define MEMLIM (2048)",
  1009. " #endif",
  1010. "",
  1011. " if (core_id == 0 && verbose)",
  1012. " { printf(\"cpu0: step 0: -DMEMLIM=%%d Mb minus hashtable+workqs (%%g + %%g Mb) leaves %%g Mb\\n\",",
  1013. " MEMLIM, ((double)n/(1048576.)), (NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.),",
  1014. " (memlim - memcnt - (double) n - (NCORE * LWQ_SIZE + GWQ_SIZE))/(1048576.));",
  1015. " }",
  1016. " #ifndef BITSTATE",
  1017. " H_tab = (struct H_el **) prep_shmid_S((size_t) n); /* hash_table */",
  1018. " #endif",
  1019. " need_mem = memlim - memcnt - ((double) NCORE * LWQ_SIZE) - GWQ_SIZE;",
  1020. " if (need_mem <= 0.)",
  1021. " { Uerror(\"internal error -- shared state memory\");",
  1022. " }",
  1023. "",
  1024. " if (core_id == 0 && verbose)",
  1025. " { printf(\"cpu0: step 2: pre-allocate shared state memory %%g Mb\\n\",",
  1026. " need_mem/(1048576.));",
  1027. " }",
  1028. "#ifdef SEP_HEAP",
  1029. " SEG_SIZE = need_mem / NCORE;",
  1030. " if (verbose && core_id == 0)",
  1031. " { printf(\"cpu0: setting segsize to %%6g MB\\n\",",
  1032. " SEG_SIZE/(1048576.));",
  1033. " }",
  1034. " #if defined(CYGWIN) || defined(__CYGWIN__)",
  1035. " if (SEG_SIZE > 512.*1024.*1024.)",
  1036. " { printf(\"warning: reducing SEG_SIZE of %%g MB to 512MB (exceeds max for Cygwin)\\n\",",
  1037. " SEG_SIZE/(1024.*1024.));",
  1038. " SEG_SIZE = 512.*1024.*1024.;",
  1039. " }",
  1040. " #endif",
  1041. "#endif",
  1042. " mem_reserved = need_mem;",
  1043. " while (need_mem > 1024.)",
  1044. " { get_mem = need_mem;",
  1045. "shm_more:",
  1046. " if (get_mem > (double) SEG_SIZE)",
  1047. " { get_mem = (double) SEG_SIZE;",
  1048. " }",
  1049. " if (get_mem <= 0.0) break;",
  1050. "",
  1051. " /* for allocating states: */",
  1052. " x = dc_mem_start = (volatile char *) prep_state_mem((size_t) get_mem);",
  1053. " if (x == NULL)",
  1054. " { if (shm_prep_result == NOT_AGAIN",
  1055. " || first_pool != NULL",
  1056. " || SEG_SIZE < (16. * 1048576.))",
  1057. " { break;",
  1058. " }",
  1059. " SEG_SIZE /= 2.;",
  1060. " if (verbose)",
  1061. " { printf(\"pan: lowered segsize to %f\\n\", SEG_SIZE);",
  1062. " }",
  1063. " if (SEG_SIZE >= 1024.)",
  1064. " { goto shm_more;", /* always terminates */
  1065. " }",
  1066. " break;",
  1067. " }",
  1068. "",
  1069. " need_mem -= get_mem;",
  1070. " got_mem += get_mem;",
  1071. " if (first_pool == NULL)",
  1072. " { search_terminated = (volatile unsigned int *) x; /* comes first */",
  1073. " x += sizeof(void *); /* maintain alignment */",
  1074. "",
  1075. " is_alive = (volatile double *) x;",
  1076. " x += NCORE * sizeof(double);",
  1077. "",
  1078. " sh_lock = (volatile int *) x;",
  1079. " x += CS_NR * sizeof(void *);", /* allow 1 word per entry */
  1080. "",
  1081. " grfree = (volatile int *) x;",
  1082. " x += sizeof(void *);",
  1083. " grfull = (volatile int *) x;",
  1084. " x += sizeof(void *);",
  1085. " grcnt = (volatile int *) x;",
  1086. " x += sizeof(void *);",
  1087. " grmax = (volatile int *) x;",
  1088. " x += sizeof(void *);",
  1089. " prfree = (volatile int *) x;",
  1090. " x += NCORE * sizeof(void *);",
  1091. " prfull = (volatile int *) x;",
  1092. " x += NCORE * sizeof(void *);",
  1093. " prcnt = (volatile int *) x;",
  1094. " x += NCORE * sizeof(void *);",
  1095. " prmax = (volatile int *) x;",
  1096. " x += NCORE * sizeof(void *);",
  1097. " gr_readmiss = (volatile double *) x;",
  1098. " x += sizeof(double);",
  1099. " gr_writemiss = (volatile double *) x;",
  1100. " x += sizeof(double);",
  1101. " #ifdef FULL_TRAIL",
  1102. " stack_last = (volatile Stack_Tree **) x;",
  1103. " x += NCORE * sizeof(Stack_Tree *);",
  1104. " #endif",
  1105. " if (((long)x)&(sizeof(void *)-1)) /* 64-bit word alignment */",
  1106. " { x += sizeof(void *)-(((long)x)&(sizeof(void *)-1));",
  1107. " }",
  1108. "",
  1109. " #ifdef COLLAPSE",
  1110. " ncomps = (unsigned long *) x;",
  1111. " x += (256+2) * sizeof(unsigned long);",
  1112. " #endif",
  1113. " }",
  1114. "",
  1115. " dc_shared = (sh_Allocater *) x; /* must be in shared memory */",
  1116. " x += sizeof(sh_Allocater);",
  1117. "",
  1118. " if (core_id == 0) /* root only */",
  1119. " { dc_shared->dc_id = shmid_M;",
  1120. " dc_shared->dc_start = dc_mem_start;",
  1121. " dc_shared->dc_arena = x;",
  1122. " dc_shared->pattern = 1234567; /* protection */",
  1123. " dc_shared->dc_size = (long) get_mem - (long) (x - dc_mem_start);",
  1124. " dc_shared->nxt = (long) 0;",
  1125. "",
  1126. " if (last_pool == NULL)",
  1127. " { first_pool = last_pool = dc_shared;",
  1128. " } else",
  1129. " { last_pool->nxt = dc_shared;",
  1130. " last_pool = dc_shared;",
  1131. " }",
  1132. " } else if (first_pool == NULL)",
  1133. " { first_pool = dc_shared;",
  1134. " } }",
  1135. "",
  1136. " if (need_mem > 1024.)",
  1137. " { printf(\"cpu0: could allocate only %%g Mb of shared memory (wanted %%g more)\\n\",",
  1138. " got_mem/(1048576.), need_mem/(1048576.));",
  1139. " }",
  1140. "",
  1141. " if (!first_pool)",
  1142. " { printf(\"cpu0: insufficient memory -- aborting.\\n\");",
  1143. " exit(1);",
  1144. " }",
  1145. " /* we are still single-threaded at this point, with core_id 0 */",
  1146. " dc_shared = first_pool;",
  1147. "",
  1148. "#endif", /* !SEP_STATE */
  1149. "}",
  1150. "",
  1151. " /* Test and Set assembly code */",
  1152. "",
  1153. " #if defined(i386) || defined(__i386__) || defined(__x86_64__)",
  1154. " int",
  1155. " tas(volatile int *s) /* tested */",
  1156. " { int r;",
  1157. " __asm__ __volatile__(",
  1158. " \"xchgl %%0, %%1 \\n\\t\"",
  1159. " : \"=r\"(r), \"=m\"(*s)",
  1160. " : \"0\"(1), \"m\"(*s)",
  1161. " : \"memory\");",
  1162. " ",
  1163. " return r;",
  1164. " }",
  1165. " #elif defined(__arm__)",
  1166. " int",
  1167. " tas(volatile int *s) /* not tested */",
  1168. " { int r = 1;",
  1169. " __asm__ __volatile__(",
  1170. " \"swpb %%0, %%0, [%%3] \\n\"",
  1171. " : \"=r\"(r), \"=m\"(*s)",
  1172. " : \"0\"(r), \"r\"(s));",
  1173. "",
  1174. " return r;",
  1175. " }",
  1176. " #elif defined(sparc) || defined(__sparc__)",
  1177. " int",
  1178. " tas(volatile int *s) /* not tested */",
  1179. " { int r = 1;",
  1180. " __asm__ __volatile__(",
  1181. " \" ldstub [%%2], %%0 \\n\"",
  1182. " : \"=r\"(r), \"=m\"(*s)",
  1183. " : \"r\"(s));",
  1184. "",
  1185. " return r;",
  1186. " }",
  1187. " #elif defined(ia64) || defined(__ia64__)",
  1188. " /* Intel Itanium */",
  1189. " int",
  1190. " tas(volatile int *s) /* tested */",
  1191. " { long int r;",
  1192. " __asm__ __volatile__(",
  1193. " \" xchg4 %%0=%%1,%%2 \\n\"",
  1194. " : \"=r\"(r), \"+m\"(*s)",
  1195. " : \"r\"(1)",
  1196. " : \"memory\");",
  1197. " return (int) r;",
  1198. " }",
  1199. " #else",
  1200. " #error missing definition of test and set operation for this platform",
  1201. " #endif",
  1202. "",
  1203. "void",
  1204. "cleanup_shm(int val)",
  1205. "{ volatile sh_Allocater *nxt_pool;",
  1206. " unsigned long cnt = 0;",
  1207. " int m;",
  1208. "",
  1209. " if (nibis != 0)",
  1210. " { printf(\"cpu%%d: Redundant call to cleanup_shm(%%d)\\n\", core_id, val);",
  1211. " return;",
  1212. " } else",
  1213. " { nibis = 1;",
  1214. " }",
  1215. " if (search_terminated != NULL)",
  1216. " { *search_terminated |= 16; /* cleanup_shm */",
  1217. " }",
  1218. "",
  1219. " for (m = 0; m < NR_QS; m++)",
  1220. " { if (shmdt((void *) shared_mem[m]) > 0)",
  1221. " { perror(\"shmdt detaching from shared queues\");",
  1222. " } }",
  1223. "",
  1224. "#ifdef SEP_STATE",
  1225. " if (shmdt((void *) shmid_X) != 0)",
  1226. " { perror(\"shmdt detaching from shared state memory\");",
  1227. " }",
  1228. "#else",
  1229. " #ifdef BITSTATE",
  1230. " if (SS > 0 && shmdt((void *) SS) != 0)",
  1231. " { if (verbose)",
  1232. " { perror(\"shmdt detaching from shared bitstate arena\");",
  1233. " } }",
  1234. " #else",
  1235. " if (core_id == 0)",
  1236. " { /* before detaching: */",
  1237. " for (nxt_pool = dc_shared; nxt_pool != NULL; nxt_pool = nxt_pool->nxt)",
  1238. " { cnt += nxt_pool->dc_size;",
  1239. " }",
  1240. " if (verbose)",
  1241. " { printf(\"cpu0: done, %%ld Mb of shared state memory left\\n\",",
  1242. " cnt / (long)(1048576));",
  1243. " } }",
  1244. "",
  1245. " if (shmdt((void *) H_tab) != 0)",
  1246. " { perror(\"shmdt detaching from shared hashtable\");",
  1247. " }",
  1248. "",
  1249. " for (last_pool = first_pool; last_pool != NULL; last_pool = nxt_pool)",
  1250. " { nxt_pool = last_pool->nxt;",
  1251. " if (shmdt((void *) last_pool->dc_start) != 0)",
  1252. " { perror(\"shmdt detaching from shared state memory\");",
  1253. " } }",
  1254. " first_pool = last_pool = NULL; /* precaution */",
  1255. " #endif",
  1256. "#endif",
  1257. " /* detached from shared memory - so cannot use cpu_printf */",
  1258. " if (verbose)",
  1259. " { printf(\"cpu%%d: done -- got %%ld states from queue\\n\",",
  1260. " core_id, nstates_get);",
  1261. " }",
  1262. "}",
  1263. "",
  1264. "extern void give_up(int);",
  1265. "extern void Read_Queue(int);",
  1266. "",
  1267. "void",
  1268. "mem_get(void)",
  1269. "{ SM_frame *f;",
  1270. " int is_parent;",
  1271. "",
  1272. "#if defined(MA) && !defined(SEP_STATE)",
  1273. " #error MA without SEP_STATE is not supported with multi-core",
  1274. "#endif",
  1275. "#ifdef BFS",
  1276. " #error BFS is not supported with multi-core",
  1277. "#endif",
  1278. "#ifdef SC",
  1279. " #error SC is not supported with multi-core",
  1280. "#endif",
  1281. " init_shm(); /* we are single threaded when this starts */",
  1282. "",
  1283. " if (core_id == 0 && verbose)",
  1284. " { printf(\"cpu0: step 4: calling fork()\\n\");",
  1285. " }",
  1286. " fflush(stdout);",
  1287. "",
  1288. "/* if NCORE > 1 the child or the parent should fork N-1 more times",
  1289. " * the parent is the only process with core_id == 0 and is_parent > 0",
  1290. " * the workers have is_parent = 0 and core_id = 1..NCORE-1",
  1291. " */",
  1292. " if (core_id == 0)",
  1293. " { worker_pids[0] = getpid(); /* for completeness */",
  1294. " while (++core_id < NCORE) /* first worker sees core_id = 1 */",
  1295. " { is_parent = fork();",
  1296. " if (is_parent == -1)",
  1297. " { Uerror(\"fork failed\");",
  1298. " }",
  1299. " if (is_parent == 0) /* this is a worker process */",
  1300. " { if (proxy_pid == core_id) /* always non-zero */",
  1301. " { start_proxy(\"-r\", 0); /* no return */",
  1302. " }",
  1303. " goto adapt; /* root process continues spawning */",
  1304. " }",
  1305. " worker_pids[core_id] = is_parent;",
  1306. " }",
  1307. " /* note that core_id is now NCORE */",
  1308. " if (proxy_pid > 0 && proxy_pid < NCORE)", /* add send-half of proxy */
  1309. " { proxy_pid_snd = fork();",
  1310. " if (proxy_pid_snd == -1)",
  1311. " { Uerror(\"proxy fork failed\");",
  1312. " }",
  1313. " if (proxy_pid_snd == 0)",
  1314. " { start_proxy(\"-s\", worker_pids[proxy_pid]); /* no return */",
  1315. " } } /* else continue */",
  1316. " if (is_parent > 0)",
  1317. " { core_id = 0; /* reset core_id for root process */",
  1318. " }",
  1319. " } else /* worker */",
  1320. " { static char db0[16]; /* good for up to 10^6 cores */",
  1321. " static char db1[16];",
  1322. "adapt: tprefix = db0; sprefix = db1;",
  1323. " sprintf(tprefix, \"cpu%%d_trail\", core_id);",
  1324. " sprintf(sprefix, \"cpu%%d_rst\", core_id);",
  1325. " memcnt = 0; /* count only additionally allocated memory */",
  1326. " }",
  1327. " signal(SIGINT, give_up);",
  1328. "",
  1329. " if (proxy_pid == 0) /* not in a cluster setup, pan_proxy must attach */",
  1330. " { rm_shared_segments(); /* mark all shared segments for removal on exit */",
  1331. " }", /* doing it early means less chance of being unable to do this */
  1332. " if (verbose)",
  1333. " { cpu_printf(\"starting core_id %%d -- pid %%d\\n\", core_id, getpid());",
  1334. " }",
  1335. "#if defined(SEP_HEAP) && !defined(SEP_STATE)", /* set my_heap and adjust dc_shared */
  1336. " { int i;",
  1337. " volatile sh_Allocater *ptr;",
  1338. " ptr = first_pool;",
  1339. " for (i = 0; i < NCORE && ptr != NULL; i++)",
  1340. " { if (i == core_id)",
  1341. " { my_heap = (char *) ptr->dc_arena;",
  1342. " my_size = (long) ptr->dc_size;",
  1343. " if (verbose)",
  1344. " cpu_printf(\"local heap %%ld MB\\n\", my_size/(1048576));",
  1345. " break;",
  1346. " }",
  1347. " ptr = ptr->nxt; /* local */",
  1348. " }",
  1349. " if (my_heap == NULL)",
  1350. " { printf(\"cpu%%d: no local heap\\n\", core_id);",
  1351. " pan_exit(1);",
  1352. " } /* else */",
  1353. " #if defined(CYGWIN) || defined(__CYGWIN__)",
  1354. " ptr = first_pool;",
  1355. " for (i = 0; i < NCORE && ptr != NULL; i++)",
  1356. " { ptr = ptr->nxt; /* local */",
  1357. " }",
  1358. " dc_shared = ptr; /* any remainder */",
  1359. " #else",
  1360. " dc_shared = NULL; /* used all mem for local heaps */",
  1361. " #endif",
  1362. " }",
  1363. "#endif",
  1364. " if (core_id == 0 && !remote_party)",
  1365. " { new_state(); /* cpu0 explores root */",
  1366. " if (verbose)",
  1367. " cpu_printf(\"done with 1st dfs, nstates %%g (put %%d states), read q\\n\",",
  1368. " nstates, nstates_put);",
  1369. " dfs_phase2 = 1;",
  1370. " }",
  1371. " Read_Queue(core_id); /* all cores */",
  1372. "",
  1373. " if (verbose)",
  1374. " { cpu_printf(\"put %%6d states into queue -- got %%6d\\n\",",
  1375. " nstates_put, nstates_get);",
  1376. " }",
  1377. " if (proxy_pid != 0)",
  1378. " { rm_shared_segments();",
  1379. " }",
  1380. " done = 1;",
  1381. " wrapup();",
  1382. " exit(0);",
  1383. "}",
  1384. "",
  1385. "#else",
  1386. "int unpack_state(SM_frame *, int);",
  1387. "#endif",
  1388. "",
  1389. "struct H_el *",
  1390. "grab_shared(int n)",
  1391. "{",
  1392. "#ifndef SEP_STATE",
  1393. " char *rval = (char *) 0;",
  1394. "",
  1395. " if (n == 0)",
  1396. " { printf(\"cpu%%d: grab shared zero\\n\", core_id); fflush(stdout);",
  1397. " return (struct H_el *) rval;",
  1398. " } else if (n&(sizeof(void *)-1))",
  1399. " { n += sizeof(void *)-(n&(sizeof(void *)-1)); /* alignment */",
  1400. " }",
  1401. "",
  1402. "#ifdef SEP_HEAP",
  1403. " /* no locking */",
  1404. " if (my_heap != NULL && my_size > n)",
  1405. " { rval = my_heap;",
  1406. " my_heap += n;",
  1407. " my_size -= n;",
  1408. " goto done;",
  1409. " }",
  1410. "#endif",
  1411. "",
  1412. " if (!dc_shared)",
  1413. " { sudden_stop(\"pan: out of memory\");",
  1414. " }",
  1415. "",
  1416. " /* another lock is always already in effect when this is called */",
  1417. " /* but not always the same lock -- i.e., on different parts of the hashtable */",
  1418. " enter_critical(GLOBAL_LOCK); /* this must be independently mutex */",
  1419. "#if defined(SEP_HEAP) && !defined(WIN32) && !defined(WIN64)",
  1420. " { static int noted = 0;",
  1421. " if (!noted)",
  1422. " { noted = 1;",
  1423. " printf(\"cpu%%d: global heap has %%ld bytes left, needed %%d\\n\",",
  1424. " core_id, dc_shared?dc_shared->dc_size:0, n);",
  1425. " } }",
  1426. "#endif",
  1427. "#if 0", /* for debugging */
  1428. " if (dc_shared->pattern != 1234567)",
  1429. " { leave_critical(GLOBAL_LOCK);",
  1430. " Uerror(\"overrun -- memory corruption\");",
  1431. " }",
  1432. "#endif",
  1433. " if (dc_shared->dc_size < n)",
  1434. " { if (verbose)",
  1435. " { printf(\"Next Pool %%g Mb + %%d\\n\", memcnt/(1048576.), n);",
  1436. " }",
  1437. " if (dc_shared->nxt == NULL",
  1438. " || dc_shared->nxt->dc_arena == NULL",
  1439. " || dc_shared->nxt->dc_size < n)",
  1440. " { printf(\"cpu%%d: memcnt %%g Mb + wanted %%d bytes more\\n\",",
  1441. " core_id, memcnt / (1048576.), n);",
  1442. " leave_critical(GLOBAL_LOCK);",
  1443. " sudden_stop(\"out of memory -- aborting\");",
  1444. " wrapup(); /* exits */",
  1445. " } else",
  1446. " { dc_shared = (sh_Allocater *) dc_shared->nxt;",
  1447. " } }",
  1448. "",
  1449. " rval = (char *) dc_shared->dc_arena;",
  1450. " dc_shared->dc_arena += n;",
  1451. " dc_shared->dc_size -= (long) n;",
  1452. "#if 0",
  1453. " if (VVERBOSE)",
  1454. " printf(\"cpu%%d grab shared (%%d bytes) -- %%ld left\\n\",",
  1455. " core_id, n, dc_shared->dc_size);",
  1456. "#endif",
  1457. " leave_critical(GLOBAL_LOCK);",
  1458. "done:",
  1459. " memset(rval, 0, n);",
  1460. " memcnt += (double) n;",
  1461. "",
  1462. " return (struct H_el *) rval;",
  1463. "#else",
  1464. " return (struct H_el *) emalloc(n);",
  1465. "#endif",
  1466. "}",
  1467. "",
  1468. "SM_frame *",
  1469. "Get_Full_Frame(int n)",
  1470. "{ SM_frame *f;",
  1471. " double cnt_start = frame_wait;",
  1472. "",
  1473. " f = &m_workq[n][prfull[n]];",
  1474. " while (f->m_vsize == 0) /* await full slot LOCK : full frame */",
  1475. " { iam_alive();",
  1476. "#ifndef NGQ",
  1477. " #ifndef SAFETY",
  1478. " if (!a_cycles || core_id != 0)",
  1479. " #endif",
  1480. " if (*grcnt > 0) /* accessed outside lock, but safe even if wrong */",
  1481. " { enter_critical(GQ_RD); /* gq - read access */",
  1482. " if (*grcnt > 0) /* could have changed */",
  1483. " { f = &m_workq[NCORE][*grfull]; /* global q */",
  1484. " if (f->m_vsize == 0)",
  1485. " { /* writer is still filling the slot */",
  1486. " *gr_writemiss++;",
  1487. " f = &m_workq[n][prfull[n]]; /* reset */",
  1488. " } else",
  1489. " { *grfull = (*grfull+1) %% (GN_FRAMES);",
  1490. " enter_critical(GQ_WR);",
  1491. " *grcnt = *grcnt - 1;",
  1492. " leave_critical(GQ_WR);",
  1493. " leave_critical(GQ_RD);",
  1494. " return f;",
  1495. " } }",
  1496. " leave_critical(GQ_RD);",
  1497. " }",
  1498. "#endif",
  1499. " if (frame_wait++ - cnt_start > Delay)",
  1500. " { if (0)", /* too frequent to enable this one */
  1501. " { cpu_printf(\"timeout on q%%d -- %%u -- query %%d\\n\",",
  1502. " n, f, query_in_progress);",
  1503. " }",
  1504. " return (SM_frame *) 0; /* timeout */",
  1505. " } }",
  1506. " iam_alive();",
  1507. " if (VVERBOSE) cpu_printf(\"got frame from q%%d\\n\", n);",
  1508. " prfull[n] = (prfull[n] + 1) %% (LN_FRAMES);",
  1509. " enter_critical(QLOCK(n));",
  1510. " prcnt[n]--; /* lock out increments */",
  1511. " leave_critical(QLOCK(n));",
  1512. " return f;",
  1513. "}",
  1514. "",
  1515. "SM_frame *",
  1516. "Get_Free_Frame(int n)",
  1517. "{ SM_frame *f;",
  1518. " double cnt_start = free_wait;",
  1519. "",
  1520. " if (VVERBOSE) { cpu_printf(\"get free frame from q%%d\\n\", n); }",
  1521. "",
  1522. " if (n == NCORE) /* global q */",
  1523. " { f = &(m_workq[n][lrfree]);",
  1524. " } else",
  1525. " { f = &(m_workq[n][prfree[n]]);",
  1526. " }",
  1527. " while (f->m_vsize != 0) /* await free slot LOCK : free slot */",
  1528. " { iam_alive();",
  1529. " if (free_wait++ - cnt_start > OneSecond)",
  1530. " { if (verbose)",
  1531. " { cpu_printf(\"timeout waiting for free slot q%%d\\n\", n);",
  1532. " }",
  1533. " cnt_start = free_wait;",
  1534. " if (someone_crashed(1))",
  1535. " { printf(\"cpu%%d: search terminated\\n\", core_id);",
  1536. " sudden_stop(\"get free frame\");",
  1537. " pan_exit(1);",
  1538. " } } }",
  1539. " if (n != NCORE)",
  1540. " { prfree[n] = (prfree[n] + 1) %% (LN_FRAMES);",
  1541. " enter_critical(QLOCK(n));",
  1542. " prcnt[n]++; /* lock out decrements */",
  1543. " if (prmax[n] < prcnt[n])",
  1544. " { prmax[n] = prcnt[n];",
  1545. " }",
  1546. " leave_critical(QLOCK(n));",
  1547. " }",
  1548. " return f;",
  1549. "}",
  1550. "",
  1551. "#ifndef NGQ",
  1552. "int",
  1553. "GlobalQ_HasRoom(void)",
  1554. "{ int rval = 0;",
  1555. "",
  1556. " gq_tries++;",
  1557. " if (*grcnt < GN_FRAMES) /* there seems to be room */",
  1558. " { enter_critical(GQ_WR); /* gq write access */",
  1559. " if (*grcnt < GN_FRAMES)",
  1560. " { if (m_workq[NCORE][*grfree].m_vsize != 0)",
  1561. " { /* can happen if reader is slow emptying slot */",
  1562. " *gr_readmiss++;",
  1563. " goto out; /* dont wait: release lock and return */",
  1564. " }",
  1565. " lrfree = *grfree; /* Get_Free_Frame use lrfree in this mode */",
  1566. " *grfree = (*grfree + 1) %% GN_FRAMES;", /* next process looks at next slot */
  1567. " *grcnt = *grcnt + 1; /* count nr of slots filled -- no additional lock needed */",
  1568. " if (*grmax < *grcnt) *grmax = *grcnt;",
  1569. " leave_critical(GQ_WR); /* for short lock duration */",
  1570. " gq_hasroom++;",
  1571. " mem_put(NCORE); /* copy state into reserved slot */",
  1572. " rval = 1; /* successfull handoff */",
  1573. " } else",
  1574. " { gq_hasnoroom++;",
  1575. "out: leave_critical(GQ_WR);", /* should be rare */
  1576. " } }",
  1577. " return rval;",
  1578. "}",
  1579. "#endif",
  1580. "",
  1581. "int",
  1582. "unpack_state(SM_frame *f, int from_q)",
  1583. "{ int i, j;",
  1584. " static struct H_el D_State;",
  1585. "",
  1586. " if (f->m_vsize > 0)",
  1587. " { boq = f->m_boq;",
  1588. " if (boq > 256)",
  1589. " { cpu_printf(\"saw control %%d, expected state\\n\", boq);",
  1590. " return 0;",
  1591. " }",
  1592. " vsize = f->m_vsize;",
  1593. "correct:",
  1594. " memcpy((uchar *) &now, (uchar *) f->m_now, vsize);",
  1595. " for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)",
  1596. " { Mask[i] = (f->m_Mask[i/8] & (1<<j)) ? 1 : 0;",
  1597. " }",
  1598. " if (now._nr_pr > 0)",
  1599. " { memcpy((uchar *) proc_offset, (uchar *) f->m_p_offset, now._nr_pr * sizeof(OFFT));",
  1600. " memcpy((uchar *) proc_skip, (uchar *) f->m_p_skip, now._nr_pr * sizeof(uchar));",
  1601. " }",
  1602. " if (now._nr_qs > 0)",
  1603. " { memcpy((uchar *) q_offset, (uchar *) f->m_q_offset, now._nr_qs * sizeof(OFFT));",
  1604. " memcpy((uchar *) q_skip, (uchar *) f->m_q_skip, now._nr_qs * sizeof(uchar));",
  1605. " }",
  1606. "#ifndef NOVSZ",
  1607. " if (vsize != now._vsz)",
  1608. " { cpu_printf(\"vsize %%d != now._vsz %%d (type %%d) %%d\\n\",",
  1609. " vsize, now._vsz, f->m_boq, f->m_vsize);",
  1610. " vsize = now._vsz;",
  1611. " goto correct; /* rare event: a race */",
  1612. " }",
  1613. "#endif",
  1614. " hmax = max(hmax, vsize);",
  1615. "",
  1616. " if (f != &cur_Root)",
  1617. " { memcpy((uchar *) &cur_Root, (uchar *) f, sizeof(SM_frame));",
  1618. " }",
  1619. "",
  1620. " if (((now._a_t) & 1) == 1) /* i.e., when starting nested DFS */",
  1621. " { A_depth = depthfound = 0;",
  1622. " memcpy((uchar *)&A_Root, (uchar *)&now, vsize);",
  1623. " }",
  1624. " nr_handoffs = f->nr_handoffs;",
  1625. " } else",
  1626. " { cpu_printf(\"pan: state empty\\n\");",
  1627. " }",
  1628. "",
  1629. " depth = 0;",
  1630. " trpt = &trail[1];",
  1631. " trpt->tau = f->m_tau;",
  1632. " trpt->o_pm = f->m_o_pm;",
  1633. "",
  1634. " (trpt-1)->ostate = &D_State; /* stub */",
  1635. " trpt->ostate = &D_State;",
  1636. "",
  1637. "#ifdef FULL_TRAIL",
  1638. " if (upto > 0)",
  1639. " { stack_last[core_id] = (Stack_Tree *) f->m_stack;",
  1640. " }",
  1641. " #if defined(VERBOSE)",
  1642. " if (stack_last[core_id])",
  1643. " { cpu_printf(\"%%d: UNPACK -- SET m_stack %%u (%%d,%%d)\\n\",",
  1644. " depth, stack_last[core_id], stack_last[core_id]->pr,",
  1645. " stack_last[core_id]->t_id);",
  1646. " }",
  1647. " #endif",
  1648. "#endif",
  1649. "",
  1650. " if (!trpt->o_t)",
  1651. " { static Trans D_Trans;",
  1652. " trpt->o_t = &D_Trans;",
  1653. " }",
  1654. "",
  1655. " #ifdef VERI",
  1656. " if ((trpt->tau & 4) != 4)",
  1657. " { trpt->tau |= 4; /* the claim moves first */",
  1658. " cpu_printf(\"warning: trpt was not up to date\\n\");",
  1659. " }",
  1660. " #endif",
  1661. "",
  1662. " for (i = 0; i < (int) now._nr_pr; i++)",
  1663. " { P0 *ptr = (P0 *) pptr(i);",
  1664. " #ifndef NP",
  1665. " if (accpstate[ptr->_t][ptr->_p])",
  1666. " { trpt->o_pm |= 2;",
  1667. " }",
  1668. " #else",
  1669. " if (progstate[ptr->_t][ptr->_p])",
  1670. " { trpt->o_pm |= 4;",
  1671. " }",
  1672. " #endif",
  1673. " }",
  1674. "",
  1675. " #ifdef EVENT_TRACE",
  1676. " #ifndef NP",
  1677. " if (accpstate[EVENT_TRACE][now._event])",
  1678. " { trpt->o_pm |= 2;",
  1679. " }",
  1680. " #else",
  1681. " if (progstate[EVENT_TRACE][now._event])",
  1682. " { trpt->o_pm |= 4;",
  1683. " }",
  1684. " #endif",
  1685. " #endif",
  1686. "",
  1687. " #if defined(C_States) && (HAS_TRACK==1)",
  1688. " /* restore state of tracked C objects */",
  1689. " c_revert((uchar *) &(now.c_state[0]));",
  1690. " #if (HAS_STACK==1)",
  1691. " c_unstack((uchar *) f->m_c_stack); /* unmatched tracked data */",
  1692. " #endif",
  1693. " #endif",
  1694. " return 1;",
  1695. "}",
  1696. "",
  1697. "void",
  1698. "write_root(void) /* for trail file */",
  1699. "{ int fd;",
  1700. "",
  1701. " if (iterative == 0 && Nr_Trails > 1)",
  1702. " sprintf(fnm, \"%%s%%d.%%s\", TrailFile, Nr_Trails-1, sprefix);",
  1703. " else",
  1704. " sprintf(fnm, \"%%s.%%s\", TrailFile, sprefix);",
  1705. "",
  1706. " if (cur_Root.m_vsize == 0)",
  1707. " { (void) unlink(fnm); /* remove possible old copy */",
  1708. " return; /* its the default initial state */",
  1709. " }",
  1710. "",
  1711. " if ((fd = creat(fnm, TMODE)) < 0)",
  1712. " { char *q;",
  1713. " if ((q = strchr(TrailFile, \'.\')))",
  1714. " { *q = \'\\0\'; /* strip .pml */",
  1715. " if (iterative == 0 && Nr_Trails-1 > 0)",
  1716. " sprintf(fnm, \"%%s%%d.%%s\", TrailFile, Nr_Trails-1, sprefix);",
  1717. " else",
  1718. " sprintf(fnm, \"%%s.%%s\", TrailFile, sprefix);",
  1719. " *q = \'.\';",
  1720. " fd = creat(fnm, TMODE);",
  1721. " }",
  1722. " if (fd < 0)",
  1723. " { cpu_printf(\"pan: cannot create %%s\\n\", fnm);",
  1724. " perror(\"cause\");",
  1725. " return;",
  1726. " } }",
  1727. "",
  1728. " if (write(fd, &cur_Root, sizeof(SM_frame)) != sizeof(SM_frame))",
  1729. " { cpu_printf(\"pan: error writing %%s\\n\", fnm);",
  1730. " } else",
  1731. " { cpu_printf(\"pan: wrote %%s\\n\", fnm);",
  1732. " }",
  1733. " close(fd);",
  1734. "}",
  1735. "",
  1736. "void",
  1737. "set_root(void)",
  1738. "{ int fd;",
  1739. " char *q;",
  1740. " char MyFile[512];", /* enough to hold a reasonable pathname */
  1741. " char MySuffix[16];",
  1742. " char *ssuffix = \"rst\";",
  1743. " int try_core = 1;",
  1744. "",
  1745. " strcpy(MyFile, TrailFile);",
  1746. "try_again:",
  1747. " if (whichtrail > 0)",
  1748. " { sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, ssuffix);",
  1749. " fd = open(fnm, O_RDONLY, 0);",
  1750. " if (fd < 0 && (q = strchr(MyFile, \'.\')))",
  1751. " { *q = \'\\0\'; /* strip .pml */",
  1752. " sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, ssuffix);",
  1753. " *q = \'.\';",
  1754. " fd = open(fnm, O_RDONLY, 0);",
  1755. " }",
  1756. " } else",
  1757. " { sprintf(fnm, \"%%s.%%s\", MyFile, ssuffix);",
  1758. " fd = open(fnm, O_RDONLY, 0);",
  1759. " if (fd < 0 && (q = strchr(MyFile, \'.\')))",
  1760. " { *q = \'\\0\'; /* strip .pml */",
  1761. " sprintf(fnm, \"%%s.%%s\", MyFile, ssuffix);",
  1762. " *q = \'.\';",
  1763. " fd = open(fnm, O_RDONLY, 0);",
  1764. " } }",
  1765. "",
  1766. " if (fd < 0)",
  1767. " { if (try_core < NCORE)",
  1768. " { ssuffix = MySuffix;",
  1769. " sprintf(ssuffix, \"cpu%%d_rst\", try_core++);",
  1770. " goto try_again;",
  1771. " }",
  1772. " cpu_printf(\"no file '%%s.rst' or '%%s' (not an error)\\n\", MyFile, fnm);",
  1773. " } else",
  1774. " { if (read(fd, &cur_Root, sizeof(SM_frame)) != sizeof(SM_frame))",
  1775. " { cpu_printf(\"read error %%s\\n\", fnm);",
  1776. " close(fd);",
  1777. " pan_exit(1);",
  1778. " }",
  1779. " close(fd);",
  1780. " (void) unpack_state(&cur_Root, -2);",
  1781. "#ifdef SEP_STATE",
  1782. " cpu_printf(\"partial trail -- last few steps only\\n\");",
  1783. "#endif",
  1784. " cpu_printf(\"restored root from '%%s'\\n\", fnm);",
  1785. " printf(\"=====State:=====\\n\");",
  1786. " { int i, j; P0 *z;",
  1787. " for (i = 0; i < now._nr_pr; i++)",
  1788. " { z = (P0 *)pptr(i);",
  1789. " printf(\"proc %%2d (%%s) \", i, procname[z->_t]);",
  1790. " for (j = 0; src_all[j].src; j++)",
  1791. " if (src_all[j].tp == (int) z->_t)",
  1792. " { printf(\" %%s:%%d \",",
  1793. " PanSource, src_all[j].src[z->_p]);",
  1794. " break;",
  1795. " }",
  1796. " printf(\"(state %%d)\\n\", z->_p);",
  1797. " c_locals(i, z->_t);",
  1798. " }",
  1799. " c_globals();",
  1800. " }",
  1801. " printf(\"================\\n\");",
  1802. " }",
  1803. "}",
  1804. "",
  1805. "#ifdef USE_DISK",
  1806. "unsigned long dsk_written, dsk_drained;",
  1807. "void mem_drain(void);",
  1808. "#endif",
  1809. "",
  1810. "void",
  1811. "m_clear_frame(SM_frame *f)", /* clear room for stats */
  1812. "{ int i, clr_sz = sizeof(SM_results);",
  1813. "",
  1814. " for (i = 0; i <= _NP_; i++) /* all proctypes */",
  1815. " { clr_sz += NrStates[i]*sizeof(uchar);",
  1816. " }",
  1817. " memset(f, 0, clr_sz);",
  1818. " /* caution if sizeof(SM_results) > sizeof(SM_frame) */",
  1819. "}",
  1820. "",
  1821. "#define TargetQ_Full(n) (m_workq[n][prfree[n]].m_vsize != 0)", /* no free slot */
  1822. "#define TargetQ_NotFull(n) (m_workq[n][prfree[n]].m_vsize == 0)", /* avoiding prcnt */
  1823. "",
  1824. "int",
  1825. "AllQueuesEmpty(void)",
  1826. "{ int q;",
  1827. "#ifndef NGQ",
  1828. " if (*grcnt != 0)",
  1829. " { return 0;",
  1830. " }",
  1831. "#endif",
  1832. " for (q = 0; q < NCORE; q++)",
  1833. " { if (prcnt[q] != 0)", /* not locked, ok if race */
  1834. " { return 0;",
  1835. " } }",
  1836. " return 1;",
  1837. "}",
  1838. "",
  1839. "void",
  1840. "Read_Queue(int q)",
  1841. "{ SM_frame *f, *of;",
  1842. " int remember, target_q;",
  1843. " SM_results *r;",
  1844. " double patience = 0.0;",
  1845. "",
  1846. " target_q = (q + 1) %% NCORE;",
  1847. "",
  1848. " for (;;)",
  1849. " { f = Get_Full_Frame(q);",
  1850. " if (!f) /* 1 second timeout -- and trigger for Query */",
  1851. " { if (someone_crashed(2))",
  1852. " { printf(\"cpu%%d: search terminated [code %%d]\\n\",",
  1853. " core_id, search_terminated?*search_terminated:-1);",
  1854. " sudden_stop(\"\");",
  1855. " pan_exit(1);",
  1856. " }",
  1857. "#ifdef TESTING",
  1858. " /* to profile with cc -pg and gprof pan.exe -- set handoff depth beyond maxdepth */",
  1859. " exit(0);",
  1860. "#endif",
  1861. " remember = *grfree;",
  1862. " if (core_id == 0 /* root can initiate termination */",
  1863. " && remote_party == 0 /* and only the original root */",
  1864. " && query_in_progress == 0 /* unless its already in progress */",
  1865. " && AllQueuesEmpty())",
  1866. " { f = Get_Free_Frame(target_q);",
  1867. " query_in_progress = 1; /* only root process can do this */",
  1868. " if (!f) { Uerror(\"Fatal1: no free slot\"); }",
  1869. " f->m_boq = QUERY; /* initiate Query */",
  1870. " if (verbose)",
  1871. " { cpu_printf(\"snd QUERY to q%%d (%%d) into slot %%d\\n\",",
  1872. " target_q, nstates_get + 1, prfree[target_q]-1);",
  1873. " }",
  1874. " f->m_vsize = remember + 1;",
  1875. " /* number will not change unless we receive more states */",
  1876. " } else if (patience++ > OneHour) /* one hour watchdog timer */",
  1877. " { cpu_printf(\"timeout -- giving up\\n\");",
  1878. " sudden_stop(\"queue timeout\");",
  1879. " pan_exit(1);",
  1880. " }",
  1881. " if (0) cpu_printf(\"timed out -- try again\\n\");",
  1882. " continue; ",
  1883. " }",
  1884. " patience = 0.0; /* reset watchdog */",
  1885. "",
  1886. " if (f->m_boq == QUERY)",
  1887. " { if (verbose)",
  1888. " { cpu_printf(\"got QUERY on q%%d (%%d <> %%d) from slot %%d\\n\",",
  1889. " q, f->m_vsize, nstates_put + 1, prfull[q]-1);",
  1890. " snapshot();",
  1891. " }",
  1892. " remember = f->m_vsize;",
  1893. " f->m_vsize = 0; /* release slot */",
  1894. "",
  1895. " if (core_id == 0 && remote_party == 0) /* original root cpu0 */",
  1896. " { if (query_in_progress == 1 /* didn't send more states in the interim */",
  1897. " && *grfree + 1 == remember) /* no action on global queue meanwhile */",
  1898. " { if (verbose) cpu_printf(\"Termination detected\\n\");",
  1899. " if (TargetQ_Full(target_q))",
  1900. " { if (verbose)",
  1901. " cpu_printf(\"warning: target q is full\\n\");",
  1902. " }",
  1903. " f = Get_Free_Frame(target_q);",
  1904. " if (!f) { Uerror(\"Fatal2: no free slot\"); }",
  1905. " m_clear_frame(f);",
  1906. " f->m_boq = QUIT; /* send final Quit, collect stats */",
  1907. " f->m_vsize = 111; /* anything non-zero will do */",
  1908. " if (verbose)",
  1909. " cpu_printf(\"put QUIT on q%%d\\n\", target_q);",
  1910. " } else",
  1911. " { if (verbose) cpu_printf(\"Stale Query\\n\");",
  1912. "#ifdef USE_DISK",
  1913. " mem_drain();",
  1914. "#endif",
  1915. " }",
  1916. " query_in_progress = 0;",
  1917. " } else",
  1918. " { if (TargetQ_Full(target_q))",
  1919. " { if (verbose)",
  1920. " cpu_printf(\"warning: forward query - target q full\\n\");",
  1921. " }",
  1922. " f = Get_Free_Frame(target_q);",
  1923. " if (verbose)",
  1924. " cpu_printf(\"snd QUERY response to q%%d (%%d <> %%d) in slot %%d\\n\",",
  1925. " target_q, remember, *grfree + 1, prfree[target_q]-1);",
  1926. " if (!f) { Uerror(\"Fatal4: no free slot\"); }",
  1927. "",
  1928. " if (*grfree + 1 == remember) /* no action on global queue */",
  1929. " { f->m_boq = QUERY; /* forward query, to root */",
  1930. " f->m_vsize = remember;",
  1931. " } else",
  1932. " { f->m_boq = QUERY_F; /* no match -- busy */",
  1933. " f->m_vsize = 112; /* anything non-zero */",
  1934. "#ifdef USE_DISK",
  1935. " if (dsk_written != dsk_drained)",
  1936. " { mem_drain();",
  1937. " }",
  1938. "#endif",
  1939. " } }",
  1940. " continue;",
  1941. " }",
  1942. "",
  1943. " if (f->m_boq == QUERY_F)",
  1944. " { if (verbose)",
  1945. " { cpu_printf(\"got QUERY_F on q%%d from slot %%d\\n\", q, prfull[q]-1);",
  1946. " }",
  1947. " f->m_vsize = 0; /* release slot */",
  1948. "",
  1949. " if (core_id == 0 && remote_party == 0) /* original root cpu0 */",
  1950. " { if (verbose) cpu_printf(\"No Match on Query\\n\");",
  1951. " query_in_progress = 0;",
  1952. " } else",
  1953. " { if (TargetQ_Full(target_q))",
  1954. " { if (verbose) cpu_printf(\"warning: forwarding query_f, target queue full\\n\");",
  1955. " }",
  1956. " f = Get_Free_Frame(target_q);",
  1957. " if (verbose) cpu_printf(\"forward QUERY_F to q%%d into slot %%d\\n\",",
  1958. " target_q, prfree[target_q]-1);",
  1959. " if (!f) { Uerror(\"Fatal5: no free slot\"); }",
  1960. " f->m_boq = QUERY_F; /* cannot terminate yet */",
  1961. " f->m_vsize = 113; /* anything non-zero */",
  1962. " }",
  1963. "#ifdef USE_DISK",
  1964. " if (dsk_written != dsk_drained)",
  1965. " { mem_drain();",
  1966. " }",
  1967. "#endif",
  1968. " continue;",
  1969. " }",
  1970. "",
  1971. " if (f->m_boq == QUIT)",
  1972. " { if (0) cpu_printf(\"done -- local memcnt %%g Mb\\n\", memcnt/(1048576.));",
  1973. " retrieve_info((SM_results *) f); /* collect and combine stats */",
  1974. " if (verbose)",
  1975. " { cpu_printf(\"received Quit\\n\");",
  1976. " snapshot();",
  1977. " }",
  1978. " f->m_vsize = 0; /* release incoming slot */",
  1979. " if (core_id != 0)",
  1980. " { f = Get_Free_Frame(target_q); /* new outgoing slot */",
  1981. " if (!f) { Uerror(\"Fatal6: no free slot\"); }",
  1982. " m_clear_frame(f); /* start with zeroed stats */",
  1983. " record_info((SM_results *) f);",
  1984. " f->m_boq = QUIT; /* forward combined results */",
  1985. " f->m_vsize = 114; /* anything non-zero */",
  1986. " if (verbose>1)",
  1987. " cpu_printf(\"fwd Results to q%%d\\n\", target_q);",
  1988. " }",
  1989. " break; /* successful termination */",
  1990. " }",
  1991. "",
  1992. " /* else: 0<= boq <= 255, means STATE transfer */",
  1993. " if (unpack_state(f, q) != 0)",
  1994. " { nstates_get++;",
  1995. " f->m_vsize = 0; /* release slot */",
  1996. " if (VVERBOSE) cpu_printf(\"Got state\\n\");",
  1997. "",
  1998. " if (search_terminated != NULL",
  1999. " && *search_terminated == 0)",
  2000. " { new_state(); /* explore successors */",
  2001. " memset((uchar *) &cur_Root, 0, sizeof(SM_frame)); /* avoid confusion */",
  2002. " } else",
  2003. " { pan_exit(0);",
  2004. " }",
  2005. " } else",
  2006. " { pan_exit(0);",
  2007. " } }",
  2008. " if (verbose) cpu_printf(\"done got %%d put %%d\\n\", nstates_get, nstates_put);",
  2009. " sleep_report();",
  2010. "}",
  2011. "",
  2012. "void",
  2013. "give_up(int unused_x)",
  2014. "{",
  2015. " if (search_terminated != NULL)",
  2016. " { *search_terminated |= 32; /* give_up */",
  2017. " }",
  2018. " if (!writing_trail)",
  2019. " { was_interrupted = 1;",
  2020. " snapshot();",
  2021. " cpu_printf(\"Give Up\\n\");",
  2022. " sleep_report();",
  2023. " pan_exit(1);",
  2024. " } else /* we are already terminating */",
  2025. " { cpu_printf(\"SIGINT\\n\");",
  2026. " }",
  2027. "}",
  2028. "",
  2029. "void",
  2030. "check_overkill(void)",
  2031. "{",
  2032. " vmax_seen = (vmax_seen + 7)/ 8;",
  2033. " vmax_seen *= 8; /* round up to a multiple of 8 */",
  2034. "",
  2035. " if (core_id == 0",
  2036. " && !remote_party",
  2037. " && nstates_put > 0",
  2038. " && VMAX - vmax_seen > 8)",
  2039. " {",
  2040. "#ifdef BITSTATE",
  2041. " printf(\"cpu0: max VMAX value seen in this run: \");",
  2042. "#else",
  2043. " printf(\"cpu0: recommend recompiling with \");",
  2044. "#endif",
  2045. " printf(\"-DVMAX=%%d\\n\", vmax_seen);",
  2046. " }",
  2047. "}",
  2048. "",
  2049. "void",
  2050. "mem_put(int q) /* handoff state to other cpu, workq q */",
  2051. "{ SM_frame *f;",
  2052. " int i, j;",
  2053. "",
  2054. " if (vsize > VMAX)",
  2055. " { vsize = (vsize + 7)/8; vsize *= 8; /* round up */",
  2056. " printf(\"pan: recompile with -DVMAX=N with N >= %%d\\n\", (int) vsize);",
  2057. " Uerror(\"aborting\");",
  2058. " }",
  2059. " if (now._nr_pr > PMAX)",
  2060. " { printf(\"pan: recompile with -DPMAX=N with N >= %%d\\n\", now._nr_pr);",
  2061. " Uerror(\"aborting\");",
  2062. " }",
  2063. " if (now._nr_qs > QMAX)",
  2064. " { printf(\"pan: recompile with -DQMAX=N with N >= %%d\\n\", now._nr_qs);",
  2065. " Uerror(\"aborting\");",
  2066. " }",
  2067. " if (vsize > vmax_seen) vmax_seen = vsize;",
  2068. " if (now._nr_pr > pmax_seen) pmax_seen = now._nr_pr;",
  2069. " if (now._nr_qs > qmax_seen) qmax_seen = now._nr_qs;",
  2070. "",
  2071. " f = Get_Free_Frame(q); /* not called in likely deadlock states */",
  2072. " if (!f) { Uerror(\"Fatal3: no free slot\"); }",
  2073. "",
  2074. " if (VVERBOSE) cpu_printf(\"putting state into q%%d\\n\", q);",
  2075. "",
  2076. " memcpy((uchar *) f->m_now, (uchar *) &now, vsize);",
  2077. " memset((uchar *) f->m_Mask, 0, (VMAX+7)/8 * sizeof(char));",
  2078. " for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)",
  2079. " { if (Mask[i])",
  2080. " { f->m_Mask[i/8] |= (1<<j);",
  2081. " } }",
  2082. "",
  2083. " if (now._nr_pr > 0)",
  2084. " { memcpy((uchar *) f->m_p_offset, (uchar *) proc_offset, now._nr_pr * sizeof(OFFT));",
  2085. " memcpy((uchar *) f->m_p_skip, (uchar *) proc_skip, now._nr_pr * sizeof(uchar));",
  2086. " }",
  2087. " if (now._nr_qs > 0)",
  2088. " { memcpy((uchar *) f->m_q_offset, (uchar *) q_offset, now._nr_qs * sizeof(OFFT));",
  2089. " memcpy((uchar *) f->m_q_skip, (uchar *) q_skip, now._nr_qs * sizeof(uchar));",
  2090. " }",
  2091. "#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)",
  2092. " c_stack((uchar *) f->m_c_stack); /* save unmatched tracked data */",
  2093. "#endif",
  2094. "#ifdef FULL_TRAIL",
  2095. " f->m_stack = stack_last[core_id];",
  2096. "#endif",
  2097. " f->nr_handoffs = nr_handoffs+1;",
  2098. " f->m_tau = trpt->tau;",
  2099. " f->m_o_pm = trpt->o_pm;",
  2100. " f->m_boq = boq;",
  2101. " f->m_vsize = vsize; /* must come last - now the other cpu can see it */",
  2102. "",
  2103. " if (query_in_progress == 1)",
  2104. " query_in_progress = 2; /* make sure we know, if a query makes the rounds */",
  2105. " nstates_put++;",
  2106. "}",
  2107. "",
  2108. "#ifdef USE_DISK",
  2109. "int Dsk_W_Nr, Dsk_R_Nr;",
  2110. "int dsk_file = -1, dsk_read = -1;",
  2111. "unsigned long dsk_written, dsk_drained;",
  2112. "char dsk_name[512];",
  2113. "",
  2114. "#ifndef BFS_DISK",
  2115. "#if defined(WIN32) || defined(WIN64)",
  2116. " #define RFLAGS (O_RDONLY|O_BINARY)",
  2117. " #define WFLAGS (O_CREAT|O_WRONLY|O_TRUNC|O_BINARY)",
  2118. "#else",
  2119. " #define RFLAGS (O_RDONLY)",
  2120. " #define WFLAGS (O_CREAT|O_WRONLY|O_TRUNC)",
  2121. "#endif",
  2122. "#endif",
  2123. "",
  2124. "void",
  2125. "dsk_stats(void)",
  2126. "{ int i;",
  2127. "",
  2128. " if (dsk_written > 0)",
  2129. " { cpu_printf(\"dsk_written %%d states in %%d files\\ncpu%%d: dsk_drained %%6d states\\n\",",
  2130. " dsk_written, Dsk_W_Nr, core_id, dsk_drained);",
  2131. " close(dsk_read);",
  2132. " close(dsk_file);",
  2133. " for (i = 0; i < Dsk_W_Nr; i++)",
  2134. " { sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", i, core_id);",
  2135. " unlink(dsk_name);",
  2136. " } }",
  2137. "}",
  2138. "",
  2139. "void",
  2140. "mem_drain(void)",
  2141. "{ SM_frame *f, g;",
  2142. " int q = (core_id + 1) %% NCORE; /* target q */",
  2143. " int sz;",
  2144. "",
  2145. " if (dsk_read < 0",
  2146. " || dsk_written <= dsk_drained)",
  2147. " { return;",
  2148. " }",
  2149. "",
  2150. " while (dsk_written > dsk_drained",
  2151. " && TargetQ_NotFull(q))",
  2152. " { f = Get_Free_Frame(q);",
  2153. " if (!f) { Uerror(\"Fatal: unhandled condition\"); }",
  2154. "",
  2155. " if ((dsk_drained+1)%%MAX_DSK_FILE == 0) /* 100K states max per file */",
  2156. " { (void) close(dsk_read); /* close current read handle */",
  2157. " sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_R_Nr++, core_id);",
  2158. " (void) unlink(dsk_name); /* remove current file */",
  2159. " sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_R_Nr, core_id);",
  2160. " cpu_printf(\"reading %%s\\n\", dsk_name);",
  2161. " dsk_read = open(dsk_name, RFLAGS); /* open next file */",
  2162. " if (dsk_read < 0)",
  2163. " { Uerror(\"could not open dsk file\");",
  2164. " } }",
  2165. " if (read(dsk_read, &g, sizeof(SM_frame)) != sizeof(SM_frame))",
  2166. " { Uerror(\"bad dsk file read\");",
  2167. " }",
  2168. " sz = g.m_vsize;",
  2169. " g.m_vsize = 0;",
  2170. " memcpy(f, &g, sizeof(SM_frame));",
  2171. " f->m_vsize = sz; /* last */",
  2172. "",
  2173. " dsk_drained++;",
  2174. " }",
  2175. "}",
  2176. "",
  2177. "void",
  2178. "mem_file(void)",
  2179. "{ SM_frame f;",
  2180. " int i, j, q = (core_id + 1) %% NCORE; /* target q */",
  2181. "",
  2182. " if (vsize > VMAX)",
  2183. " { printf(\"pan: recompile with -DVMAX=N with N >= %%d\\n\", vsize);",
  2184. " Uerror(\"aborting\");",
  2185. " }",
  2186. " if (now._nr_pr > PMAX)",
  2187. " { printf(\"pan: recompile with -DPMAX=N with N >= %%d\\n\", now._nr_pr);",
  2188. " Uerror(\"aborting\");",
  2189. " }",
  2190. " if (now._nr_qs > QMAX)",
  2191. " { printf(\"pan: recompile with -DQMAX=N with N >= %%d\\n\", now._nr_qs);",
  2192. " Uerror(\"aborting\");",
  2193. " }",
  2194. "",
  2195. " if (VVERBOSE) cpu_printf(\"filing state for q%%d\\n\", q);",
  2196. "",
  2197. " memcpy((uchar *) f.m_now, (uchar *) &now, vsize);",
  2198. " memset((uchar *) f.m_Mask, 0, (VMAX+7)/8 * sizeof(char));",
  2199. " for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)",
  2200. " { if (Mask[i])",
  2201. " { f.m_Mask[i/8] |= (1<<j);",
  2202. " } }",
  2203. "",
  2204. " if (now._nr_pr > 0)",
  2205. " { memcpy((uchar *)f.m_p_offset, (uchar *)proc_offset, now._nr_pr*sizeof(OFFT));",
  2206. " memcpy((uchar *)f.m_p_skip, (uchar *)proc_skip, now._nr_pr*sizeof(uchar));",
  2207. " }",
  2208. " if (now._nr_qs > 0)",
  2209. " { memcpy((uchar *) f.m_q_offset, (uchar *) q_offset, now._nr_qs*sizeof(OFFT));",
  2210. " memcpy((uchar *) f.m_q_skip, (uchar *) q_skip, now._nr_qs*sizeof(uchar));",
  2211. " }",
  2212. "#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)",
  2213. " c_stack((uchar *) f.m_c_stack); /* save unmatched tracked data */",
  2214. "#endif",
  2215. "#ifdef FULL_TRAIL",
  2216. " f.m_stack = stack_last[core_id];",
  2217. "#endif",
  2218. " f.nr_handoffs = nr_handoffs+1;",
  2219. " f.m_tau = trpt->tau;",
  2220. " f.m_o_pm = trpt->o_pm;",
  2221. " f.m_boq = boq;",
  2222. " f.m_vsize = vsize;",
  2223. "",
  2224. " if (query_in_progress == 1)",
  2225. " { query_in_progress = 2;",
  2226. " }",
  2227. " if (dsk_file < 0)",
  2228. " { sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_W_Nr, core_id);",
  2229. " dsk_file = open(dsk_name, WFLAGS, 0644);",
  2230. " dsk_read = open(dsk_name, RFLAGS);",
  2231. " if (dsk_file < 0 || dsk_read < 0)",
  2232. " { cpu_printf(\"File: <%%s>\\n\", dsk_name);",
  2233. " Uerror(\"cannot open diskfile\");",
  2234. " }",
  2235. " Dsk_W_Nr++; /* nr of next file to open */",
  2236. " cpu_printf(\"created temporary diskfile %%s\\n\", dsk_name);",
  2237. " } else if ((dsk_written+1)%%MAX_DSK_FILE == 0)",
  2238. " { close(dsk_file); /* close write handle */",
  2239. " sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_W_Nr++, core_id);",
  2240. " dsk_file = open(dsk_name, WFLAGS, 0644);",
  2241. " if (dsk_file < 0)",
  2242. " { cpu_printf(\"File: <%%s>\\n\", dsk_name);",
  2243. " Uerror(\"aborting: cannot open new diskfile\");",
  2244. " }",
  2245. " cpu_printf(\"created temporary diskfile %%s\\n\", dsk_name);",
  2246. " }",
  2247. " if (write(dsk_file, &f, sizeof(SM_frame)) != sizeof(SM_frame))",
  2248. " { Uerror(\"aborting -- disk write failed (disk full?)\");",
  2249. " }",
  2250. " nstates_put++;",
  2251. " dsk_written++;",
  2252. "}",
  2253. "#endif",
  2254. "",
  2255. "int",
  2256. "mem_hand_off(void)",
  2257. "{",
  2258. " if (search_terminated == NULL",
  2259. " || *search_terminated != 0) /* not a full crash check */",
  2260. " { pan_exit(0);",
  2261. " }",
  2262. " iam_alive(); /* on every transition of Down */",
  2263. "#ifdef USE_DISK",
  2264. " mem_drain(); /* maybe call this also on every Up */",
  2265. "#endif",
  2266. " if (depth > z_handoff /* above handoff limit */",
  2267. "#ifndef SAFETY",
  2268. " && !a_cycles /* not in liveness mode */",
  2269. "#endif",
  2270. "#if SYNC",
  2271. " && boq == -1 /* not mid-rv */",
  2272. "#endif",
  2273. "#ifdef VERI",
  2274. " && (trpt->tau&4) /* claim moves first */",
  2275. " && !((trpt-1)->tau&128) /* not a stutter move */",
  2276. "#endif",
  2277. " && !(trpt->tau&8)) /* not an atomic move */",
  2278. " { int q = (core_id + 1) %% NCORE; /* circular handoff */",
  2279. " #ifdef GENEROUS",
  2280. " if (prcnt[q] < LN_FRAMES)", /* not the best strategy */
  2281. " #else",
  2282. " if (TargetQ_NotFull(q)",
  2283. " && (dfs_phase2 == 0 || prcnt[core_id] > 0))", /* not locked, ok if race */
  2284. " #endif",
  2285. " { mem_put(q);", /* only 1 writer: lock-free */
  2286. " return 1;",
  2287. " }",
  2288. " { int rval;",
  2289. " #ifndef NGQ",
  2290. " rval = GlobalQ_HasRoom();",
  2291. " #else",
  2292. " rval = 0;",
  2293. " #endif",
  2294. " #ifdef USE_DISK",
  2295. " if (rval == 0)",
  2296. " { void mem_file(void);",
  2297. " mem_file();",
  2298. " rval = 1;",
  2299. " }",
  2300. " #endif",
  2301. " return rval;",
  2302. " }",
  2303. " }",
  2304. " return 0; /* i.e., no handoff */",
  2305. "}",
  2306. "",
  2307. "void",
  2308. "mem_put_acc(void) /* liveness mode */",
  2309. "{ int q = (core_id + 1) %% NCORE;",
  2310. "",
  2311. " if (search_terminated == NULL",
  2312. " || *search_terminated != 0)",
  2313. " { pan_exit(0);",
  2314. " }",
  2315. "#ifdef USE_DISK",
  2316. " mem_drain();",
  2317. "#endif",
  2318. " /* some tortured use of preprocessing: */",
  2319. "#if !defined(NGQ) || defined(USE_DISK)",
  2320. " if (TargetQ_Full(q))",
  2321. " {",
  2322. "#endif",
  2323. "#ifndef NGQ",
  2324. " if (GlobalQ_HasRoom())",
  2325. " { return;",
  2326. " }",
  2327. "#endif",
  2328. "#ifdef USE_DISK",
  2329. " mem_file();",
  2330. " } else",
  2331. "#else",
  2332. " #if !defined(NGQ) || defined(USE_DISK)",
  2333. " }",
  2334. " #endif",
  2335. "#endif",
  2336. " { mem_put(q);",
  2337. " }",
  2338. "}",
  2339. "",
  2340. "#if defined(WIN32) || defined(WIN64)", /* visual studio */
  2341. "void",
  2342. "init_shm(void) /* initialize shared work-queues */",
  2343. "{ char key[512];",
  2344. " int n, m;",
  2345. " int must_exit = 0;",
  2346. "",
  2347. " if (core_id == 0 && verbose)",
  2348. " { printf(\"cpu0: step 3: allocate shared work-queues %%g Mb\\n\",",
  2349. " ((double) NCORE * LWQ_SIZE + GWQ_SIZE) / (1048576.));",
  2350. " }",
  2351. " for (m = 0; m < NR_QS; m++) /* last q is global 1 */",
  2352. " { double qsize = (m == NCORE) ? GWQ_SIZE : LWQ_SIZE;",
  2353. " sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, m);",
  2354. " if (core_id == 0)", /* root process creates shared memory segments */
  2355. " { shmid[m] = CreateFileMapping(",
  2356. " INVALID_HANDLE_VALUE, /* use paging file */",
  2357. " NULL, /* default security */",
  2358. " PAGE_READWRITE, /* access permissions */",
  2359. " 0, /* high-order 4 bytes */",
  2360. " qsize, /* low-order bytes, size in bytes */",
  2361. " key); /* name */",
  2362. " } else /* worker nodes just open these segments */",
  2363. " { shmid[m] = OpenFileMapping(",
  2364. " FILE_MAP_ALL_ACCESS, /* read/write access */",
  2365. " FALSE, /* children do not inherit handle */",
  2366. " key);",
  2367. " }",
  2368. " if (shmid[m] == NULL)",
  2369. " { fprintf(stderr, \"cpu%%d: could not create or open shared queues\\n\",",
  2370. " core_id);",
  2371. " must_exit = 1;",
  2372. " break;",
  2373. " }",
  2374. " /* attach: */",
  2375. " shared_mem[m] = (char *) MapViewOfFile(shmid[m], FILE_MAP_ALL_ACCESS, 0, 0, 0);",
  2376. " if (shared_mem[m] == NULL)",
  2377. " { fprintf(stderr, \"cpu%%d: cannot attach shared q%%d (%%d Mb)\\n\",",
  2378. " core_id, m+1, (int) (qsize/(1048576.)));",
  2379. " must_exit = 1;",
  2380. " break;",
  2381. " }",
  2382. "",
  2383. " memcnt += qsize;",
  2384. "",
  2385. " m_workq[m] = (SM_frame *) shared_mem[m];",
  2386. " if (core_id == 0)",
  2387. " { int nframes = (m == NCORE) ? GN_FRAMES : LN_FRAMES;",
  2388. " for (n = 0; n < nframes; n++)",
  2389. " { m_workq[m][n].m_vsize = 0;",
  2390. " m_workq[m][n].m_boq = 0;",
  2391. " } } }",
  2392. "",
  2393. " if (must_exit)",
  2394. " { fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
  2395. " pan_exit(1); /* calls cleanup_shm */",
  2396. " }",
  2397. "}",
  2398. "",
  2399. "static uchar *",
  2400. "prep_shmid_S(size_t n) /* either sets SS or H_tab, WIN32/WIN64 */",
  2401. "{ char *rval;",
  2402. "#ifndef SEP_STATE",
  2403. " char key[512];",
  2404. "",
  2405. " if (verbose && core_id == 0)",
  2406. " {",
  2407. " #ifdef BITSTATE",
  2408. " printf(\"cpu0: step 1: allocate shared bitstate %%g Mb\\n\",",
  2409. " (double) n / (1048576.));",
  2410. " #else",
  2411. " printf(\"cpu0: step 1: allocate shared hastable %%g Mb\\n\",",
  2412. " (double) n / (1048576.));",
  2413. " #endif",
  2414. " }",
  2415. " #ifdef MEMLIM",
  2416. " if (memcnt + (double) n > memlim)",
  2417. " { printf(\"cpu%%d: S %%8g + %%d Kb exceeds memory limit of %%8g Mb\\n\",",
  2418. " core_id, memcnt/1024., n/1024, memlim/(1048576.));",
  2419. " printf(\"cpu%%d: insufficient memory -- aborting\\n\", core_id);",
  2420. " exit(1);",
  2421. " }",
  2422. " #endif",
  2423. "",
  2424. " /* make key different from queues: */",
  2425. " sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, NCORE+2); /* different from qs */",
  2426. "",
  2427. " if (core_id == 0) /* root */",
  2428. " { shmid_S = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,",
  2429. "#ifdef WIN64",
  2430. " PAGE_READWRITE, (n>>32), (n & 0xffffffff), key);",
  2431. "#else",
  2432. " PAGE_READWRITE, 0, n, key);",
  2433. "#endif",
  2434. " memcnt += (double) n;",
  2435. " } else /* worker */",
  2436. " { shmid_S = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, key);",
  2437. " }",
  2438. " if (shmid_S == NULL)",
  2439. " {",
  2440. " #ifdef BITSTATE",
  2441. " fprintf(stderr, \"cpu%%d: cannot %%s shared bitstate\",",
  2442. " core_id, core_id?\"open\":\"create\");",
  2443. " #else",
  2444. " fprintf(stderr, \"cpu%%d: cannot %%s shared hashtable\",",
  2445. " core_id, core_id?\"open\":\"create\");",
  2446. " #endif",
  2447. " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
  2448. " pan_exit(1);",
  2449. " }",
  2450. "",
  2451. " rval = (char *) MapViewOfFile(shmid_S, FILE_MAP_ALL_ACCESS, 0, 0, 0); /* attach */",
  2452. " if ((char *) rval == NULL)",
  2453. " { fprintf(stderr, \"cpu%%d: cannot attach shared bitstate or hashtable\\n\", core_id);",
  2454. " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");",
  2455. " pan_exit(1);",
  2456. " }",
  2457. "#else",
  2458. " rval = (char *) emalloc(n);",
  2459. "#endif",
  2460. " return (uchar *) rval;",
  2461. "}",
  2462. "",
  2463. "static uchar *",
  2464. "prep_state_mem(size_t n) /* WIN32/WIN64 sets memory arena for states */",
  2465. "{ char *rval;",
  2466. " char key[512];",
  2467. " static int cnt = 3; /* start larger than earlier ftok calls */",
  2468. "",
  2469. " if (verbose && core_id == 0)",
  2470. " { printf(\"cpu0: step 2+: pre-allocate memory arena %%d of %%g Mb\\n\",",
  2471. " cnt-3, (double) n / (1048576.));",
  2472. " }",
  2473. " #ifdef MEMLIM",
  2474. " if (memcnt + (double) n > memlim)",
  2475. " { printf(\"cpu%%d: error: M %%.0f + %%.0f exceeds memory limit of %%.0f Kb\\n\",",
  2476. " core_id, memcnt/1024.0, (double) n/1024.0, memlim/1024.0);",
  2477. " return NULL;",
  2478. " }",
  2479. " #endif",
  2480. "",
  2481. " sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, NCORE+cnt); cnt++;",
  2482. "",
  2483. " if (core_id == 0)",
  2484. " { shmid_M = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,",
  2485. "#ifdef WIN64",
  2486. " PAGE_READWRITE, (n>>32), (n & 0xffffffff), key);",
  2487. "#else",
  2488. " PAGE_READWRITE, 0, n, key);",
  2489. "#endif",
  2490. " } else",
  2491. " { shmid_M = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, key);",
  2492. " }",
  2493. " if (shmid_M == NULL)",
  2494. " { printf(\"cpu%%d: failed to get pool of shared memory nr %%d of size %%d\\n\",",
  2495. " core_id, cnt-3, n);",
  2496. " printf(\"pan: check './pan --' for usage details\\n\");",
  2497. " return NULL;",
  2498. " }",
  2499. " rval = (char *) MapViewOfFile(shmid_M, FILE_MAP_ALL_ACCESS, 0, 0, 0); /* attach */",
  2500. "",
  2501. " if (rval == NULL)",
  2502. " { printf(\"cpu%%d: failed to attach pool of shared memory nr %%d of size %%d\\n\",",
  2503. " core_id, cnt-3, n);",
  2504. " return NULL;",
  2505. " }",
  2506. " return (uchar *) rval;",
  2507. "}",
  2508. "",
  2509. "void",
  2510. "init_HT(unsigned long n) /* WIN32/WIN64 version */",
  2511. "{ volatile char *x;",
  2512. " double get_mem;",
  2513. "#ifndef SEP_STATE",
  2514. " char *dc_mem_start;",
  2515. "#endif",
  2516. " if (verbose) printf(\"cpu%%d: initialization for Windows\\n\", core_id);",
  2517. "",
  2518. "#ifdef SEP_STATE",
  2519. " #ifndef MEMLIM",
  2520. " if (verbose)",
  2521. " { printf(\"cpu0: steps 0,1: no -DMEMLIM set\\n\");",
  2522. " }",
  2523. " #else",
  2524. " if (verbose)",
  2525. " printf(\"cpu0: steps 0,1: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb)\\n\",",
  2526. " MEMLIM, ((double)n/(1048576.)), ((double) NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.));",
  2527. "#endif",
  2528. " get_mem = NCORE * sizeof(double) + (1 + CS_NR) * sizeof(void *)+ 4*sizeof(void *) + 2*sizeof(double);",
  2529. " /* NCORE * is_alive + search_terminated + CS_NR * sh_lock + 6 gr vars */",
  2530. " get_mem += 4 * NCORE * sizeof(void *);", /* prfree, prfull, prcnt, prmax */
  2531. " #ifdef FULL_TRAIL",
  2532. " get_mem += (NCORE) * sizeof(Stack_Tree *);",
  2533. " /* NCORE * stack_last */",
  2534. " #endif",
  2535. " x = (volatile char *) prep_state_mem((size_t) get_mem);",
  2536. " shmid_X = (void *) x;",
  2537. " if (x == NULL)",
  2538. " { printf(\"cpu0: could not allocate shared memory, see ./pan --\\n\");",
  2539. " exit(1);",
  2540. " }",
  2541. " search_terminated = (volatile unsigned int *) x; /* comes first */",
  2542. " x += sizeof(void *); /* maintain alignment */",
  2543. "",
  2544. " is_alive = (volatile double *) x;",
  2545. " x += NCORE * sizeof(double);",
  2546. "",
  2547. " sh_lock = (volatile int *) x;",
  2548. " x += CS_NR * sizeof(void *); /* allow 1 word per entry */",
  2549. "",
  2550. " grfree = (volatile int *) x;",
  2551. " x += sizeof(void *);",
  2552. " grfull = (volatile int *) x;",
  2553. " x += sizeof(void *);",
  2554. " grcnt = (volatile int *) x;",
  2555. " x += sizeof(void *);",
  2556. " grmax = (volatile int *) x;",
  2557. " x += sizeof(void *);",
  2558. " prfree = (volatile int *) x;",
  2559. " x += NCORE * sizeof(void *);",
  2560. " prfull = (volatile int *) x;",
  2561. " x += NCORE * sizeof(void *);",
  2562. " prcnt = (volatile int *) x;",
  2563. " x += NCORE * sizeof(void *);",
  2564. " prmax = (volatile int *) x;",
  2565. " x += NCORE * sizeof(void *);",
  2566. " gr_readmiss = (volatile double *) x;",
  2567. " x += sizeof(double);",
  2568. " gr_writemiss = (volatile double *) x;",
  2569. " x += sizeof(double);",
  2570. "",
  2571. " #ifdef FULL_TRAIL",
  2572. " stack_last = (volatile Stack_Tree **) x;",
  2573. " x += NCORE * sizeof(Stack_Tree *);",
  2574. " #endif",
  2575. "",
  2576. " #ifndef BITSTATE",
  2577. " H_tab = (struct H_el **) emalloc(n);",
  2578. " #endif",
  2579. "#else",
  2580. " #ifndef MEMLIM",
  2581. " #warning MEMLIM not set", /* cannot happen */
  2582. " #define MEMLIM (2048)",
  2583. " #endif",
  2584. "",
  2585. " if (core_id == 0 && verbose)",
  2586. " printf(\"cpu0: step 0: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb) = %%g Mb for state storage\\n\",",
  2587. " MEMLIM, ((double)n/(1048576.)), ((double) NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.),",
  2588. " (memlim - memcnt - (double) n - ((double) NCORE * LWQ_SIZE + GWQ_SIZE))/(1048576.));",
  2589. " #ifndef BITSTATE",
  2590. " H_tab = (struct H_el **) prep_shmid_S((size_t) n); /* hash_table */",
  2591. " #endif",
  2592. " get_mem = memlim - memcnt - ((double) NCORE) * LWQ_SIZE - GWQ_SIZE;",
  2593. " if (get_mem <= 0)",
  2594. " { Uerror(\"internal error -- shared state memory\");",
  2595. " }",
  2596. "",
  2597. " if (core_id == 0 && verbose)",
  2598. " { printf(\"cpu0: step 2: shared state memory %%g Mb\\n\",",
  2599. " get_mem/(1048576.));",
  2600. " }",
  2601. " x = dc_mem_start = (char *) prep_state_mem((size_t) get_mem); /* for states */",
  2602. " if (x == NULL)",
  2603. " { printf(\"cpu%%d: insufficient memory -- aborting\\n\", core_id);",
  2604. " exit(1);",
  2605. " }",
  2606. "",
  2607. " search_terminated = (volatile unsigned int *) x; /* comes first */",
  2608. " x += sizeof(void *); /* maintain alignment */",
  2609. "",
  2610. " is_alive = (volatile double *) x;",
  2611. " x += NCORE * sizeof(double);",
  2612. "",
  2613. " sh_lock = (volatile int *) x;",
  2614. " x += CS_NR * sizeof(int);",
  2615. "",
  2616. " grfree = (volatile int *) x;",
  2617. " x += sizeof(void *);",
  2618. " grfull = (volatile int *) x;",
  2619. " x += sizeof(void *);",
  2620. " grcnt = (volatile int *) x;",
  2621. " x += sizeof(void *);",
  2622. " grmax = (volatile int *) x;",
  2623. " x += sizeof(void *);",
  2624. " prfree = (volatile int *) x;",
  2625. " x += NCORE * sizeof(void *);",
  2626. " prfull = (volatile int *) x;",
  2627. " x += NCORE * sizeof(void *);",
  2628. " prcnt = (volatile int *) x;",
  2629. " x += NCORE * sizeof(void *);",
  2630. " prmax = (volatile int *) x;",
  2631. " x += NCORE * sizeof(void *);",
  2632. " gr_readmiss = (volatile double *) x;",
  2633. " x += sizeof(double);",
  2634. " gr_writemiss = (volatile double *) x;",
  2635. " x += sizeof(double);",
  2636. "",
  2637. " #ifdef FULL_TRAIL",
  2638. " stack_last = (volatile Stack_Tree **) x;",
  2639. " x += NCORE * sizeof(Stack_Tree *);",
  2640. " #endif",
  2641. " if (((long)x)&(sizeof(void *)-1)) /* word alignment */",
  2642. " { x += sizeof(void *)-(((long)x)&(sizeof(void *)-1)); /* 64-bit align */",
  2643. " }",
  2644. "",
  2645. " #ifdef COLLAPSE",
  2646. " ncomps = (unsigned long *) x;",
  2647. " x += (256+2) * sizeof(unsigned long);",
  2648. " #endif",
  2649. "",
  2650. " dc_shared = (sh_Allocater *) x; /* in shared memory */",
  2651. " x += sizeof(sh_Allocater);",
  2652. "",
  2653. " if (core_id == 0) /* root only */",
  2654. " { dc_shared->dc_id = shmid_M;",
  2655. " dc_shared->dc_start = (void *) dc_mem_start;",
  2656. " dc_shared->dc_arena = x;",
  2657. " dc_shared->pattern = 1234567;",
  2658. " dc_shared->dc_size = (long) get_mem - (long) (x - dc_mem_start);",
  2659. " dc_shared->nxt = NULL;",
  2660. " }",
  2661. "#endif",
  2662. "}",
  2663. "",
  2664. "#if defined(WIN32) || defined(WIN64) || defined(__i386__) || defined(__x86_64__)",
  2665. "extern BOOLEAN InterlockedBitTestAndSet(LONG volatile* Base, LONG Bit);",
  2666. "int",
  2667. "tas(volatile LONG *s)", /* atomic test and set */
  2668. "{ return InterlockedBitTestAndSet(s, 1);",
  2669. "}",
  2670. "#else",
  2671. " #error missing definition of test and set operation for this platform",
  2672. "#endif",
  2673. "",
  2674. "void",
  2675. "cleanup_shm(int val)",
  2676. "{ int m;",
  2677. " static int nibis = 0;",
  2678. "",
  2679. " if (nibis != 0)",
  2680. " { printf(\"cpu%%d: Redundant call to cleanup_shm(%%d)\\n\", core_id, val);",
  2681. " return;",
  2682. " } else",
  2683. " { nibis = 1;",
  2684. " }",
  2685. " if (search_terminated != NULL)",
  2686. " { *search_terminated |= 16; /* cleanup_shm */",
  2687. " }",
  2688. "",
  2689. " for (m = 0; m < NR_QS; m++)",
  2690. " { if (shmid[m] != NULL)",
  2691. " { UnmapViewOfFile((char *) shared_mem[m]);",
  2692. " CloseHandle(shmid[m]);",
  2693. " } }",
  2694. "#ifdef SEP_STATE",
  2695. " UnmapViewOfFile((void *) shmid_X);",
  2696. " CloseHandle((void *) shmid_M);",
  2697. "#else",
  2698. " #ifdef BITSTATE",
  2699. " if (shmid_S != NULL)",
  2700. " { UnmapViewOfFile(SS);",
  2701. " CloseHandle(shmid_S);",
  2702. " }",
  2703. " #else",
  2704. " if (core_id == 0 && verbose)",
  2705. " { printf(\"cpu0: done, %%ld Mb of shared state memory left\\n\",",
  2706. " dc_shared->dc_size / (long)(1048576));",
  2707. " }",
  2708. " if (shmid_S != NULL)",
  2709. " { UnmapViewOfFile(H_tab);",
  2710. " CloseHandle(shmid_S);",
  2711. " }",
  2712. " shmid_M = (void *) (dc_shared->dc_id);",
  2713. " UnmapViewOfFile((char *) dc_shared->dc_start);",
  2714. " CloseHandle(shmid_M);",
  2715. " #endif",
  2716. "#endif",
  2717. " /* detached from shared memory - so cannot use cpu_printf */",
  2718. " if (verbose)",
  2719. " { printf(\"cpu%%d: done -- got %%d states from queue\\n\",",
  2720. " core_id, nstates_get);",
  2721. " }",
  2722. "}",
  2723. "",
  2724. "void",
  2725. "mem_get(void)",
  2726. "{ SM_frame *f;",
  2727. " int is_parent;",
  2728. "",
  2729. "#if defined(MA) && !defined(SEP_STATE)",
  2730. " #error MA requires SEP_STATE in multi-core mode",
  2731. "#endif",
  2732. "#ifdef BFS",
  2733. " #error BFS is not supported in multi-core mode",
  2734. "#endif",
  2735. "#ifdef SC",
  2736. " #error SC is not supported in multi-core mode",
  2737. "#endif",
  2738. " init_shm(); /* we are single threaded when this starts */",
  2739. " signal(SIGINT, give_up); /* windows control-c interrupt */",
  2740. "",
  2741. " if (core_id == 0 && verbose)",
  2742. " { printf(\"cpu0: step 4: creating additional workers (proxy %%d)\\n\",",
  2743. " proxy_pid);",
  2744. " }",
  2745. "#if 0",
  2746. " if NCORE > 1 the child or the parent should fork N-1 more times",
  2747. " the parent is the only process with core_id == 0 and is_parent > 0",
  2748. " the others (workers) have is_parent = 0 and core_id = 1..NCORE-1",
  2749. "#endif",
  2750. " if (core_id == 0) /* root starts up the workers */",
  2751. " { worker_pids[0] = (DWORD) getpid(); /* for completeness */",
  2752. " while (++core_id < NCORE) /* first worker sees core_id = 1 */",
  2753. " { char cmdline[64];",
  2754. " STARTUPINFO si = { sizeof(si) };",
  2755. " PROCESS_INFORMATION pi;",
  2756. "",
  2757. " if (proxy_pid == core_id) /* always non-zero */",
  2758. " { sprintf(cmdline, \"pan_proxy.exe -r %%s-Q%%d -Z%%d\",",
  2759. " o_cmdline, getpid(), core_id);",
  2760. " } else",
  2761. " { sprintf(cmdline, \"pan.exe %%s-Q%%d -Z%%d\",",
  2762. " o_cmdline, getpid(), core_id);",
  2763. " }",
  2764. " if (verbose) printf(\"cpu%%d: spawn %%s\\n\", core_id, cmdline);",
  2765. "",
  2766. " is_parent = CreateProcess(0, cmdline, 0, 0, FALSE, 0, 0, 0, &si, &pi);",
  2767. " if (is_parent == 0)",
  2768. " { Uerror(\"fork failed\");",
  2769. " }",
  2770. " worker_pids[core_id] = pi.dwProcessId;",
  2771. " worker_handles[core_id] = pi.hProcess;",
  2772. " if (verbose)",
  2773. " { cpu_printf(\"created core %%d, pid %%d\\n\",",
  2774. " core_id, pi.dwProcessId);",
  2775. " }",
  2776. " if (proxy_pid == core_id) /* we just created the receive half */",
  2777. " { /* add proxy send, store pid in proxy_pid_snd */",
  2778. " sprintf(cmdline, \"pan_proxy.exe -s %%s-Q%%d -Z%%d -Y%%d\",",
  2779. " o_cmdline, getpid(), core_id, worker_pids[proxy_pid]);",
  2780. " if (verbose) printf(\"cpu%%d: spawn %%s\\n\", core_id, cmdline);",
  2781. " is_parent = CreateProcess(0, cmdline, 0,0, FALSE, 0,0,0, &si, &pi);",
  2782. " if (is_parent == 0)",
  2783. " { Uerror(\"fork failed\");",
  2784. " }",
  2785. " proxy_pid_snd = pi.dwProcessId;",
  2786. " proxy_handle_snd = pi.hProcess;",
  2787. " if (verbose)",
  2788. " { cpu_printf(\"created core %%d, pid %%d (send proxy)\\n\",",
  2789. " core_id, pi.dwProcessId);",
  2790. " } } }",
  2791. " core_id = 0; /* reset core_id for root process */",
  2792. " } else /* worker */",
  2793. " { static char db0[16]; /* good for up to 10^6 cores */",
  2794. " static char db1[16];",
  2795. " tprefix = db0; sprefix = db1;",
  2796. " sprintf(tprefix, \"cpu%%d_trail\", core_id); /* avoid conflicts on file access */",
  2797. " sprintf(sprefix, \"cpu%%d_rst\", core_id);",
  2798. " memcnt = 0; /* count only additionally allocated memory */",
  2799. " }",
  2800. " if (verbose)",
  2801. " { cpu_printf(\"starting core_id %%d -- pid %%d\\n\", core_id, getpid());",
  2802. " }",
  2803. " if (core_id == 0 && !remote_party)",
  2804. " { new_state(); /* root starts the search */",
  2805. " if (verbose)",
  2806. " cpu_printf(\"done with 1st dfs, nstates %%g (put %%d states), start reading q\\n\",",
  2807. " nstates, nstates_put);",
  2808. " dfs_phase2 = 1;",
  2809. " }",
  2810. " Read_Queue(core_id); /* all cores */",
  2811. "",
  2812. " if (verbose)",
  2813. " { cpu_printf(\"put %%6d states into queue -- got %%6d\\n\",",
  2814. " nstates_put, nstates_get);",
  2815. " }",
  2816. " done = 1;",
  2817. " wrapup();",
  2818. " exit(0);",
  2819. "}",
  2820. "#endif", /* WIN32 || WIN64 */
  2821. "",
  2822. "#ifdef BITSTATE",
  2823. "void",
  2824. "init_SS(unsigned long n)",
  2825. "{",
  2826. " SS = (uchar *) prep_shmid_S((size_t) n);",
  2827. " init_HT(0L);", /* locks and shared memory for Stack_Tree allocations */
  2828. "}",
  2829. "#endif", /* BITSTATE */
  2830. "",
  2831. "#endif", /* NCORE>1 */
  2832. 0,
  2833. };