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