1 /* 2 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers 3 * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. 4 * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved. 5 * 6 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 7 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 8 * 9 * Permission is hereby granted to use or copy this program 10 * for any purpose, provided the above notices are retained on all copies. 11 * Permission to modify the code and to distribute modified code is granted, 12 * provided the above notices are retained, and a notice that the code was 13 * modified is included with the above copyright notice. 14 */ 15 /* Boehm, July 31, 1995 5:02 pm PDT */ 16 17 18 #include <stdio.h> 19 #include <limits.h> 20 #ifndef _WIN32_WCE 21 #include <signal.h> 22 #endif 23 24 #define I_HIDE_POINTERS /* To make GC_call_with_alloc_lock visible */ 25 #include "private/gc_pmark.h" 26 27 #ifdef GC_SOLARIS_THREADS 28 # include <sys/syscall.h> 29 #endif 30 #if defined(MSWIN32) || defined(MSWINCE) 31 # define WIN32_LEAN_AND_MEAN 32 # define NOSERVICE 33 # include <windows.h> 34 # include <tchar.h> 35 #endif 36 37 # ifdef THREADS 38 # ifdef PCR 39 # include "il/PCR_IL.h" 40 PCR_Th_ML GC_allocate_ml; 41 # else 42 # ifdef SRC_M3 43 /* Critical section counter is defined in the M3 runtime */ 44 /* That's all we use. */ 45 # else 46 # ifdef GC_SOLARIS_THREADS 47 mutex_t GC_allocate_ml; /* Implicitly initialized. */ 48 # else 49 # if defined(GC_WIN32_THREADS) 50 # if defined(GC_PTHREADS) 51 pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER; 52 # elif defined(GC_DLL) 53 __declspec(dllexport) CRITICAL_SECTION GC_allocate_ml; 54 # else 55 CRITICAL_SECTION GC_allocate_ml; 56 # endif 57 # else 58 # if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) 59 # if defined(USE_SPIN_LOCK) 60 pthread_t GC_lock_holder = NO_THREAD; 61 # else 62 pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER; 63 pthread_t GC_lock_holder = NO_THREAD; 64 /* Used only for assertions, and to prevent */ 65 /* recursive reentry in the system call wrapper. */ 66 # endif 67 # else 68 --> declare allocator lock here 69 # endif 70 # endif 71 # endif 72 # endif 73 # endif 74 # endif 75 76 #if defined(NOSYS) || defined(ECOS) 77 #undef STACKBASE 78 #endif 79 80 /* Dont unnecessarily call GC_register_main_static_data() in case */ 81 /* dyn_load.c isn't linked in. */ 82 #ifdef DYNAMIC_LOADING 83 # define GC_REGISTER_MAIN_STATIC_DATA() GC_register_main_static_data() 84 #else 85 # define GC_REGISTER_MAIN_STATIC_DATA() TRUE 86 #endif 87 88 GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */; 89 90 91 GC_bool GC_debugging_started = FALSE; 92 /* defined here so we don't have to load debug_malloc.o */ 93 94 void (*GC_check_heap) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0; 95 void (*GC_print_all_smashed) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0; 96 97 void (*GC_start_call_back) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0; 98 99 ptr_t GC_stackbottom = 0; 100 101 #ifdef IA64 102 ptr_t GC_register_stackbottom = 0; 103 #endif 104 105 GC_bool GC_dont_gc = 0; 106 107 GC_bool GC_dont_precollect = 0; 108 109 GC_bool GC_quiet = 0; 110 111 GC_bool GC_print_stats = 0; 112 113 GC_bool GC_print_back_height = 0; 114 115 #ifndef NO_DEBUGGING 116 GC_bool GC_dump_regularly = 0; /* Generate regular debugging dumps. */ 117 #endif 118 119 #ifdef FIND_LEAK 120 int GC_find_leak = 1; 121 #else 122 int GC_find_leak = 0; 123 #endif 124 125 #ifdef ALL_INTERIOR_POINTERS 126 int GC_all_interior_pointers = 1; 127 #else 128 int GC_all_interior_pointers = 0; 129 #endif 130 131 long GC_large_alloc_warn_interval = 5; 132 /* Interval between unsuppressed warnings. */ 133 134 long GC_large_alloc_warn_suppressed = 0; 135 /* Number of warnings suppressed so far. */ 136 137 /*ARGSUSED*/ 138 GC_PTR GC_default_oom_fn GC_PROTO((size_t bytes_requested)) 139 { 140 return(0); 141 } 142 143 GC_PTR (*GC_oom_fn) GC_PROTO((size_t bytes_requested)) = GC_default_oom_fn; 144 145 extern signed_word GC_mem_found; 146 147 void * GC_project2(arg1, arg2) 148 void *arg1; 149 void *arg2; 150 { 151 return arg2; 152 } 153 154 # ifdef MERGE_SIZES 155 /* Set things up so that GC_size_map[i] >= words(i), */ 156 /* but not too much bigger */ 157 /* and so that size_map contains relatively few distinct entries */ 158 /* This is stolen from Russ Atkinson's Cedar quantization */ 159 /* alogrithm (but we precompute it). */ 160 161 162 void GC_init_size_map() 163 { 164 register unsigned i; 165 166 /* Map size 0 to something bigger. */ 167 /* This avoids problems at lower levels. */ 168 /* One word objects don't have to be 2 word aligned, */ 169 /* unless we're using mark bytes. */ 170 for (i = 0; i < sizeof(word); i++) { 171 GC_size_map[i] = MIN_WORDS; 172 } 173 # if MIN_WORDS > 1 174 GC_size_map[sizeof(word)] = MIN_WORDS; 175 # else 176 GC_size_map[sizeof(word)] = ROUNDED_UP_WORDS(sizeof(word)); 177 # endif 178 for (i = sizeof(word) + 1; i <= 8 * sizeof(word); i++) { 179 GC_size_map[i] = ALIGNED_WORDS(i); 180 } 181 for (i = 8*sizeof(word) + 1; i <= 16 * sizeof(word); i++) { 182 GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1); 183 } 184 # ifdef GC_GCJ_SUPPORT 185 /* Make all sizes up to 32 words predictable, so that a */ 186 /* compiler can statically perform the same computation, */ 187 /* or at least a computation that results in similar size */ 188 /* classes. */ 189 for (i = 16*sizeof(word) + 1; i <= 32 * sizeof(word); i++) { 190 GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 3) & (~3); 191 } 192 # endif 193 /* We leave the rest of the array to be filled in on demand. */ 194 } 195 196 /* Fill in additional entries in GC_size_map, including the ith one */ 197 /* We assume the ith entry is currently 0. */ 198 /* Note that a filled in section of the array ending at n always */ 199 /* has length at least n/4. */ 200 void GC_extend_size_map(i) 201 word i; 202 { 203 word orig_word_sz = ROUNDED_UP_WORDS(i); 204 word word_sz = orig_word_sz; 205 register word byte_sz = WORDS_TO_BYTES(word_sz); 206 /* The size we try to preserve. */ 207 /* Close to to i, unless this would */ 208 /* introduce too many distinct sizes. */ 209 word smaller_than_i = byte_sz - (byte_sz >> 3); 210 word much_smaller_than_i = byte_sz - (byte_sz >> 2); 211 register word low_limit; /* The lowest indexed entry we */ 212 /* initialize. */ 213 register word j; 214 215 if (GC_size_map[smaller_than_i] == 0) { 216 low_limit = much_smaller_than_i; 217 while (GC_size_map[low_limit] != 0) low_limit++; 218 } else { 219 low_limit = smaller_than_i + 1; 220 while (GC_size_map[low_limit] != 0) low_limit++; 221 word_sz = ROUNDED_UP_WORDS(low_limit); 222 word_sz += word_sz >> 3; 223 if (word_sz < orig_word_sz) word_sz = orig_word_sz; 224 } 225 # ifdef ALIGN_DOUBLE 226 word_sz += 1; 227 word_sz &= ~1; 228 # endif 229 if (word_sz > MAXOBJSZ) { 230 word_sz = MAXOBJSZ; 231 } 232 /* If we can fit the same number of larger objects in a block, */ 233 /* do so. */ 234 { 235 size_t number_of_objs = BODY_SZ/word_sz; 236 word_sz = BODY_SZ/number_of_objs; 237 # ifdef ALIGN_DOUBLE 238 word_sz &= ~1; 239 # endif 240 } 241 byte_sz = WORDS_TO_BYTES(word_sz); 242 if (GC_all_interior_pointers) { 243 /* We need one extra byte; don't fill in GC_size_map[byte_sz] */ 244 byte_sz--; 245 } 246 247 for (j = low_limit; j <= byte_sz; j++) GC_size_map[j] = word_sz; 248 } 249 # endif 250 251 252 /* 253 * The following is a gross hack to deal with a problem that can occur 254 * on machines that are sloppy about stack frame sizes, notably SPARC. 255 * Bogus pointers may be written to the stack and not cleared for 256 * a LONG time, because they always fall into holes in stack frames 257 * that are not written. We partially address this by clearing 258 * sections of the stack whenever we get control. 259 */ 260 word GC_stack_last_cleared = 0; /* GC_no when we last did this */ 261 # ifdef THREADS 262 # define BIG_CLEAR_SIZE 2048 /* Clear this much now and then. */ 263 # define SMALL_CLEAR_SIZE 256 /* Clear this much every time. */ 264 # endif 265 # define CLEAR_SIZE 213 /* Granularity for GC_clear_stack_inner */ 266 # define DEGRADE_RATE 50 267 268 word GC_min_sp; /* Coolest stack pointer value from which we've */ 269 /* already cleared the stack. */ 270 271 word GC_high_water; 272 /* "hottest" stack pointer value we have seen */ 273 /* recently. Degrades over time. */ 274 275 word GC_words_allocd_at_reset; 276 277 #if defined(ASM_CLEAR_CODE) 278 extern ptr_t GC_clear_stack_inner(); 279 #else 280 /* Clear the stack up to about limit. Return arg. */ 281 /*ARGSUSED*/ 282 ptr_t GC_clear_stack_inner(arg, limit) 283 ptr_t arg; 284 word limit; 285 { 286 word dummy[CLEAR_SIZE]; 287 288 BZERO(dummy, CLEAR_SIZE*sizeof(word)); 289 if ((word)(dummy) COOLER_THAN limit) { 290 (void) GC_clear_stack_inner(arg, limit); 291 } 292 /* Make sure the recursive call is not a tail call, and the bzero */ 293 /* call is not recognized as dead code. */ 294 GC_noop1((word)dummy); 295 return(arg); 296 } 297 #endif 298 299 /* Clear some of the inaccessible part of the stack. Returns its */ 300 /* argument, so it can be used in a tail call position, hence clearing */ 301 /* another frame. */ 302 ptr_t GC_clear_stack(arg) 303 ptr_t arg; 304 { 305 register word sp = (word)GC_approx_sp(); /* Hotter than actual sp */ 306 # ifdef THREADS 307 word dummy[SMALL_CLEAR_SIZE]; 308 static unsigned random_no = 0; 309 /* Should be more random than it is ... */ 310 /* Used to occasionally clear a bigger */ 311 /* chunk. */ 312 # endif 313 register word limit; 314 315 # define SLOP 400 316 /* Extra bytes we clear every time. This clears our own */ 317 /* activation record, and should cause more frequent */ 318 /* clearing near the cold end of the stack, a good thing. */ 319 # define GC_SLOP 4000 320 /* We make GC_high_water this much hotter than we really saw */ 321 /* saw it, to cover for GC noise etc. above our current frame. */ 322 # define CLEAR_THRESHOLD 100000 323 /* We restart the clearing process after this many bytes of */ 324 /* allocation. Otherwise very heavily recursive programs */ 325 /* with sparse stacks may result in heaps that grow almost */ 326 /* without bounds. As the heap gets larger, collection */ 327 /* frequency decreases, thus clearing frequency would decrease, */ 328 /* thus more junk remains accessible, thus the heap gets */ 329 /* larger ... */ 330 # ifdef THREADS 331 if (++random_no % 13 == 0) { 332 limit = sp; 333 MAKE_HOTTER(limit, BIG_CLEAR_SIZE*sizeof(word)); 334 limit &= ~0xf; /* Make it sufficiently aligned for assembly */ 335 /* implementations of GC_clear_stack_inner. */ 336 return GC_clear_stack_inner(arg, limit); 337 } else { 338 BZERO(dummy, SMALL_CLEAR_SIZE*sizeof(word)); 339 return arg; 340 } 341 # else 342 if (GC_gc_no > GC_stack_last_cleared) { 343 /* Start things over, so we clear the entire stack again */ 344 if (GC_stack_last_cleared == 0) GC_high_water = (word) GC_stackbottom; 345 GC_min_sp = GC_high_water; 346 GC_stack_last_cleared = GC_gc_no; 347 GC_words_allocd_at_reset = GC_words_allocd; 348 } 349 /* Adjust GC_high_water */ 350 MAKE_COOLER(GC_high_water, WORDS_TO_BYTES(DEGRADE_RATE) + GC_SLOP); 351 if (sp HOTTER_THAN GC_high_water) { 352 GC_high_water = sp; 353 } 354 MAKE_HOTTER(GC_high_water, GC_SLOP); 355 limit = GC_min_sp; 356 MAKE_HOTTER(limit, SLOP); 357 if (sp COOLER_THAN limit) { 358 limit &= ~0xf; /* Make it sufficiently aligned for assembly */ 359 /* implementations of GC_clear_stack_inner. */ 360 GC_min_sp = sp; 361 return(GC_clear_stack_inner(arg, limit)); 362 } else if (WORDS_TO_BYTES(GC_words_allocd - GC_words_allocd_at_reset) 363 > CLEAR_THRESHOLD) { 364 /* Restart clearing process, but limit how much clearing we do. */ 365 GC_min_sp = sp; 366 MAKE_HOTTER(GC_min_sp, CLEAR_THRESHOLD/4); 367 if (GC_min_sp HOTTER_THAN GC_high_water) GC_min_sp = GC_high_water; 368 GC_words_allocd_at_reset = GC_words_allocd; 369 } 370 return(arg); 371 # endif 372 } 373 374 375 /* Return a pointer to the base address of p, given a pointer to a */ 376 /* an address within an object. Return 0 o.w. */ 377 # ifdef __STDC__ 378 GC_PTR GC_base(GC_PTR p) 379 # else 380 GC_PTR GC_base(p) 381 GC_PTR p; 382 # endif 383 { 384 register word r; 385 register struct hblk *h; 386 register bottom_index *bi; 387 register hdr *candidate_hdr; 388 register word limit; 389 390 r = (word)p; 391 if (!GC_is_initialized) return 0; 392 h = HBLKPTR(r); 393 GET_BI(r, bi); 394 candidate_hdr = HDR_FROM_BI(bi, r); 395 if (candidate_hdr == 0) return(0); 396 /* If it's a pointer to the middle of a large object, move it */ 397 /* to the beginning. */ 398 while (IS_FORWARDING_ADDR_OR_NIL(candidate_hdr)) { 399 h = FORWARDED_ADDR(h,candidate_hdr); 400 r = (word)h; 401 candidate_hdr = HDR(h); 402 } 403 if (candidate_hdr -> hb_map == GC_invalid_map) return(0); 404 /* Make sure r points to the beginning of the object */ 405 r &= ~(WORDS_TO_BYTES(1) - 1); 406 { 407 register int offset = HBLKDISPL(r); 408 register signed_word sz = candidate_hdr -> hb_sz; 409 register signed_word map_entry; 410 411 map_entry = MAP_ENTRY((candidate_hdr -> hb_map), offset); 412 if (map_entry > CPP_MAX_OFFSET) { 413 map_entry = (signed_word)(BYTES_TO_WORDS(offset)) % sz; 414 } 415 r -= WORDS_TO_BYTES(map_entry); 416 limit = r + WORDS_TO_BYTES(sz); 417 if (limit > (word)(h + 1) 418 && sz <= BYTES_TO_WORDS(HBLKSIZE)) { 419 return(0); 420 } 421 if ((word)p >= limit) return(0); 422 } 423 return((GC_PTR)r); 424 } 425 426 427 /* Return the size of an object, given a pointer to its base. */ 428 /* (For small obects this also happens to work from interior pointers, */ 429 /* but that shouldn't be relied upon.) */ 430 # ifdef __STDC__ 431 size_t GC_size(GC_PTR p) 432 # else 433 size_t GC_size(p) 434 GC_PTR p; 435 # endif 436 { 437 register int sz; 438 register hdr * hhdr = HDR(p); 439 440 sz = WORDS_TO_BYTES(hhdr -> hb_sz); 441 return(sz); 442 } 443 444 size_t GC_get_heap_size GC_PROTO(()) 445 { 446 return ((size_t) GC_heapsize); 447 } 448 449 size_t GC_get_free_bytes GC_PROTO(()) 450 { 451 return ((size_t) GC_large_free_bytes); 452 } 453 454 size_t GC_get_bytes_since_gc GC_PROTO(()) 455 { 456 return ((size_t) WORDS_TO_BYTES(GC_words_allocd)); 457 } 458 459 size_t GC_get_total_bytes GC_PROTO(()) 460 { 461 return ((size_t) WORDS_TO_BYTES(GC_words_allocd+GC_words_allocd_before_gc)); 462 } 463 464 GC_bool GC_is_initialized = FALSE; 465 466 void GC_init() 467 { 468 DCL_LOCK_STATE; 469 470 DISABLE_SIGNALS(); 471 472 #if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) 473 if (!GC_is_initialized) InitializeCriticalSection(&GC_allocate_ml); 474 #endif /* MSWIN32 */ 475 476 LOCK(); 477 GC_init_inner(); 478 UNLOCK(); 479 ENABLE_SIGNALS(); 480 481 # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) 482 /* Make sure marker threads and started and thread local */ 483 /* allocation is initialized, in case we didn't get */ 484 /* called from GC_init_parallel(); */ 485 { 486 extern void GC_init_parallel(void); 487 GC_init_parallel(); 488 } 489 # endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */ 490 491 # if defined(DYNAMIC_LOADING) && defined(DARWIN) 492 { 493 /* This must be called WITHOUT the allocation lock held 494 and before any threads are created */ 495 extern void GC_init_dyld(); 496 GC_init_dyld(); 497 } 498 # endif 499 } 500 501 #if defined(MSWIN32) || defined(MSWINCE) 502 CRITICAL_SECTION GC_write_cs; 503 #endif 504 505 #ifdef MSWIN32 506 extern void GC_init_win32 GC_PROTO((void)); 507 #endif 508 509 extern void GC_setpagesize(); 510 511 512 #ifdef MSWIN32 513 extern GC_bool GC_no_win32_dlls; 514 #else 515 # define GC_no_win32_dlls FALSE 516 #endif 517 518 void GC_exit_check GC_PROTO((void)) 519 { 520 GC_gcollect(); 521 } 522 523 #ifdef SEARCH_FOR_DATA_START 524 extern void GC_init_linux_data_start GC_PROTO((void)); 525 #endif 526 527 #ifdef UNIX_LIKE 528 529 extern void GC_set_and_save_fault_handler GC_PROTO((void (*handler)(int))); 530 531 static void looping_handler(sig) 532 int sig; 533 { 534 GC_err_printf1("Caught signal %d: looping in handler\n", sig); 535 for(;;); 536 } 537 538 static GC_bool installed_looping_handler = FALSE; 539 540 void maybe_install_looping_handler() 541 { 542 /* Install looping handler before the write fault handler, so we */ 543 /* handle write faults correctly. */ 544 if (!installed_looping_handler && 0 != GETENV("GC_LOOP_ON_ABORT")) { 545 GC_set_and_save_fault_handler(looping_handler); 546 installed_looping_handler = TRUE; 547 } 548 } 549 550 #else /* !UNIX_LIKE */ 551 552 # define maybe_install_looping_handler() 553 554 #endif 555 556 void GC_init_inner() 557 { 558 # if !defined(THREADS) && defined(GC_ASSERTIONS) 559 word dummy; 560 # endif 561 word initial_heap_sz = (word)MINHINCR; 562 563 if (GC_is_initialized) return; 564 # ifdef PRINTSTATS 565 GC_print_stats = 1; 566 # endif 567 # if defined(MSWIN32) || defined(MSWINCE) 568 InitializeCriticalSection(&GC_write_cs); 569 # endif 570 if (0 != GETENV("GC_PRINT_STATS")) { 571 GC_print_stats = 1; 572 } 573 # ifndef NO_DEBUGGING 574 if (0 != GETENV("GC_DUMP_REGULARLY")) { 575 GC_dump_regularly = 1; 576 } 577 # endif 578 if (0 != GETENV("GC_FIND_LEAK")) { 579 GC_find_leak = 1; 580 # ifdef __STDC__ 581 atexit(GC_exit_check); 582 # endif 583 } 584 if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) { 585 GC_all_interior_pointers = 1; 586 } 587 if (0 != GETENV("GC_DONT_GC")) { 588 GC_dont_gc = 1; 589 } 590 if (0 != GETENV("GC_PRINT_BACK_HEIGHT")) { 591 GC_print_back_height = 1; 592 } 593 if (0 != GETENV("GC_NO_BLACKLIST_WARNING")) { 594 GC_large_alloc_warn_interval = LONG_MAX; 595 } 596 { 597 char * time_limit_string = GETENV("GC_PAUSE_TIME_TARGET"); 598 if (0 != time_limit_string) { 599 long time_limit = atol(time_limit_string); 600 if (time_limit < 5) { 601 WARN("GC_PAUSE_TIME_TARGET environment variable value too small " 602 "or bad syntax: Ignoring\n", 0); 603 } else { 604 GC_time_limit = time_limit; 605 } 606 } 607 } 608 { 609 char * interval_string = GETENV("GC_LARGE_ALLOC_WARN_INTERVAL"); 610 if (0 != interval_string) { 611 long interval = atol(interval_string); 612 if (interval <= 0) { 613 WARN("GC_LARGE_ALLOC_WARN_INTERVAL environment variable has " 614 "bad value: Ignoring\n", 0); 615 } else { 616 GC_large_alloc_warn_interval = interval; 617 } 618 } 619 } 620 maybe_install_looping_handler(); 621 /* Adjust normal object descriptor for extra allocation. */ 622 if (ALIGNMENT > GC_DS_TAGS && EXTRA_BYTES != 0) { 623 GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH); 624 } 625 GC_setpagesize(); 626 GC_exclude_static_roots(beginGC_arrays, endGC_arrays); 627 GC_exclude_static_roots(beginGC_obj_kinds, endGC_obj_kinds); 628 # ifdef SEPARATE_GLOBALS 629 GC_exclude_static_roots(beginGC_objfreelist, endGC_objfreelist); 630 GC_exclude_static_roots(beginGC_aobjfreelist, endGC_aobjfreelist); 631 # endif 632 # ifdef MSWIN32 633 GC_init_win32(); 634 # endif 635 # if defined(SEARCH_FOR_DATA_START) 636 GC_init_linux_data_start(); 637 # endif 638 # if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__) 639 GC_init_netbsd_elf(); 640 # endif 641 # if defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS) \ 642 || defined(GC_WIN32_THREADS) 643 GC_thr_init(); 644 # endif 645 # ifdef GC_SOLARIS_THREADS 646 /* We need dirty bits in order to find live stack sections. */ 647 GC_dirty_init(); 648 # endif 649 # if !defined(THREADS) || defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) \ 650 || defined(GC_SOLARIS_THREADS) 651 if (GC_stackbottom == 0) { 652 GC_stackbottom = GC_get_stack_base(); 653 # if defined(LINUX) && defined(IA64) 654 GC_register_stackbottom = GC_get_register_stack_base(); 655 # endif 656 } else { 657 # if defined(LINUX) && defined(IA64) 658 if (GC_register_stackbottom == 0) { 659 WARN("GC_register_stackbottom should be set with GC_stackbottom", 0); 660 /* The following is likely to fail, since we rely on */ 661 /* alignment properties that may not hold with a user set */ 662 /* GC_stackbottom. */ 663 GC_register_stackbottom = GC_get_register_stack_base(); 664 } 665 # endif 666 } 667 # endif 668 GC_STATIC_ASSERT(sizeof (ptr_t) == sizeof(word)); 669 GC_STATIC_ASSERT(sizeof (signed_word) == sizeof(word)); 670 GC_STATIC_ASSERT(sizeof (struct hblk) == HBLKSIZE); 671 # ifndef THREADS 672 # if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN) 673 ABORT( 674 "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n"); 675 # endif 676 # if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN) 677 ABORT( 678 "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n"); 679 # endif 680 # ifdef STACK_GROWS_DOWN 681 GC_ASSERT((word)(&dummy) <= (word)GC_stackbottom); 682 # else 683 GC_ASSERT((word)(&dummy) >= (word)GC_stackbottom); 684 # endif 685 # endif 686 # if !defined(_AUX_SOURCE) || defined(__GNUC__) 687 GC_ASSERT((word)(-1) > (word)0); 688 /* word should be unsigned */ 689 # endif 690 GC_ASSERT((signed_word)(-1) < (signed_word)0); 691 692 /* Add initial guess of root sets. Do this first, since sbrk(0) */ 693 /* might be used. */ 694 if (GC_REGISTER_MAIN_STATIC_DATA()) GC_register_data_segments(); 695 GC_init_headers(); 696 GC_bl_init(); 697 GC_mark_init(); 698 { 699 char * sz_str = GETENV("GC_INITIAL_HEAP_SIZE"); 700 if (sz_str != NULL) { 701 initial_heap_sz = atoi(sz_str); 702 if (initial_heap_sz <= MINHINCR * HBLKSIZE) { 703 WARN("Bad initial heap size %s - ignoring it.\n", 704 sz_str); 705 } 706 initial_heap_sz = divHBLKSZ(initial_heap_sz); 707 } 708 } 709 { 710 char * sz_str = GETENV("GC_MAXIMUM_HEAP_SIZE"); 711 if (sz_str != NULL) { 712 word max_heap_sz = (word)atol(sz_str); 713 if (max_heap_sz < initial_heap_sz * HBLKSIZE) { 714 WARN("Bad maximum heap size %s - ignoring it.\n", 715 sz_str); 716 } 717 if (0 == GC_max_retries) GC_max_retries = 2; 718 GC_set_max_heap_size(max_heap_sz); 719 } 720 } 721 if (!GC_expand_hp_inner(initial_heap_sz)) { 722 GC_err_printf0("Can't start up: not enough memory\n"); 723 EXIT(); 724 } 725 /* Preallocate large object map. It's otherwise inconvenient to */ 726 /* deal with failure. */ 727 if (!GC_add_map_entry((word)0)) { 728 GC_err_printf0("Can't start up: not enough memory\n"); 729 EXIT(); 730 } 731 GC_register_displacement_inner(0L); 732 # ifdef MERGE_SIZES 733 GC_init_size_map(); 734 # endif 735 # ifdef PCR 736 if (PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever) 737 != PCR_ERes_okay) { 738 ABORT("Can't lock load state\n"); 739 } else if (PCR_IL_Unlock() != PCR_ERes_okay) { 740 ABORT("Can't unlock load state\n"); 741 } 742 PCR_IL_Unlock(); 743 GC_pcr_install(); 744 # endif 745 # if !defined(SMALL_CONFIG) 746 if (!GC_no_win32_dlls && 0 != GETENV("GC_ENABLE_INCREMENTAL")) { 747 GC_ASSERT(!GC_incremental); 748 GC_setpagesize(); 749 # ifndef GC_SOLARIS_THREADS 750 GC_dirty_init(); 751 # endif 752 GC_ASSERT(GC_words_allocd == 0) 753 GC_incremental = TRUE; 754 } 755 # endif /* !SMALL_CONFIG */ 756 COND_DUMP; 757 /* Get black list set up and/or incrmental GC started */ 758 if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner(); 759 GC_is_initialized = TRUE; 760 # ifdef STUBBORN_ALLOC 761 GC_stubborn_init(); 762 # endif 763 /* Convince lint that some things are used */ 764 # ifdef LINT 765 { 766 extern char * GC_copyright[]; 767 extern int GC_read(); 768 extern void GC_register_finalizer_no_order(); 769 770 GC_noop(GC_copyright, GC_find_header, 771 GC_push_one, GC_call_with_alloc_lock, GC_read, 772 GC_dont_expand, 773 # ifndef NO_DEBUGGING 774 GC_dump, 775 # endif 776 GC_register_finalizer_no_order); 777 } 778 # endif 779 } 780 781 void GC_enable_incremental GC_PROTO(()) 782 { 783 # if !defined(SMALL_CONFIG) 784 if (!GC_find_leak) { 785 DCL_LOCK_STATE; 786 787 DISABLE_SIGNALS(); 788 LOCK(); 789 if (GC_incremental) goto out; 790 GC_setpagesize(); 791 if (GC_no_win32_dlls) goto out; 792 # ifndef GC_SOLARIS_THREADS 793 maybe_install_looping_handler(); /* Before write fault handler! */ 794 GC_dirty_init(); 795 # endif 796 if (!GC_is_initialized) { 797 GC_init_inner(); 798 } 799 if (GC_incremental) goto out; 800 if (GC_dont_gc) { 801 /* Can't easily do it. */ 802 UNLOCK(); 803 ENABLE_SIGNALS(); 804 return; 805 } 806 if (GC_words_allocd > 0) { 807 /* There may be unmarked reachable objects */ 808 GC_gcollect_inner(); 809 } /* else we're OK in assuming everything's */ 810 /* clean since nothing can point to an */ 811 /* unmarked object. */ 812 GC_read_dirty(); 813 GC_incremental = TRUE; 814 out: 815 UNLOCK(); 816 ENABLE_SIGNALS(); 817 } 818 # endif 819 } 820 821 822 #if defined(MSWIN32) || defined(MSWINCE) 823 # define LOG_FILE _T("gc.log") 824 825 HANDLE GC_stdout = 0; 826 827 void GC_deinit() 828 { 829 if (GC_is_initialized) { 830 DeleteCriticalSection(&GC_write_cs); 831 } 832 } 833 834 int GC_write(buf, len) 835 GC_CONST char * buf; 836 size_t len; 837 { 838 BOOL tmp; 839 DWORD written; 840 if (len == 0) 841 return 0; 842 EnterCriticalSection(&GC_write_cs); 843 if (GC_stdout == INVALID_HANDLE_VALUE) { 844 return -1; 845 } else if (GC_stdout == 0) { 846 GC_stdout = CreateFile(LOG_FILE, GENERIC_WRITE, 847 FILE_SHARE_READ | FILE_SHARE_WRITE, 848 NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 849 NULL); 850 if (GC_stdout == INVALID_HANDLE_VALUE) ABORT("Open of log file failed"); 851 } 852 tmp = WriteFile(GC_stdout, buf, len, &written, NULL); 853 if (!tmp) 854 DebugBreak(); 855 LeaveCriticalSection(&GC_write_cs); 856 return tmp ? (int)written : -1; 857 } 858 859 #endif 860 861 #if defined(OS2) || defined(MACOS) 862 FILE * GC_stdout = NULL; 863 FILE * GC_stderr = NULL; 864 int GC_tmp; /* Should really be local ... */ 865 866 void GC_set_files() 867 { 868 if (GC_stdout == NULL) { 869 GC_stdout = stdout; 870 } 871 if (GC_stderr == NULL) { 872 GC_stderr = stderr; 873 } 874 } 875 #endif 876 877 #if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE) 878 int GC_stdout = 1; 879 int GC_stderr = 2; 880 # if !defined(AMIGA) 881 # include <unistd.h> 882 # endif 883 #endif 884 885 #if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) \ 886 && !defined(MACOS) && !defined(ECOS) && !defined(NOSYS) 887 int GC_write(fd, buf, len) 888 int fd; 889 GC_CONST char *buf; 890 size_t len; 891 { 892 register int bytes_written = 0; 893 register int result; 894 895 while (bytes_written < len) { 896 # ifdef GC_SOLARIS_THREADS 897 result = syscall(SYS_write, fd, buf + bytes_written, 898 len - bytes_written); 899 # else 900 result = write(fd, buf + bytes_written, len - bytes_written); 901 # endif 902 if (-1 == result) return(result); 903 bytes_written += result; 904 } 905 return(bytes_written); 906 } 907 #endif /* UN*X */ 908 909 #ifdef ECOS 910 int GC_write(fd, buf, len) 911 { 912 _Jv_diag_write (buf, len); 913 return len; 914 } 915 #endif 916 917 #ifdef NOSYS 918 int GC_write(fd, buf, len) 919 { 920 /* No writing. */ 921 return len; 922 } 923 #endif 924 925 926 #if defined(MSWIN32) || defined(MSWINCE) 927 # define WRITE(f, buf, len) GC_write(buf, len) 928 #else 929 # if defined(OS2) || defined(MACOS) 930 # define WRITE(f, buf, len) (GC_set_files(), \ 931 GC_tmp = fwrite((buf), 1, (len), (f)), \ 932 fflush(f), GC_tmp) 933 # else 934 # define WRITE(f, buf, len) GC_write((f), (buf), (len)) 935 # endif 936 #endif 937 938 /* A version of printf that is unlikely to call malloc, and is thus safer */ 939 /* to call from the collector in case malloc has been bound to GC_malloc. */ 940 /* Assumes that no more than 1023 characters are written at once. */ 941 /* Assumes that all arguments have been converted to something of the */ 942 /* same size as long, and that the format conversions expect something */ 943 /* of that size. */ 944 void GC_printf(format, a, b, c, d, e, f) 945 GC_CONST char * format; 946 long a, b, c, d, e, f; 947 { 948 char buf[1025]; 949 950 if (GC_quiet) return; 951 buf[1024] = 0x15; 952 (void) sprintf(buf, format, a, b, c, d, e, f); 953 if (buf[1024] != 0x15) ABORT("GC_printf clobbered stack"); 954 if (WRITE(GC_stdout, buf, strlen(buf)) < 0) ABORT("write to stdout failed"); 955 } 956 957 void GC_err_printf(format, a, b, c, d, e, f) 958 GC_CONST char * format; 959 long a, b, c, d, e, f; 960 { 961 char buf[1025]; 962 963 buf[1024] = 0x15; 964 (void) sprintf(buf, format, a, b, c, d, e, f); 965 if (buf[1024] != 0x15) ABORT("GC_err_printf clobbered stack"); 966 if (WRITE(GC_stderr, buf, strlen(buf)) < 0) ABORT("write to stderr failed"); 967 } 968 969 void GC_err_puts(s) 970 GC_CONST char *s; 971 { 972 if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed"); 973 } 974 975 #if defined(LINUX) && !defined(SMALL_CONFIG) 976 void GC_err_write(buf, len) 977 GC_CONST char *buf; 978 size_t len; 979 { 980 if (WRITE(GC_stderr, buf, len) < 0) ABORT("write to stderr failed"); 981 } 982 #endif 983 984 # if defined(__STDC__) || defined(__cplusplus) 985 void GC_default_warn_proc(char *msg, GC_word arg) 986 # else 987 void GC_default_warn_proc(msg, arg) 988 char *msg; 989 GC_word arg; 990 # endif 991 { 992 GC_err_printf1(msg, (unsigned long)arg); 993 } 994 995 GC_warn_proc GC_current_warn_proc = GC_default_warn_proc; 996 997 # if defined(__STDC__) || defined(__cplusplus) 998 GC_warn_proc GC_set_warn_proc(GC_warn_proc p) 999 # else 1000 GC_warn_proc GC_set_warn_proc(p) 1001 GC_warn_proc p; 1002 # endif 1003 { 1004 GC_warn_proc result; 1005 1006 # ifdef GC_WIN32_THREADS 1007 GC_ASSERT(GC_is_initialized); 1008 # endif 1009 LOCK(); 1010 result = GC_current_warn_proc; 1011 GC_current_warn_proc = p; 1012 UNLOCK(); 1013 return(result); 1014 } 1015 1016 # if defined(__STDC__) || defined(__cplusplus) 1017 GC_word GC_set_free_space_divisor (GC_word value) 1018 # else 1019 GC_word GC_set_free_space_divisor (value) 1020 GC_word value; 1021 # endif 1022 { 1023 GC_word old = GC_free_space_divisor; 1024 GC_free_space_divisor = value; 1025 return old; 1026 } 1027 1028 #ifndef PCR 1029 void GC_abort(msg) 1030 GC_CONST char * msg; 1031 { 1032 # if defined(MSWIN32) 1033 (void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK); 1034 DebugBreak(); 1035 # else 1036 GC_err_printf1("%s\n", msg); 1037 # endif 1038 if (GETENV("GC_LOOP_ON_ABORT") != NULL) { 1039 /* In many cases it's easier to debug a running process. */ 1040 /* It's arguably nicer to sleep, but that makes it harder */ 1041 /* to look at the thread if the debugger doesn't know much */ 1042 /* about threads. */ 1043 for(;;) {} 1044 } 1045 # ifdef MSWIN32 1046 DebugBreak(); 1047 # else 1048 (void) abort(); 1049 # endif 1050 } 1051 #endif 1052 1053 void GC_enable() 1054 { 1055 LOCK(); 1056 GC_dont_gc--; 1057 UNLOCK(); 1058 } 1059 1060 void GC_disable() 1061 { 1062 LOCK(); 1063 GC_dont_gc++; 1064 UNLOCK(); 1065 } 1066 1067 #if !defined(NO_DEBUGGING) 1068 1069 void GC_dump() 1070 { 1071 GC_printf0("***Static roots:\n"); 1072 GC_print_static_roots(); 1073 GC_printf0("\n***Heap sections:\n"); 1074 GC_print_heap_sects(); 1075 GC_printf0("\n***Free blocks:\n"); 1076 GC_print_hblkfreelist(); 1077 GC_printf0("\n***Blocks in use:\n"); 1078 GC_print_block_list(); 1079 GC_printf0("\n***Finalization statistics:\n"); 1080 GC_print_finalization_stats(); 1081 } 1082 1083 #endif /* NO_DEBUGGING */ 1084