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

Annotation of OpenXM_contrib/gc/misc.c, Revision 1.1.1.2

1.1       maekawa     1: /*
                      2:  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
                      3:  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
                      4:  *
                      5:  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
                      6:  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
                      7:  *
                      8:  * Permission is hereby granted to use or copy this program
                      9:  * for any purpose,  provided the above notices are retained on all copies.
                     10:  * Permission to modify the code and to distribute modified code is granted,
                     11:  * provided the above notices are retained, and a notice that the code was
                     12:  * modified is included with the above copyright notice.
                     13:  */
                     14: /* Boehm, July 31, 1995 5:02 pm PDT */
                     15:
                     16:
                     17: #include <stdio.h>
                     18: #include <signal.h>
                     19:
                     20: #define I_HIDE_POINTERS        /* To make GC_call_with_alloc_lock visible */
                     21: #include "gc_priv.h"
                     22:
                     23: #ifdef SOLARIS_THREADS
                     24: # include <sys/syscall.h>
                     25: #endif
                     26: #ifdef MSWIN32
                     27: # include <windows.h>
                     28: #endif
                     29:
                     30: # ifdef THREADS
                     31: #   ifdef PCR
                     32: #     include "il/PCR_IL.h"
                     33:       PCR_Th_ML GC_allocate_ml;
                     34: #   else
                     35: #     ifdef SRC_M3
                     36:        /* Critical section counter is defined in the M3 runtime        */
                     37:        /* That's all we use.                                           */
                     38: #     else
                     39: #      ifdef SOLARIS_THREADS
                     40:          mutex_t GC_allocate_ml;       /* Implicitly initialized.      */
                     41: #      else
                     42: #          ifdef WIN32_THREADS
                     43:              GC_API CRITICAL_SECTION GC_allocate_ml;
                     44: #          else
                     45: #             if defined(IRIX_THREADS) || defined(LINUX_THREADS) \
                     46:                 || defined(IRIX_JDK_THREADS)
                     47:                pthread_t GC_lock_holder = NO_THREAD;
                     48: #            else
1.1.1.2 ! maekawa    49: #              if defined(HPUX_THREADS)
        !            50:                  pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
        !            51: #              else
        !            52:                  --> declare allocator lock here
        !            53: #              endif
1.1       maekawa    54: #            endif
                     55: #         endif
                     56: #      endif
                     57: #     endif
                     58: #   endif
                     59: # endif
                     60:
                     61: GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */;
                     62:
                     63:
                     64: GC_bool GC_debugging_started = FALSE;
                     65:        /* defined here so we don't have to load debug_malloc.o */
                     66:
                     67: void (*GC_check_heap)() = (void (*)())0;
                     68:
                     69: void (*GC_start_call_back)() = (void (*)())0;
                     70:
                     71: ptr_t GC_stackbottom = 0;
                     72:
                     73: GC_bool GC_dont_gc = 0;
                     74:
                     75: GC_bool GC_quiet = 0;
                     76:
1.1.1.2 ! maekawa    77: #ifdef FIND_LEAK
        !            78:   int GC_find_leak = 1;
        !            79: #else
        !            80:   int GC_find_leak = 0;
        !            81: #endif
        !            82:
1.1       maekawa    83: /*ARGSUSED*/
                     84: GC_PTR GC_default_oom_fn GC_PROTO((size_t bytes_requested))
                     85: {
                     86:     return(0);
                     87: }
                     88:
                     89: GC_PTR (*GC_oom_fn) GC_PROTO((size_t bytes_requested)) = GC_default_oom_fn;
                     90:
                     91: extern signed_word GC_mem_found;
                     92:
                     93: # ifdef MERGE_SIZES
                     94:     /* Set things up so that GC_size_map[i] >= words(i),               */
                     95:     /* but not too much bigger                                         */
                     96:     /* and so that size_map contains relatively few distinct entries   */
                     97:     /* This is stolen from Russ Atkinson's Cedar quantization          */
                     98:     /* alogrithm (but we precompute it).                               */
                     99:
                    100:
                    101:     void GC_init_size_map()
                    102:     {
                    103:        register unsigned i;
                    104:
                    105:        /* Map size 0 to 1.  This avoids problems at lower levels. */
                    106:          GC_size_map[0] = 1;
                    107:        /* One word objects don't have to be 2 word aligned.       */
                    108:          for (i = 1; i < sizeof(word); i++) {
                    109:              GC_size_map[i] = 1;
                    110:          }
                    111:          GC_size_map[sizeof(word)] = ROUNDED_UP_WORDS(sizeof(word));
                    112:        for (i = sizeof(word) + 1; i <= 8 * sizeof(word); i++) {
                    113: #           ifdef ALIGN_DOUBLE
                    114:              GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1);
                    115: #           else
                    116:              GC_size_map[i] = ROUNDED_UP_WORDS(i);
                    117: #           endif
                    118:        }
                    119:        for (i = 8*sizeof(word) + 1; i <= 16 * sizeof(word); i++) {
                    120:              GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1);
                    121:        }
                    122:        /* We leave the rest of the array to be filled in on demand. */
                    123:     }
                    124:
                    125:     /* Fill in additional entries in GC_size_map, including the ith one */
                    126:     /* We assume the ith entry is currently 0.                         */
                    127:     /* Note that a filled in section of the array ending at n always    */
                    128:     /* has length at least n/4.                                                */
                    129:     void GC_extend_size_map(i)
                    130:     word i;
                    131:     {
                    132:         word orig_word_sz = ROUNDED_UP_WORDS(i);
                    133:         word word_sz = orig_word_sz;
                    134:        register word byte_sz = WORDS_TO_BYTES(word_sz);
                    135:                                /* The size we try to preserve.         */
                    136:                                /* Close to to i, unless this would     */
                    137:                                /* introduce too many distinct sizes.   */
                    138:        word smaller_than_i = byte_sz - (byte_sz >> 3);
                    139:        word much_smaller_than_i = byte_sz - (byte_sz >> 2);
                    140:        register word low_limit;        /* The lowest indexed entry we  */
                    141:                                        /* initialize.                  */
                    142:        register word j;
                    143:
                    144:        if (GC_size_map[smaller_than_i] == 0) {
                    145:            low_limit = much_smaller_than_i;
                    146:            while (GC_size_map[low_limit] != 0) low_limit++;
                    147:        } else {
                    148:            low_limit = smaller_than_i + 1;
                    149:            while (GC_size_map[low_limit] != 0) low_limit++;
                    150:            word_sz = ROUNDED_UP_WORDS(low_limit);
                    151:            word_sz += word_sz >> 3;
                    152:            if (word_sz < orig_word_sz) word_sz = orig_word_sz;
                    153:        }
                    154: #      ifdef ALIGN_DOUBLE
                    155:            word_sz += 1;
                    156:            word_sz &= ~1;
                    157: #      endif
                    158:        if (word_sz > MAXOBJSZ) {
                    159:            word_sz = MAXOBJSZ;
                    160:        }
                    161:        /* If we can fit the same number of larger objects in a block,  */
                    162:        /* do so.                                                       */
                    163:        {
                    164:            size_t number_of_objs = BODY_SZ/word_sz;
                    165:            word_sz = BODY_SZ/number_of_objs;
                    166: #          ifdef ALIGN_DOUBLE
                    167:                word_sz &= ~1;
                    168: #          endif
                    169:        }
                    170:        byte_sz = WORDS_TO_BYTES(word_sz);
                    171: #      ifdef ADD_BYTE_AT_END
                    172:            /* We need one extra byte; don't fill in GC_size_map[byte_sz] */
                    173:            byte_sz--;
                    174: #      endif
                    175:
                    176:        for (j = low_limit; j <= byte_sz; j++) GC_size_map[j] = word_sz;
                    177:     }
                    178: # endif
                    179:
                    180:
                    181: /*
                    182:  * The following is a gross hack to deal with a problem that can occur
                    183:  * on machines that are sloppy about stack frame sizes, notably SPARC.
                    184:  * Bogus pointers may be written to the stack and not cleared for
                    185:  * a LONG time, because they always fall into holes in stack frames
                    186:  * that are not written.  We partially address this by clearing
                    187:  * sections of the stack whenever we get control.
                    188:  */
                    189: word GC_stack_last_cleared = 0;        /* GC_no when we last did this */
                    190: # ifdef THREADS
                    191: #   define CLEAR_SIZE 2048
                    192: # else
                    193: #   define CLEAR_SIZE 213
                    194: # endif
                    195: # define DEGRADE_RATE 50
                    196:
                    197: word GC_min_sp;                /* Coolest stack pointer value from which we've */
                    198:                        /* already cleared the stack.                   */
                    199:
                    200: # ifdef STACK_GROWS_DOWN
                    201: #   define COOLER_THAN >
                    202: #   define HOTTER_THAN <
                    203: #   define MAKE_COOLER(x,y) if ((word)(x)+(y) > (word)(x)) {(x) += (y);} \
                    204:                            else {(x) = (word)ONES;}
                    205: #   define MAKE_HOTTER(x,y) (x) -= (y)
                    206: # else
                    207: #   define COOLER_THAN <
                    208: #   define HOTTER_THAN >
                    209: #   define MAKE_COOLER(x,y) if ((word)(x)-(y) < (word)(x)) {(x) -= (y);} else {(x) = 0;}
                    210: #   define MAKE_HOTTER(x,y) (x) += (y)
                    211: # endif
                    212:
                    213: word GC_high_water;
                    214:                        /* "hottest" stack pointer value we have seen   */
                    215:                        /* recently.  Degrades over time.               */
                    216:
                    217: word GC_words_allocd_at_reset;
                    218:
                    219: #if defined(ASM_CLEAR_CODE) && !defined(THREADS)
                    220:   extern ptr_t GC_clear_stack_inner();
                    221: #endif
                    222:
                    223: #if !defined(ASM_CLEAR_CODE) && !defined(THREADS)
                    224: /* Clear the stack up to about limit.  Return arg. */
                    225: /*ARGSUSED*/
                    226: ptr_t GC_clear_stack_inner(arg, limit)
                    227: ptr_t arg;
                    228: word limit;
                    229: {
                    230:     word dummy[CLEAR_SIZE];
                    231:
                    232:     BZERO(dummy, CLEAR_SIZE*sizeof(word));
                    233:     if ((word)(dummy) COOLER_THAN limit) {
                    234:         (void) GC_clear_stack_inner(arg, limit);
                    235:     }
                    236:     /* Make sure the recursive call is not a tail call, and the bzero  */
                    237:     /* call is not recognized as dead code.                            */
                    238:     GC_noop1((word)dummy);
                    239:     return(arg);
                    240: }
                    241: #endif
                    242:
                    243: /* Clear some of the inaccessible part of the stack.  Returns its      */
                    244: /* argument, so it can be used in a tail call position, hence clearing  */
                    245: /* another frame.                                                      */
                    246: ptr_t GC_clear_stack(arg)
                    247: ptr_t arg;
                    248: {
                    249:     register word sp = (word)GC_approx_sp();  /* Hotter than actual sp */
                    250: #   ifdef THREADS
                    251:         word dummy[CLEAR_SIZE];
                    252: #   else
                    253:        register word limit;
                    254: #   endif
                    255:
                    256: #   define SLOP 400
                    257:        /* Extra bytes we clear every time.  This clears our own        */
                    258:        /* activation record, and should cause more frequent            */
                    259:        /* clearing near the cold end of the stack, a good thing.       */
                    260: #   define GC_SLOP 4000
                    261:        /* We make GC_high_water this much hotter than we really saw    */
                    262:        /* saw it, to cover for GC noise etc. above our current frame.  */
                    263: #   define CLEAR_THRESHOLD 100000
                    264:        /* We restart the clearing process after this many bytes of     */
                    265:        /* allocation.  Otherwise very heavily recursive programs       */
                    266:        /* with sparse stacks may result in heaps that grow almost      */
                    267:        /* without bounds.  As the heap gets larger, collection         */
                    268:        /* frequency decreases, thus clearing frequency would decrease, */
                    269:        /* thus more junk remains accessible, thus the heap gets        */
                    270:        /* larger ...                                                   */
                    271: # ifdef THREADS
                    272:     BZERO(dummy, CLEAR_SIZE*sizeof(word));
                    273: # else
                    274:     if (GC_gc_no > GC_stack_last_cleared) {
                    275:         /* Start things over, so we clear the entire stack again */
                    276:         if (GC_stack_last_cleared == 0) GC_high_water = (word) GC_stackbottom;
                    277:         GC_min_sp = GC_high_water;
                    278:         GC_stack_last_cleared = GC_gc_no;
                    279:         GC_words_allocd_at_reset = GC_words_allocd;
                    280:     }
                    281:     /* Adjust GC_high_water */
                    282:         MAKE_COOLER(GC_high_water, WORDS_TO_BYTES(DEGRADE_RATE) + GC_SLOP);
                    283:         if (sp HOTTER_THAN GC_high_water) {
                    284:             GC_high_water = sp;
                    285:         }
                    286:         MAKE_HOTTER(GC_high_water, GC_SLOP);
                    287:     limit = GC_min_sp;
                    288:     MAKE_HOTTER(limit, SLOP);
                    289:     if (sp COOLER_THAN limit) {
                    290:         limit &= ~0xf; /* Make it sufficiently aligned for assembly    */
                    291:                        /* implementations of GC_clear_stack_inner.     */
                    292:         GC_min_sp = sp;
                    293:         return(GC_clear_stack_inner(arg, limit));
                    294:     } else if (WORDS_TO_BYTES(GC_words_allocd - GC_words_allocd_at_reset)
                    295:               > CLEAR_THRESHOLD) {
                    296:        /* Restart clearing process, but limit how much clearing we do. */
                    297:        GC_min_sp = sp;
                    298:        MAKE_HOTTER(GC_min_sp, CLEAR_THRESHOLD/4);
                    299:        if (GC_min_sp HOTTER_THAN GC_high_water) GC_min_sp = GC_high_water;
                    300:        GC_words_allocd_at_reset = GC_words_allocd;
                    301:     }
                    302: # endif
                    303:   return(arg);
                    304: }
                    305:
                    306:
                    307: /* Return a pointer to the base address of p, given a pointer to a     */
                    308: /* an address within an object.  Return 0 o.w.                         */
                    309: # ifdef __STDC__
                    310:     GC_PTR GC_base(GC_PTR p)
                    311: # else
                    312:     GC_PTR GC_base(p)
                    313:     GC_PTR p;
                    314: # endif
                    315: {
                    316:     register word r;
                    317:     register struct hblk *h;
                    318:     register bottom_index *bi;
                    319:     register hdr *candidate_hdr;
                    320:     register word limit;
                    321:
                    322:     r = (word)p;
                    323:     if (!GC_is_initialized) return 0;
                    324:     h = HBLKPTR(r);
                    325:     GET_BI(r, bi);
                    326:     candidate_hdr = HDR_FROM_BI(bi, r);
                    327:     if (candidate_hdr == 0) return(0);
                    328:     /* If it's a pointer to the middle of a large object, move it      */
                    329:     /* to the beginning.                                               */
                    330:        while (IS_FORWARDING_ADDR_OR_NIL(candidate_hdr)) {
                    331:           h = FORWARDED_ADDR(h,candidate_hdr);
                    332:           r = (word)h + HDR_BYTES;
                    333:           candidate_hdr = HDR(h);
                    334:        }
                    335:     if (candidate_hdr -> hb_map == GC_invalid_map) return(0);
                    336:     /* Make sure r points to the beginning of the object */
                    337:        r &= ~(WORDS_TO_BYTES(1) - 1);
                    338:         {
                    339:            register int offset = (char *)r - (char *)(HBLKPTR(r));
                    340:            register signed_word sz = candidate_hdr -> hb_sz;
                    341:
                    342: #          ifdef ALL_INTERIOR_POINTERS
                    343:              register map_entry_type map_entry;
                    344:
                    345:              map_entry = MAP_ENTRY((candidate_hdr -> hb_map), offset);
                    346:              if (map_entry == OBJ_INVALID) {
                    347:                return(0);
                    348:               }
                    349:               r -= WORDS_TO_BYTES(map_entry);
                    350:               limit = r + WORDS_TO_BYTES(sz);
                    351: #          else
                    352:              register int correction;
                    353:
                    354:              offset = BYTES_TO_WORDS(offset - HDR_BYTES);
                    355:              correction = offset % sz;
                    356:              r -= (WORDS_TO_BYTES(correction));
                    357:              limit = r + WORDS_TO_BYTES(sz);
                    358:              if (limit > (word)(h + 1)
                    359:                && sz <= BYTES_TO_WORDS(HBLKSIZE) - HDR_WORDS) {
                    360:                return(0);
                    361:              }
                    362: #          endif
                    363:            if ((word)p >= limit) return(0);
                    364:        }
                    365:     return((GC_PTR)r);
                    366: }
                    367:
                    368:
                    369: /* Return the size of an object, given a pointer to its base.          */
                    370: /* (For small obects this also happens to work from interior pointers, */
                    371: /* but that shouldn't be relied upon.)                                 */
                    372: # ifdef __STDC__
                    373:     size_t GC_size(GC_PTR p)
                    374: # else
                    375:     size_t GC_size(p)
                    376:     GC_PTR p;
                    377: # endif
                    378: {
                    379:     register int sz;
                    380:     register hdr * hhdr = HDR(p);
                    381:
                    382:     sz = WORDS_TO_BYTES(hhdr -> hb_sz);
                    383:     if (sz < 0) {
                    384:         return(-sz);
                    385:     } else {
                    386:         return(sz);
                    387:     }
                    388: }
                    389:
                    390: size_t GC_get_heap_size GC_PROTO(())
                    391: {
                    392:     return ((size_t) GC_heapsize);
                    393: }
                    394:
1.1.1.2 ! maekawa   395: size_t GC_get_free_bytes GC_PROTO(())
        !           396: {
        !           397:     return ((size_t) GC_large_free_bytes);
        !           398: }
        !           399:
1.1       maekawa   400: size_t GC_get_bytes_since_gc GC_PROTO(())
                    401: {
                    402:     return ((size_t) WORDS_TO_BYTES(GC_words_allocd));
                    403: }
                    404:
                    405: GC_bool GC_is_initialized = FALSE;
                    406:
                    407: void GC_init()
                    408: {
                    409:     DCL_LOCK_STATE;
                    410:
                    411:     DISABLE_SIGNALS();
                    412:     LOCK();
                    413:     GC_init_inner();
                    414:     UNLOCK();
                    415:     ENABLE_SIGNALS();
                    416:
                    417: }
                    418:
                    419: #ifdef MSWIN32
                    420:     extern void GC_init_win32();
                    421: #endif
                    422:
                    423: extern void GC_setpagesize();
                    424:
                    425: void GC_init_inner()
                    426: {
                    427: #   ifndef THREADS
                    428:         word dummy;
                    429: #   endif
                    430:
                    431:     if (GC_is_initialized) return;
                    432:     GC_setpagesize();
                    433:     GC_exclude_static_roots(beginGC_arrays, end_gc_area);
                    434: #   ifdef PRINTSTATS
                    435:        if ((ptr_t)endGC_arrays != (ptr_t)(&GC_obj_kinds)) {
                    436:            GC_printf0("Reordering linker, didn't exclude obj_kinds\n");
                    437:        }
                    438: #   endif
                    439: #   ifdef MSWIN32
                    440:        GC_init_win32();
                    441: #   endif
1.1.1.2 ! maekawa   442: #   if defined(LINUX) && \
        !           443:        (defined(POWERPC) || defined(ALPHA) || defined(SPARC) || defined(IA64))
        !           444:        GC_init_linux_data_start();
1.1       maekawa   445: #   endif
                    446: #   ifdef SOLARIS_THREADS
                    447:        GC_thr_init();
                    448:        /* We need dirty bits in order to find live stack sections.     */
                    449:         GC_dirty_init();
                    450: #   endif
                    451: #   if defined(IRIX_THREADS) || defined(LINUX_THREADS) \
1.1.1.2 ! maekawa   452:        || defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS)
1.1       maekawa   453:         GC_thr_init();
                    454: #   endif
                    455: #   if !defined(THREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \
1.1.1.2 ! maekawa   456:        || defined(IRIX_THREADS) || defined(LINUX_THREADS) \
        !           457:        || defined(HPUX_THREADS)
1.1       maekawa   458:       if (GC_stackbottom == 0) {
                    459:        GC_stackbottom = GC_get_stack_base();
                    460:       }
                    461: #   endif
                    462:     if  (sizeof (ptr_t) != sizeof(word)) {
                    463:         ABORT("sizeof (ptr_t) != sizeof(word)\n");
                    464:     }
                    465:     if  (sizeof (signed_word) != sizeof(word)) {
                    466:         ABORT("sizeof (signed_word) != sizeof(word)\n");
                    467:     }
                    468:     if  (sizeof (struct hblk) != HBLKSIZE) {
                    469:         ABORT("sizeof (struct hblk) != HBLKSIZE\n");
                    470:     }
                    471: #   ifndef THREADS
                    472: #     if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)
                    473:        ABORT(
                    474:          "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
                    475: #     endif
                    476: #     if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN)
                    477:        ABORT(
                    478:          "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
                    479: #     endif
                    480: #     ifdef STACK_GROWS_DOWN
                    481:         if ((word)(&dummy) > (word)GC_stackbottom) {
                    482:           GC_err_printf0(
                    483:                "STACK_GROWS_DOWN is defd, but stack appears to grow up\n");
                    484: #        ifndef UTS4  /* Compiler bug workaround */
                    485:             GC_err_printf2("sp = 0x%lx, GC_stackbottom = 0x%lx\n",
                    486:                           (unsigned long) (&dummy),
                    487:                           (unsigned long) GC_stackbottom);
                    488: #        endif
                    489:           ABORT("stack direction 3\n");
                    490:         }
                    491: #     else
                    492:         if ((word)(&dummy) < (word)GC_stackbottom) {
                    493:           GC_err_printf0(
                    494:                "STACK_GROWS_UP is defd, but stack appears to grow down\n");
                    495:           GC_err_printf2("sp = 0x%lx, GC_stackbottom = 0x%lx\n",
                    496:                         (unsigned long) (&dummy),
                    497:                         (unsigned long) GC_stackbottom);
                    498:           ABORT("stack direction 4");
                    499:         }
                    500: #     endif
                    501: #   endif
                    502: #   if !defined(_AUX_SOURCE) || defined(__GNUC__)
                    503:       if ((word)(-1) < (word)0) {
                    504:        GC_err_printf0("The type word should be an unsigned integer type\n");
                    505:        GC_err_printf0("It appears to be signed\n");
                    506:        ABORT("word");
                    507:       }
                    508: #   endif
                    509:     if ((signed_word)(-1) >= (signed_word)0) {
                    510:        GC_err_printf0(
                    511:                "The type signed_word should be a signed integer type\n");
                    512:        GC_err_printf0("It appears to be unsigned\n");
                    513:        ABORT("signed_word");
                    514:     }
                    515:
                    516:     /* Add initial guess of root sets.  Do this first, since sbrk(0)   */
                    517:     /* might be used.                                                  */
                    518:       GC_register_data_segments();
                    519:     GC_init_headers();
                    520:     GC_bl_init();
                    521:     GC_mark_init();
                    522:     if (!GC_expand_hp_inner((word)MINHINCR)) {
                    523:         GC_err_printf0("Can't start up: not enough memory\n");
                    524:         EXIT();
                    525:     }
                    526:     /* Preallocate large object map.  It's otherwise inconvenient to   */
                    527:     /* deal with failure.                                              */
                    528:       if (!GC_add_map_entry((word)0)) {
                    529:         GC_err_printf0("Can't start up: not enough memory\n");
                    530:         EXIT();
                    531:       }
                    532:     GC_register_displacement_inner(0L);
                    533: #   ifdef MERGE_SIZES
                    534:       GC_init_size_map();
                    535: #   endif
                    536: #   ifdef PCR
                    537:       if (PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever)
                    538:           != PCR_ERes_okay) {
                    539:           ABORT("Can't lock load state\n");
                    540:       } else if (PCR_IL_Unlock() != PCR_ERes_okay) {
                    541:           ABORT("Can't unlock load state\n");
                    542:       }
                    543:       PCR_IL_Unlock();
                    544:       GC_pcr_install();
                    545: #   endif
                    546:     /* Get black list set up */
                    547:       GC_gcollect_inner();
                    548: #   ifdef STUBBORN_ALLOC
                    549:        GC_stubborn_init();
                    550: #   endif
                    551:     GC_is_initialized = TRUE;
                    552:     /* Convince lint that some things are used */
                    553: #   ifdef LINT
                    554:       {
                    555:           extern char * GC_copyright[];
                    556:           extern int GC_read();
                    557:           extern void GC_register_finalizer_no_order();
                    558:
                    559:           GC_noop(GC_copyright, GC_find_header,
                    560:                   GC_push_one, GC_call_with_alloc_lock, GC_read,
                    561:                   GC_dont_expand,
                    562: #                ifndef NO_DEBUGGING
                    563:                    GC_dump,
                    564: #                endif
                    565:                   GC_register_finalizer_no_order);
                    566:       }
                    567: #   endif
                    568: }
                    569:
                    570: void GC_enable_incremental GC_PROTO(())
                    571: {
1.1.1.2 ! maekawa   572: # if !defined(SMALL_CONFIG)
        !           573:   if (!GC_find_leak) {
1.1       maekawa   574:     DCL_LOCK_STATE;
                    575:
                    576:     DISABLE_SIGNALS();
                    577:     LOCK();
                    578:     if (GC_incremental) goto out;
                    579:     GC_setpagesize();
                    580: #   ifdef MSWIN32
                    581:       {
                    582:         extern GC_bool GC_is_win32s();
                    583:
                    584:        /* VirtualProtect is not functional under win32s.       */
                    585:        if (GC_is_win32s()) goto out;
                    586:       }
                    587: #   endif /* MSWIN32 */
                    588: #   ifndef SOLARIS_THREADS
                    589:         GC_dirty_init();
                    590: #   endif
                    591:     if (!GC_is_initialized) {
                    592:         GC_init_inner();
                    593:     }
                    594:     if (GC_dont_gc) {
                    595:         /* Can't easily do it. */
                    596:         UNLOCK();
                    597:        ENABLE_SIGNALS();
                    598:        return;
                    599:     }
                    600:     if (GC_words_allocd > 0) {
                    601:        /* There may be unmarked reachable objects      */
                    602:        GC_gcollect_inner();
                    603:     }   /* else we're OK in assuming everything's      */
                    604:        /* clean since nothing can point to an          */
                    605:        /* unmarked object.                             */
                    606:     GC_read_dirty();
                    607:     GC_incremental = TRUE;
                    608: out:
                    609:     UNLOCK();
                    610:     ENABLE_SIGNALS();
1.1.1.2 ! maekawa   611:   }
1.1       maekawa   612: # endif
                    613: }
                    614:
                    615:
                    616: #ifdef MSWIN32
                    617: # define LOG_FILE "gc.log"
                    618:
                    619:   HANDLE GC_stdout = 0, GC_stderr;
                    620:   int GC_tmp;
                    621:   DWORD GC_junk;
                    622:
                    623:   void GC_set_files()
                    624:   {
                    625:     if (!GC_stdout) {
                    626:         GC_stdout = CreateFile(LOG_FILE, GENERIC_WRITE,
                    627:                               FILE_SHARE_READ | FILE_SHARE_WRITE,
                    628:                               NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,
                    629:                               NULL);
                    630:        if (INVALID_HANDLE_VALUE == GC_stdout) ABORT("Open of log file failed");
                    631:     }
                    632:     if (GC_stderr == 0) {
                    633:        GC_stderr = GC_stdout;
                    634:     }
                    635:   }
                    636:
                    637: #endif
                    638:
                    639: #if defined(OS2) || defined(MACOS)
                    640: FILE * GC_stdout = NULL;
                    641: FILE * GC_stderr = NULL;
                    642: int GC_tmp;  /* Should really be local ... */
                    643:
                    644:   void GC_set_files()
                    645:   {
                    646:       if (GC_stdout == NULL) {
                    647:        GC_stdout = stdout;
                    648:     }
                    649:     if (GC_stderr == NULL) {
                    650:        GC_stderr = stderr;
                    651:     }
                    652:   }
                    653: #endif
                    654:
                    655: #if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32)
                    656:   int GC_stdout = 1;
                    657:   int GC_stderr = 2;
                    658: # if !defined(AMIGA)
                    659: #   include <unistd.h>
                    660: # endif
                    661: #endif
                    662:
                    663: #if !defined(MSWIN32)  && !defined(OS2) && !defined(MACOS)
                    664: int GC_write(fd, buf, len)
                    665: int fd;
                    666: char *buf;
                    667: size_t len;
                    668: {
                    669:      register int bytes_written = 0;
                    670:      register int result;
                    671:
                    672:      while (bytes_written < len) {
                    673: #      ifdef SOLARIS_THREADS
                    674:            result = syscall(SYS_write, fd, buf + bytes_written,
                    675:                                            len - bytes_written);
                    676: #      else
                    677:            result = write(fd, buf + bytes_written, len - bytes_written);
                    678: #      endif
                    679:        if (-1 == result) return(result);
                    680:        bytes_written += result;
                    681:     }
                    682:     return(bytes_written);
                    683: }
                    684: #endif /* UN*X */
                    685:
                    686: #ifdef MSWIN32
                    687: #   define WRITE(f, buf, len) (GC_set_files(), \
                    688:                               GC_tmp = WriteFile((f), (buf), \
                    689:                                                  (len), &GC_junk, NULL),\
                    690:                               (GC_tmp? 1 : -1))
                    691: #else
                    692: #   if defined(OS2) || defined(MACOS)
                    693: #   define WRITE(f, buf, len) (GC_set_files(), \
                    694:                               GC_tmp = fwrite((buf), 1, (len), (f)), \
                    695:                               fflush(f), GC_tmp)
                    696: #   else
                    697: #     define WRITE(f, buf, len) GC_write((f), (buf), (len))
                    698: #   endif
                    699: #endif
                    700:
                    701: /* A version of printf that is unlikely to call malloc, and is thus safer */
                    702: /* to call from the collector in case malloc has been bound to GC_malloc. */
                    703: /* Assumes that no more than 1023 characters are written at once.        */
                    704: /* Assumes that all arguments have been converted to something of the    */
                    705: /* same size as long, and that the format conversions expect something   */
                    706: /* of that size.                                                         */
                    707: void GC_printf(format, a, b, c, d, e, f)
                    708: char * format;
                    709: long a, b, c, d, e, f;
                    710: {
                    711:     char buf[1025];
                    712:
                    713:     if (GC_quiet) return;
                    714:     buf[1024] = 0x15;
                    715:     (void) sprintf(buf, format, a, b, c, d, e, f);
                    716:     if (buf[1024] != 0x15) ABORT("GC_printf clobbered stack");
                    717:     if (WRITE(GC_stdout, buf, strlen(buf)) < 0) ABORT("write to stdout failed");
                    718: }
                    719:
                    720: void GC_err_printf(format, a, b, c, d, e, f)
                    721: char * format;
                    722: long a, b, c, d, e, f;
                    723: {
                    724:     char buf[1025];
                    725:
                    726:     buf[1024] = 0x15;
                    727:     (void) sprintf(buf, format, a, b, c, d, e, f);
                    728:     if (buf[1024] != 0x15) ABORT("GC_err_printf clobbered stack");
                    729:     if (WRITE(GC_stderr, buf, strlen(buf)) < 0) ABORT("write to stderr failed");
                    730: }
                    731:
                    732: void GC_err_puts(s)
                    733: char *s;
                    734: {
                    735:     if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed");
                    736: }
                    737:
                    738: # if defined(__STDC__) || defined(__cplusplus)
                    739:     void GC_default_warn_proc(char *msg, GC_word arg)
                    740: # else
                    741:     void GC_default_warn_proc(msg, arg)
                    742:     char *msg;
                    743:     GC_word arg;
                    744: # endif
                    745: {
                    746:     GC_err_printf1(msg, (unsigned long)arg);
                    747: }
                    748:
                    749: GC_warn_proc GC_current_warn_proc = GC_default_warn_proc;
                    750:
                    751: # if defined(__STDC__) || defined(__cplusplus)
                    752:     GC_warn_proc GC_set_warn_proc(GC_warn_proc p)
                    753: # else
                    754:     GC_warn_proc GC_set_warn_proc(p)
                    755:     GC_warn_proc p;
                    756: # endif
                    757: {
                    758:     GC_warn_proc result;
                    759:
                    760:     LOCK();
                    761:     result = GC_current_warn_proc;
                    762:     GC_current_warn_proc = p;
                    763:     UNLOCK();
                    764:     return(result);
                    765: }
                    766:
                    767:
                    768: #ifndef PCR
                    769: void GC_abort(msg)
                    770: char * msg;
                    771: {
                    772:     GC_err_printf1("%s\n", msg);
                    773:     (void) abort();
                    774: }
                    775: #endif
                    776:
                    777: #ifdef NEED_CALLINFO
                    778:
                    779: void GC_print_callers (info)
                    780: struct callinfo info[NFRAMES];
                    781: {
                    782:     register int i;
                    783:
                    784: #   if NFRAMES == 1
                    785:       GC_err_printf0("\tCaller at allocation:\n");
                    786: #   else
                    787:       GC_err_printf0("\tCall chain at allocation:\n");
                    788: #   endif
                    789:     for (i = 0; i < NFRAMES; i++) {
                    790:        if (info[i].ci_pc == 0) break;
                    791: #      if NARGS > 0
                    792:        {
                    793:          int j;
                    794:
                    795:          GC_err_printf0("\t\targs: ");
                    796:          for (j = 0; j < NARGS; j++) {
                    797:            if (j != 0) GC_err_printf0(", ");
                    798:            GC_err_printf2("%d (0x%X)", ~(info[i].ci_arg[j]),
                    799:                                        ~(info[i].ci_arg[j]));
                    800:          }
                    801:          GC_err_printf0("\n");
                    802:        }
                    803: #      endif
                    804:        GC_err_printf1("\t\t##PC##= 0x%X\n", info[i].ci_pc);
                    805:     }
                    806: }
                    807:
                    808: #endif /* SAVE_CALL_CHAIN */
                    809:
                    810: # ifdef SRC_M3
                    811: void GC_enable()
                    812: {
                    813:     GC_dont_gc--;
                    814: }
                    815:
                    816: void GC_disable()
                    817: {
                    818:     GC_dont_gc++;
                    819: }
                    820: # endif
                    821:
                    822: #if !defined(NO_DEBUGGING)
                    823:
                    824: void GC_dump()
                    825: {
                    826:     GC_printf0("***Static roots:\n");
                    827:     GC_print_static_roots();
                    828:     GC_printf0("\n***Heap sections:\n");
                    829:     GC_print_heap_sects();
                    830:     GC_printf0("\n***Free blocks:\n");
                    831:     GC_print_hblkfreelist();
                    832:     GC_printf0("\n***Blocks in use:\n");
                    833:     GC_print_block_list();
                    834: }
                    835:
                    836: # endif /* NO_DEBUGGING */

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