[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.3

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

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