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

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

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