[BACK]Return to misc.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / gc

Annotation of OpenXM_contrib2/asir2000/gc/misc.c, Revision 1.7

1.1       noro        1: /*
                      2:  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
                      3:  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
1.6       noro        4:  * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved.
1.1       noro        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>
1.6       noro       19: #include <limits.h>
1.4       noro       20: #ifndef _WIN32_WCE
1.1       noro       21: #include <signal.h>
1.4       noro       22: #endif
1.1       noro       23:
                     24: #define I_HIDE_POINTERS        /* To make GC_call_with_alloc_lock visible */
1.4       noro       25: #include "private/gc_pmark.h"
1.1       noro       26:
1.6       noro       27: #ifdef GC_SOLARIS_THREADS
1.1       noro       28: # include <sys/syscall.h>
                     29: #endif
1.4       noro       30: #if defined(MSWIN32) || defined(MSWINCE)
                     31: # define WIN32_LEAN_AND_MEAN
                     32: # define NOSERVICE
1.1       noro       33: # include <windows.h>
1.4       noro       34: # include <tchar.h>
1.1       noro       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
1.6       noro       46: #      ifdef GC_SOLARIS_THREADS
1.1       noro       47:          mutex_t GC_allocate_ml;       /* Implicitly initialized.      */
                     48: #      else
1.6       noro       49: #          if defined(GC_WIN32_THREADS)
                     50: #             if defined(GC_PTHREADS)
                     51:                  pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
1.7     ! noro       52: #            elif defined(GC_DLL)
1.4       noro       53:                 __declspec(dllexport) CRITICAL_SECTION GC_allocate_ml;
                     54: #            else
                     55:                 CRITICAL_SECTION GC_allocate_ml;
                     56: #            endif
1.1       noro       57: #          else
1.6       noro       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
1.2       noro       62:                  pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
1.4       noro       63:                  pthread_t GC_lock_holder = NO_THREAD;
                     64:                        /* Used only for assertions, and to prevent      */
                     65:                        /* recursive reentry in the system call wrapper. */
1.6       noro       66: #              endif
                     67: #            else
1.2       noro       68:                  --> declare allocator lock here
1.1       noro       69: #            endif
                     70: #         endif
                     71: #      endif
                     72: #     endif
                     73: #   endif
                     74: # endif
                     75:
1.6       noro       76: #if defined(NOSYS) || defined(ECOS)
                     77: #undef STACKBASE
                     78: #endif
                     79:
1.7     ! noro       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:
1.1       noro       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:
1.4       noro       94: void (*GC_check_heap) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0;
1.6       noro       95: void (*GC_print_all_smashed) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0;
1.1       noro       96:
1.4       noro       97: void (*GC_start_call_back) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0;
1.1       noro       98:
                     99: ptr_t GC_stackbottom = 0;
                    100:
1.4       noro      101: #ifdef IA64
                    102:   ptr_t GC_register_stackbottom = 0;
                    103: #endif
                    104:
1.1       noro      105: GC_bool GC_dont_gc = 0;
                    106:
1.4       noro      107: GC_bool GC_dont_precollect = 0;
                    108:
1.1       noro      109: GC_bool GC_quiet = 0;
                    110:
1.4       noro      111: GC_bool GC_print_stats = 0;
                    112:
1.6       noro      113: GC_bool GC_print_back_height = 0;
                    114:
1.7     ! noro      115: #ifndef NO_DEBUGGING
        !           116:   GC_bool GC_dump_regularly = 0;  /* Generate regular debugging dumps. */
        !           117: #endif
        !           118:
1.2       noro      119: #ifdef FIND_LEAK
                    120:   int GC_find_leak = 1;
                    121: #else
                    122:   int GC_find_leak = 0;
                    123: #endif
                    124:
1.4       noro      125: #ifdef ALL_INTERIOR_POINTERS
                    126:   int GC_all_interior_pointers = 1;
                    127: #else
                    128:   int GC_all_interior_pointers = 0;
                    129: #endif
                    130:
1.6       noro      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:
1.1       noro      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:
1.7     ! noro      147: void * GC_project2(arg1, arg2)
        !           148: void *arg1;
        !           149: void *arg2;
        !           150: {
        !           151:   return arg2;
        !           152: }
        !           153:
1.1       noro      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:
1.4       noro      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;
1.1       noro      172:          }
1.4       noro      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
1.1       noro      178:        for (i = sizeof(word) + 1; i <= 8 * sizeof(word); i++) {
1.4       noro      179:            GC_size_map[i] = ALIGNED_WORDS(i);
1.1       noro      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:        }
1.3       noro      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
1.1       noro      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);
1.4       noro      242:        if (GC_all_interior_pointers) {
1.1       noro      243:            /* We need one extra byte; don't fill in GC_size_map[byte_sz] */
                    244:            byte_sz--;
1.4       noro      245:        }
1.1       noro      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
1.4       noro      262: #   define BIG_CLEAR_SIZE 2048 /* Clear this much now and then.        */
                    263: #   define SMALL_CLEAR_SIZE 256 /* Clear this much every time.         */
1.1       noro      264: # endif
1.4       noro      265: # define CLEAR_SIZE 213  /* Granularity for GC_clear_stack_inner */
1.1       noro      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:
1.4       noro      277: #if defined(ASM_CLEAR_CODE)
1.1       noro      278:   extern ptr_t GC_clear_stack_inner();
1.4       noro      279: #else
1.1       noro      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
1.4       noro      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.                               */
1.1       noro      312: #   endif
1.4       noro      313:     register word limit;
1.1       noro      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
1.4       noro      331:     if (++random_no % 13 == 0) {
                    332:        limit = sp;
                    333:        MAKE_HOTTER(limit, BIG_CLEAR_SIZE*sizeof(word));
1.6       noro      334:         limit &= ~0xf; /* Make it sufficiently aligned for assembly    */
                    335:                        /* implementations of GC_clear_stack_inner.     */
1.4       noro      336:        return GC_clear_stack_inner(arg, limit);
                    337:     } else {
                    338:        BZERO(dummy, SMALL_CLEAR_SIZE*sizeof(word));
                    339:        return arg;
                    340:     }
1.1       noro      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:     }
1.4       noro      370:     return(arg);
1.1       noro      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);
1.4       noro      400:           r = (word)h;
1.1       noro      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:         {
1.4       noro      407:            register int offset = HBLKDISPL(r);
1.1       noro      408:            register signed_word sz = candidate_hdr -> hb_sz;
1.4       noro      409:            register signed_word map_entry;
1.1       noro      410:
1.4       noro      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)) {
1.1       noro      419:                return(0);
1.4       noro      420:            }
1.1       noro      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);
1.4       noro      441:     return(sz);
1.1       noro      442: }
                    443:
                    444: size_t GC_get_heap_size GC_PROTO(())
                    445: {
                    446:     return ((size_t) GC_heapsize);
                    447: }
                    448:
1.2       noro      449: size_t GC_get_free_bytes GC_PROTO(())
                    450: {
                    451:     return ((size_t) GC_large_free_bytes);
                    452: }
                    453:
1.1       noro      454: size_t GC_get_bytes_since_gc GC_PROTO(())
                    455: {
                    456:     return ((size_t) WORDS_TO_BYTES(GC_words_allocd));
                    457: }
                    458:
1.4       noro      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:
1.1       noro      464: GC_bool GC_is_initialized = FALSE;
                    465:
                    466: void GC_init()
                    467: {
                    468:     DCL_LOCK_STATE;
                    469:
                    470:     DISABLE_SIGNALS();
1.6       noro      471:
                    472: #if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
                    473:     if (!GC_is_initialized) InitializeCriticalSection(&GC_allocate_ml);
                    474: #endif /* MSWIN32 */
                    475:
1.1       noro      476:     LOCK();
                    477:     GC_init_inner();
                    478:     UNLOCK();
                    479:     ENABLE_SIGNALS();
                    480:
1.6       noro      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 */
1.7     ! noro      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
1.1       noro      499: }
                    500:
1.4       noro      501: #if defined(MSWIN32) || defined(MSWINCE)
                    502:     CRITICAL_SECTION GC_write_cs;
                    503: #endif
                    504:
1.1       noro      505: #ifdef MSWIN32
1.4       noro      506:     extern void GC_init_win32 GC_PROTO((void));
1.1       noro      507: #endif
                    508:
                    509: extern void GC_setpagesize();
                    510:
1.7     ! noro      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:
1.4       noro      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:
1.7     ! noro      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:
1.6       noro      554: #endif
                    555:
1.1       noro      556: void GC_init_inner()
                    557: {
1.4       noro      558: #   if !defined(THREADS) && defined(GC_ASSERTIONS)
1.1       noro      559:         word dummy;
                    560: #   endif
1.4       noro      561:     word initial_heap_sz = (word)MINHINCR;
1.1       noro      562:
                    563:     if (GC_is_initialized) return;
1.4       noro      564: #   ifdef PRINTSTATS
                    565:       GC_print_stats = 1;
                    566: #   endif
1.6       noro      567: #   if defined(MSWIN32) || defined(MSWINCE)
                    568:       InitializeCriticalSection(&GC_write_cs);
                    569: #   endif
1.4       noro      570:     if (0 != GETENV("GC_PRINT_STATS")) {
                    571:       GC_print_stats = 1;
                    572:     }
1.7     ! noro      573: #   ifndef NO_DEBUGGING
        !           574:       if (0 != GETENV("GC_DUMP_REGULARLY")) {
        !           575:         GC_dump_regularly = 1;
        !           576:       }
        !           577: #   endif
1.4       noro      578:     if (0 != GETENV("GC_FIND_LEAK")) {
                    579:       GC_find_leak = 1;
1.7     ! noro      580: #     ifdef __STDC__
        !           581:         atexit(GC_exit_check);
        !           582: #     endif
1.4       noro      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:     }
1.6       noro      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:     }
1.7     ! noro      620:     maybe_install_looping_handler();
1.4       noro      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:     }
1.1       noro      625:     GC_setpagesize();
1.4       noro      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);
1.1       noro      631: #   endif
                    632: #   ifdef MSWIN32
                    633:        GC_init_win32();
                    634: #   endif
1.3       noro      635: #   if defined(SEARCH_FOR_DATA_START)
1.1       noro      636:        GC_init_linux_data_start();
                    637: #   endif
1.6       noro      638: #   if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
1.4       noro      639:        GC_init_netbsd_elf();
                    640: #   endif
1.6       noro      641: #   if defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS)
1.4       noro      642:         GC_thr_init();
                    643: #   endif
1.6       noro      644: #   ifdef GC_SOLARIS_THREADS
1.1       noro      645:        /* We need dirty bits in order to find live stack sections.     */
                    646:         GC_dirty_init();
                    647: #   endif
1.6       noro      648: #   if !defined(THREADS) || defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) \
                    649:        || defined(GC_SOLARIS_THREADS)
1.1       noro      650:       if (GC_stackbottom == 0) {
                    651:        GC_stackbottom = GC_get_stack_base();
1.4       noro      652: #       if defined(LINUX) && defined(IA64)
                    653:          GC_register_stackbottom = GC_get_register_stack_base();
                    654: #       endif
1.7     ! noro      655:       } else {
        !           656: #       if defined(LINUX) && defined(IA64)
        !           657:          if (GC_register_stackbottom == 0) {
        !           658:            WARN("GC_register_stackbottom should be set with GC_stackbottom", 0);
        !           659:            /* The following is likely to fail, since we rely on        */
        !           660:            /* alignment properties that may not hold with a user set   */
        !           661:            /* GC_stackbottom.                                          */
        !           662:            GC_register_stackbottom = GC_get_register_stack_base();
        !           663:          }
        !           664: #      endif
1.1       noro      665:       }
                    666: #   endif
1.7     ! noro      667:     GC_STATIC_ASSERT(sizeof (ptr_t) == sizeof(word));
        !           668:     GC_STATIC_ASSERT(sizeof (signed_word) == sizeof(word));
        !           669:     GC_STATIC_ASSERT(sizeof (struct hblk) == HBLKSIZE);
1.1       noro      670: #   ifndef THREADS
                    671: #     if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)
                    672:        ABORT(
                    673:          "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
                    674: #     endif
                    675: #     if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN)
                    676:        ABORT(
                    677:          "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
                    678: #     endif
                    679: #     ifdef STACK_GROWS_DOWN
1.4       noro      680:         GC_ASSERT((word)(&dummy) <= (word)GC_stackbottom);
1.1       noro      681: #     else
1.4       noro      682:         GC_ASSERT((word)(&dummy) >= (word)GC_stackbottom);
1.1       noro      683: #     endif
                    684: #   endif
                    685: #   if !defined(_AUX_SOURCE) || defined(__GNUC__)
1.4       noro      686:       GC_ASSERT((word)(-1) > (word)0);
                    687:       /* word should be unsigned */
1.1       noro      688: #   endif
1.4       noro      689:     GC_ASSERT((signed_word)(-1) < (signed_word)0);
1.1       noro      690:
                    691:     /* Add initial guess of root sets.  Do this first, since sbrk(0)   */
                    692:     /* might be used.                                                  */
1.7     ! noro      693:       if (GC_REGISTER_MAIN_STATIC_DATA()) GC_register_data_segments();
1.1       noro      694:     GC_init_headers();
                    695:     GC_bl_init();
                    696:     GC_mark_init();
1.4       noro      697:     {
                    698:        char * sz_str = GETENV("GC_INITIAL_HEAP_SIZE");
                    699:        if (sz_str != NULL) {
                    700:          initial_heap_sz = atoi(sz_str);
                    701:          if (initial_heap_sz <= MINHINCR * HBLKSIZE) {
                    702:            WARN("Bad initial heap size %s - ignoring it.\n",
                    703:                 sz_str);
                    704:          }
                    705:          initial_heap_sz = divHBLKSZ(initial_heap_sz);
                    706:        }
                    707:     }
1.7     ! noro      708:     {
        !           709:        char * sz_str = GETENV("GC_MAXIMUM_HEAP_SIZE");
        !           710:        if (sz_str != NULL) {
        !           711:          word max_heap_sz = (word)atol(sz_str);
        !           712:          if (max_heap_sz < initial_heap_sz * HBLKSIZE) {
        !           713:            WARN("Bad maximum heap size %s - ignoring it.\n",
        !           714:                 sz_str);
        !           715:          }
        !           716:          if (0 == GC_max_retries) GC_max_retries = 2;
        !           717:          GC_set_max_heap_size(max_heap_sz);
        !           718:        }
        !           719:     }
1.4       noro      720:     if (!GC_expand_hp_inner(initial_heap_sz)) {
1.1       noro      721:         GC_err_printf0("Can't start up: not enough memory\n");
                    722:         EXIT();
                    723:     }
                    724:     /* Preallocate large object map.  It's otherwise inconvenient to   */
                    725:     /* deal with failure.                                              */
                    726:       if (!GC_add_map_entry((word)0)) {
                    727:         GC_err_printf0("Can't start up: not enough memory\n");
                    728:         EXIT();
                    729:       }
                    730:     GC_register_displacement_inner(0L);
                    731: #   ifdef MERGE_SIZES
                    732:       GC_init_size_map();
                    733: #   endif
                    734: #   ifdef PCR
                    735:       if (PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever)
                    736:           != PCR_ERes_okay) {
                    737:           ABORT("Can't lock load state\n");
                    738:       } else if (PCR_IL_Unlock() != PCR_ERes_okay) {
                    739:           ABORT("Can't unlock load state\n");
                    740:       }
                    741:       PCR_IL_Unlock();
                    742:       GC_pcr_install();
                    743: #   endif
1.6       noro      744: #   if !defined(SMALL_CONFIG)
                    745:       if (!GC_no_win32_dlls && 0 != GETENV("GC_ENABLE_INCREMENTAL")) {
                    746:        GC_ASSERT(!GC_incremental);
                    747:         GC_setpagesize();
                    748: #       ifndef GC_SOLARIS_THREADS
                    749:           GC_dirty_init();
                    750: #       endif
                    751:         GC_ASSERT(GC_words_allocd == 0)
                    752:        GC_incremental = TRUE;
                    753:       }
                    754: #   endif /* !SMALL_CONFIG */
1.7     ! noro      755:     COND_DUMP;
1.6       noro      756:     /* Get black list set up and/or incrmental GC started */
                    757:       if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner();
1.4       noro      758:     GC_is_initialized = TRUE;
1.1       noro      759: #   ifdef STUBBORN_ALLOC
                    760:        GC_stubborn_init();
                    761: #   endif
                    762:     /* Convince lint that some things are used */
                    763: #   ifdef LINT
                    764:       {
                    765:           extern char * GC_copyright[];
                    766:           extern int GC_read();
                    767:           extern void GC_register_finalizer_no_order();
                    768:
                    769:           GC_noop(GC_copyright, GC_find_header,
                    770:                   GC_push_one, GC_call_with_alloc_lock, GC_read,
                    771:                   GC_dont_expand,
                    772: #                ifndef NO_DEBUGGING
                    773:                    GC_dump,
                    774: #                endif
                    775:                   GC_register_finalizer_no_order);
                    776:       }
                    777: #   endif
                    778: }
                    779:
                    780: void GC_enable_incremental GC_PROTO(())
                    781: {
1.2       noro      782: # if !defined(SMALL_CONFIG)
                    783:   if (!GC_find_leak) {
1.1       noro      784:     DCL_LOCK_STATE;
                    785:
                    786:     DISABLE_SIGNALS();
                    787:     LOCK();
                    788:     if (GC_incremental) goto out;
                    789:     GC_setpagesize();
1.6       noro      790:     if (GC_no_win32_dlls) goto out;
1.7     ! noro      791: #   ifndef GC_SOLARIS_THREADS
        !           792:       maybe_install_looping_handler();  /* Before write fault handler! */
        !           793:       GC_dirty_init();
1.1       noro      794: #   endif
                    795:     if (!GC_is_initialized) {
                    796:         GC_init_inner();
                    797:     }
1.6       noro      798:     if (GC_incremental) goto out;
1.1       noro      799:     if (GC_dont_gc) {
                    800:         /* Can't easily do it. */
                    801:         UNLOCK();
                    802:        ENABLE_SIGNALS();
                    803:        return;
                    804:     }
                    805:     if (GC_words_allocd > 0) {
                    806:        /* There may be unmarked reachable objects      */
                    807:        GC_gcollect_inner();
                    808:     }   /* else we're OK in assuming everything's      */
                    809:        /* clean since nothing can point to an          */
                    810:        /* unmarked object.                             */
                    811:     GC_read_dirty();
                    812:     GC_incremental = TRUE;
                    813: out:
                    814:     UNLOCK();
                    815:     ENABLE_SIGNALS();
1.2       noro      816:   }
1.1       noro      817: # endif
                    818: }
                    819:
                    820:
1.4       noro      821: #if defined(MSWIN32) || defined(MSWINCE)
                    822: # define LOG_FILE _T("gc.log")
                    823:
                    824:   HANDLE GC_stdout = 0;
1.1       noro      825:
1.4       noro      826:   void GC_deinit()
                    827:   {
                    828:       if (GC_is_initialized) {
                    829:        DeleteCriticalSection(&GC_write_cs);
                    830:       }
                    831:   }
1.1       noro      832:
1.4       noro      833:   int GC_write(buf, len)
1.6       noro      834:   GC_CONST char * buf;
1.4       noro      835:   size_t len;
1.1       noro      836:   {
1.4       noro      837:       BOOL tmp;
                    838:       DWORD written;
                    839:       if (len == 0)
                    840:          return 0;
                    841:       EnterCriticalSection(&GC_write_cs);
                    842:       if (GC_stdout == INVALID_HANDLE_VALUE) {
                    843:          return -1;
                    844:       } else if (GC_stdout == 0) {
                    845:          GC_stdout = CreateFile(LOG_FILE, GENERIC_WRITE,
                    846:                                 FILE_SHARE_READ | FILE_SHARE_WRITE,
                    847:                                 NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,
                    848:                                 NULL);
                    849:          if (GC_stdout == INVALID_HANDLE_VALUE) ABORT("Open of log file failed");
                    850:       }
                    851:       tmp = WriteFile(GC_stdout, buf, len, &written, NULL);
                    852:       if (!tmp)
                    853:          DebugBreak();
                    854:       LeaveCriticalSection(&GC_write_cs);
                    855:       return tmp ? (int)written : -1;
1.1       noro      856:   }
                    857:
                    858: #endif
                    859:
                    860: #if defined(OS2) || defined(MACOS)
                    861: FILE * GC_stdout = NULL;
                    862: FILE * GC_stderr = NULL;
                    863: int GC_tmp;  /* Should really be local ... */
                    864:
                    865:   void GC_set_files()
                    866:   {
                    867:       if (GC_stdout == NULL) {
                    868:        GC_stdout = stdout;
                    869:     }
                    870:     if (GC_stderr == NULL) {
                    871:        GC_stderr = stderr;
                    872:     }
                    873:   }
                    874: #endif
                    875:
1.4       noro      876: #if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE)
1.1       noro      877:   int GC_stdout = 1;
                    878:   int GC_stderr = 2;
                    879: # if !defined(AMIGA)
                    880: #   include <unistd.h>
                    881: # endif
                    882: #endif
                    883:
1.6       noro      884: #if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) \
                    885:     && !defined(MACOS)  && !defined(ECOS) && !defined(NOSYS)
1.1       noro      886: int GC_write(fd, buf, len)
                    887: int fd;
1.6       noro      888: GC_CONST char *buf;
1.1       noro      889: size_t len;
                    890: {
                    891:      register int bytes_written = 0;
                    892:      register int result;
                    893:
                    894:      while (bytes_written < len) {
1.6       noro      895: #      ifdef GC_SOLARIS_THREADS
1.1       noro      896:            result = syscall(SYS_write, fd, buf + bytes_written,
                    897:                                            len - bytes_written);
                    898: #      else
                    899:            result = write(fd, buf + bytes_written, len - bytes_written);
                    900: #      endif
                    901:        if (-1 == result) return(result);
                    902:        bytes_written += result;
                    903:     }
                    904:     return(bytes_written);
                    905: }
                    906: #endif /* UN*X */
                    907:
1.6       noro      908: #ifdef ECOS
                    909: int GC_write(fd, buf, len)
                    910: {
                    911:   _Jv_diag_write (buf, len);
                    912:   return len;
                    913: }
                    914: #endif
                    915:
                    916: #ifdef NOSYS
                    917: int GC_write(fd, buf, len)
                    918: {
                    919:   /* No writing.  */
                    920:   return len;
                    921: }
                    922: #endif
                    923:
                    924:
1.4       noro      925: #if defined(MSWIN32) || defined(MSWINCE)
                    926: #   define WRITE(f, buf, len) GC_write(buf, len)
1.1       noro      927: #else
                    928: #   if defined(OS2) || defined(MACOS)
                    929: #   define WRITE(f, buf, len) (GC_set_files(), \
                    930:                               GC_tmp = fwrite((buf), 1, (len), (f)), \
                    931:                               fflush(f), GC_tmp)
                    932: #   else
                    933: #     define WRITE(f, buf, len) GC_write((f), (buf), (len))
                    934: #   endif
                    935: #endif
                    936:
                    937: /* A version of printf that is unlikely to call malloc, and is thus safer */
                    938: /* to call from the collector in case malloc has been bound to GC_malloc. */
                    939: /* Assumes that no more than 1023 characters are written at once.        */
                    940: /* Assumes that all arguments have been converted to something of the    */
                    941: /* same size as long, and that the format conversions expect something   */
                    942: /* of that size.                                                         */
                    943: void GC_printf(format, a, b, c, d, e, f)
1.4       noro      944: GC_CONST char * format;
1.1       noro      945: long a, b, c, d, e, f;
                    946: {
                    947:     char buf[1025];
                    948:
                    949:     if (GC_quiet) return;
                    950:     buf[1024] = 0x15;
                    951:     (void) sprintf(buf, format, a, b, c, d, e, f);
                    952:     if (buf[1024] != 0x15) ABORT("GC_printf clobbered stack");
                    953:     if (WRITE(GC_stdout, buf, strlen(buf)) < 0) ABORT("write to stdout failed");
                    954: }
                    955:
                    956: void GC_err_printf(format, a, b, c, d, e, f)
1.4       noro      957: GC_CONST char * format;
1.1       noro      958: long a, b, c, d, e, f;
                    959: {
                    960:     char buf[1025];
                    961:
                    962:     buf[1024] = 0x15;
                    963:     (void) sprintf(buf, format, a, b, c, d, e, f);
                    964:     if (buf[1024] != 0x15) ABORT("GC_err_printf clobbered stack");
                    965:     if (WRITE(GC_stderr, buf, strlen(buf)) < 0) ABORT("write to stderr failed");
                    966: }
                    967:
                    968: void GC_err_puts(s)
1.4       noro      969: GC_CONST char *s;
1.1       noro      970: {
                    971:     if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed");
                    972: }
                    973:
1.4       noro      974: #if defined(LINUX) && !defined(SMALL_CONFIG)
                    975: void GC_err_write(buf, len)
                    976: GC_CONST char *buf;
                    977: size_t len;
                    978: {
                    979:     if (WRITE(GC_stderr, buf, len) < 0) ABORT("write to stderr failed");
                    980: }
                    981: #endif
                    982:
1.1       noro      983: # if defined(__STDC__) || defined(__cplusplus)
                    984:     void GC_default_warn_proc(char *msg, GC_word arg)
                    985: # else
                    986:     void GC_default_warn_proc(msg, arg)
                    987:     char *msg;
                    988:     GC_word arg;
                    989: # endif
                    990: {
                    991:     GC_err_printf1(msg, (unsigned long)arg);
                    992: }
                    993:
                    994: GC_warn_proc GC_current_warn_proc = GC_default_warn_proc;
                    995:
                    996: # if defined(__STDC__) || defined(__cplusplus)
                    997:     GC_warn_proc GC_set_warn_proc(GC_warn_proc p)
                    998: # else
                    999:     GC_warn_proc GC_set_warn_proc(p)
                   1000:     GC_warn_proc p;
                   1001: # endif
                   1002: {
                   1003:     GC_warn_proc result;
                   1004:
                   1005:     LOCK();
                   1006:     result = GC_current_warn_proc;
                   1007:     GC_current_warn_proc = p;
                   1008:     UNLOCK();
                   1009:     return(result);
                   1010: }
                   1011:
1.7     ! noro     1012: # if defined(__STDC__) || defined(__cplusplus)
        !          1013:     GC_word GC_set_free_space_divisor (GC_word value)
        !          1014: # else
        !          1015:     GC_word GC_set_free_space_divisor (value)
        !          1016:     GC_word value;
        !          1017: # endif
        !          1018: {
        !          1019:     GC_word old = GC_free_space_divisor;
        !          1020:     GC_free_space_divisor = value;
        !          1021:     return old;
        !          1022: }
1.1       noro     1023:
                   1024: #ifndef PCR
                   1025: void GC_abort(msg)
1.4       noro     1026: GC_CONST char * msg;
1.1       noro     1027: {
1.4       noro     1028: #   if defined(MSWIN32)
                   1029:       (void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK);
                   1030:       DebugBreak();
                   1031: #   else
                   1032:       GC_err_printf1("%s\n", msg);
                   1033: #   endif
                   1034:     if (GETENV("GC_LOOP_ON_ABORT") != NULL) {
                   1035:            /* In many cases it's easier to debug a running process.    */
                   1036:            /* It's arguably nicer to sleep, but that makes it harder   */
                   1037:            /* to look at the thread if the debugger doesn't know much  */
                   1038:            /* about threads.                                           */
1.6       noro     1039:            for(;;) {}
1.4       noro     1040:     }
                   1041: #   ifdef MSWIN32
                   1042:        DebugBreak();
                   1043: #   else
                   1044:         (void) abort();
                   1045: #   endif
1.1       noro     1046: }
                   1047: #endif
                   1048:
                   1049: void GC_enable()
                   1050: {
1.7     ! noro     1051:     LOCK();
1.1       noro     1052:     GC_dont_gc--;
1.7     ! noro     1053:     UNLOCK();
1.1       noro     1054: }
                   1055:
                   1056: void GC_disable()
                   1057: {
1.7     ! noro     1058:     LOCK();
1.1       noro     1059:     GC_dont_gc++;
1.7     ! noro     1060:     UNLOCK();
1.1       noro     1061: }
                   1062:
                   1063: #if !defined(NO_DEBUGGING)
                   1064:
                   1065: void GC_dump()
                   1066: {
                   1067:     GC_printf0("***Static roots:\n");
                   1068:     GC_print_static_roots();
                   1069:     GC_printf0("\n***Heap sections:\n");
                   1070:     GC_print_heap_sects();
                   1071:     GC_printf0("\n***Free blocks:\n");
                   1072:     GC_print_hblkfreelist();
                   1073:     GC_printf0("\n***Blocks in use:\n");
                   1074:     GC_print_block_list();
1.7     ! noro     1075:     GC_printf0("\n***Finalization statistics:\n");
        !          1076:     GC_print_finalization_stats();
1.1       noro     1077: }
                   1078:
1.4       noro     1079: #endif /* NO_DEBUGGING */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>