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

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
                     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) || defined(ALPHA) || defined(SPARC))
                    431:        GC_init_linux_data_start();
                    432: #   endif
                    433: #   ifdef SOLARIS_THREADS
                    434:        GC_thr_init();
                    435:        /* We need dirty bits in order to find live stack sections.     */
                    436:         GC_dirty_init();
                    437: #   endif
                    438: #   if defined(IRIX_THREADS) || defined(LINUX_THREADS) \
                    439:        || defined(IRIX_JDK_THREADS)
                    440:         GC_thr_init();
                    441: #   endif
                    442: #   if !defined(THREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \
                    443:        || defined(IRIX_THREADS) || defined(LINUX_THREADS)
                    444:       if (GC_stackbottom == 0) {
                    445:        GC_stackbottom = GC_get_stack_base();
                    446:       }
                    447: #   endif
                    448:     if  (sizeof (ptr_t) != sizeof(word)) {
                    449:         ABORT("sizeof (ptr_t) != sizeof(word)\n");
                    450:     }
                    451:     if  (sizeof (signed_word) != sizeof(word)) {
                    452:         ABORT("sizeof (signed_word) != sizeof(word)\n");
                    453:     }
                    454:     if  (sizeof (struct hblk) != HBLKSIZE) {
                    455:         ABORT("sizeof (struct hblk) != HBLKSIZE\n");
                    456:     }
                    457: #   ifndef THREADS
                    458: #     if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)
                    459:        ABORT(
                    460:          "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
                    461: #     endif
                    462: #     if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN)
                    463:        ABORT(
                    464:          "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
                    465: #     endif
                    466: #     ifdef STACK_GROWS_DOWN
                    467:         if ((word)(&dummy) > (word)GC_stackbottom) {
                    468:           GC_err_printf0(
                    469:                "STACK_GROWS_DOWN is defd, but stack appears to grow up\n");
                    470: #        ifndef UTS4  /* Compiler bug workaround */
                    471:             GC_err_printf2("sp = 0x%lx, GC_stackbottom = 0x%lx\n",
                    472:                           (unsigned long) (&dummy),
                    473:                           (unsigned long) GC_stackbottom);
                    474: #        endif
                    475:           ABORT("stack direction 3\n");
                    476:         }
                    477: #     else
                    478:         if ((word)(&dummy) < (word)GC_stackbottom) {
                    479:           GC_err_printf0(
                    480:                "STACK_GROWS_UP is defd, but stack appears to grow down\n");
                    481:           GC_err_printf2("sp = 0x%lx, GC_stackbottom = 0x%lx\n",
                    482:                         (unsigned long) (&dummy),
                    483:                         (unsigned long) GC_stackbottom);
                    484:           ABORT("stack direction 4");
                    485:         }
                    486: #     endif
                    487: #   endif
                    488: #   if !defined(_AUX_SOURCE) || defined(__GNUC__)
                    489:       if ((word)(-1) < (word)0) {
                    490:        GC_err_printf0("The type word should be an unsigned integer type\n");
                    491:        GC_err_printf0("It appears to be signed\n");
                    492:        ABORT("word");
                    493:       }
                    494: #   endif
                    495:     if ((signed_word)(-1) >= (signed_word)0) {
                    496:        GC_err_printf0(
                    497:                "The type signed_word should be a signed integer type\n");
                    498:        GC_err_printf0("It appears to be unsigned\n");
                    499:        ABORT("signed_word");
                    500:     }
                    501:
                    502:     /* Add initial guess of root sets.  Do this first, since sbrk(0)   */
                    503:     /* might be used.                                                  */
                    504:       GC_register_data_segments();
                    505:     GC_init_headers();
                    506:     GC_bl_init();
                    507:     GC_mark_init();
                    508:     if (!GC_expand_hp_inner((word)MINHINCR)) {
                    509:         GC_err_printf0("Can't start up: not enough memory\n");
                    510:         EXIT();
                    511:     }
                    512:     /* Preallocate large object map.  It's otherwise inconvenient to   */
                    513:     /* deal with failure.                                              */
                    514:       if (!GC_add_map_entry((word)0)) {
                    515:         GC_err_printf0("Can't start up: not enough memory\n");
                    516:         EXIT();
                    517:       }
                    518:     GC_register_displacement_inner(0L);
                    519: #   ifdef MERGE_SIZES
                    520:       GC_init_size_map();
                    521: #   endif
                    522: #   ifdef PCR
                    523:       if (PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever)
                    524:           != PCR_ERes_okay) {
                    525:           ABORT("Can't lock load state\n");
                    526:       } else if (PCR_IL_Unlock() != PCR_ERes_okay) {
                    527:           ABORT("Can't unlock load state\n");
                    528:       }
                    529:       PCR_IL_Unlock();
                    530:       GC_pcr_install();
                    531: #   endif
                    532:     /* Get black list set up */
                    533:       GC_gcollect_inner();
                    534: #   ifdef STUBBORN_ALLOC
                    535:        GC_stubborn_init();
                    536: #   endif
                    537:     GC_is_initialized = TRUE;
                    538:     /* Convince lint that some things are used */
                    539: #   ifdef LINT
                    540:       {
                    541:           extern char * GC_copyright[];
                    542:           extern int GC_read();
                    543:           extern void GC_register_finalizer_no_order();
                    544:
                    545:           GC_noop(GC_copyright, GC_find_header,
                    546:                   GC_push_one, GC_call_with_alloc_lock, GC_read,
                    547:                   GC_dont_expand,
                    548: #                ifndef NO_DEBUGGING
                    549:                    GC_dump,
                    550: #                endif
                    551:                   GC_register_finalizer_no_order);
                    552:       }
                    553: #   endif
                    554: }
                    555:
                    556: void GC_enable_incremental GC_PROTO(())
                    557: {
                    558: # if  !defined(FIND_LEAK) && !defined(SMALL_CONFIG)
                    559:     DCL_LOCK_STATE;
                    560:
                    561:     DISABLE_SIGNALS();
                    562:     LOCK();
                    563:     if (GC_incremental) goto out;
                    564:     GC_setpagesize();
                    565: #   ifdef MSWIN32
                    566:       {
                    567:         extern GC_bool GC_is_win32s();
                    568:
                    569:        /* VirtualProtect is not functional under win32s.       */
                    570:        if (GC_is_win32s()) goto out;
                    571:       }
                    572: #   endif /* MSWIN32 */
                    573: #   ifndef SOLARIS_THREADS
                    574:         GC_dirty_init();
                    575: #   endif
                    576:     if (!GC_is_initialized) {
                    577:         GC_init_inner();
                    578:     }
                    579:     if (GC_dont_gc) {
                    580:         /* Can't easily do it. */
                    581:         UNLOCK();
                    582:        ENABLE_SIGNALS();
                    583:        return;
                    584:     }
                    585:     if (GC_words_allocd > 0) {
                    586:        /* There may be unmarked reachable objects      */
                    587:        GC_gcollect_inner();
                    588:     }   /* else we're OK in assuming everything's      */
                    589:        /* clean since nothing can point to an          */
                    590:        /* unmarked object.                             */
                    591:     GC_read_dirty();
                    592:     GC_incremental = TRUE;
                    593: out:
                    594:     UNLOCK();
                    595:     ENABLE_SIGNALS();
                    596: # endif
                    597: }
                    598:
                    599:
                    600: #ifdef MSWIN32
                    601: # define LOG_FILE "gc.log"
                    602:
                    603:   HANDLE GC_stdout = 0, GC_stderr;
                    604:   int GC_tmp;
                    605:   DWORD GC_junk;
                    606:
                    607:   void GC_set_files()
                    608:   {
                    609:     if (!GC_stdout) {
                    610:         GC_stdout = CreateFile(LOG_FILE, GENERIC_WRITE,
                    611:                               FILE_SHARE_READ | FILE_SHARE_WRITE,
                    612:                               NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,
                    613:                               NULL);
                    614:        if (INVALID_HANDLE_VALUE == GC_stdout) ABORT("Open of log file failed");
                    615:     }
                    616:     if (GC_stderr == 0) {
                    617:        GC_stderr = GC_stdout;
                    618:     }
                    619:   }
                    620:
                    621: #endif
                    622:
                    623: #if defined(OS2) || defined(MACOS)
                    624: FILE * GC_stdout = NULL;
                    625: FILE * GC_stderr = NULL;
                    626: int GC_tmp;  /* Should really be local ... */
                    627:
                    628:   void GC_set_files()
                    629:   {
                    630:       if (GC_stdout == NULL) {
                    631:        GC_stdout = stdout;
                    632:     }
                    633:     if (GC_stderr == NULL) {
                    634:        GC_stderr = stderr;
                    635:     }
                    636:   }
                    637: #endif
                    638:
                    639: #if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32)
                    640:   int GC_stdout = 1;
                    641:   int GC_stderr = 2;
                    642: # if !defined(AMIGA)
                    643: #   include <unistd.h>
                    644: # endif
                    645: #endif
                    646:
                    647: #if !defined(MSWIN32)  && !defined(OS2) && !defined(MACOS)
                    648: int GC_write(fd, buf, len)
                    649: int fd;
                    650: char *buf;
                    651: size_t len;
                    652: {
                    653:      register int bytes_written = 0;
                    654:      register int result;
                    655:
                    656:      while (bytes_written < len) {
                    657: #      ifdef SOLARIS_THREADS
                    658:            result = syscall(SYS_write, fd, buf + bytes_written,
                    659:                                            len - bytes_written);
                    660: #      else
                    661:            result = write(fd, buf + bytes_written, len - bytes_written);
                    662: #      endif
                    663:        if (-1 == result) return(result);
                    664:        bytes_written += result;
                    665:     }
                    666:     return(bytes_written);
                    667: }
                    668: #endif /* UN*X */
                    669:
                    670: #ifdef MSWIN32
                    671: #   define WRITE(f, buf, len) (GC_set_files(), \
                    672:                               GC_tmp = WriteFile((f), (buf), \
                    673:                                                  (len), &GC_junk, NULL),\
                    674:                               (GC_tmp? 1 : -1))
                    675: #else
                    676: #   if defined(OS2) || defined(MACOS)
                    677: #   define WRITE(f, buf, len) (GC_set_files(), \
                    678:                               GC_tmp = fwrite((buf), 1, (len), (f)), \
                    679:                               fflush(f), GC_tmp)
                    680: #   else
                    681: #     define WRITE(f, buf, len) GC_write((f), (buf), (len))
                    682: #   endif
                    683: #endif
                    684:
                    685: /* A version of printf that is unlikely to call malloc, and is thus safer */
                    686: /* to call from the collector in case malloc has been bound to GC_malloc. */
                    687: /* Assumes that no more than 1023 characters are written at once.        */
                    688: /* Assumes that all arguments have been converted to something of the    */
                    689: /* same size as long, and that the format conversions expect something   */
                    690: /* of that size.                                                         */
                    691: void GC_printf(format, a, b, c, d, e, f)
                    692: char * format;
                    693: long a, b, c, d, e, f;
                    694: {
                    695:     char buf[1025];
                    696:
                    697:     if (GC_quiet) return;
                    698:     buf[1024] = 0x15;
                    699:     (void) sprintf(buf, format, a, b, c, d, e, f);
                    700:     if (buf[1024] != 0x15) ABORT("GC_printf clobbered stack");
                    701:     if (WRITE(GC_stdout, buf, strlen(buf)) < 0) ABORT("write to stdout failed");
                    702: }
                    703:
                    704: void GC_err_printf(format, a, b, c, d, e, f)
                    705: char * format;
                    706: long a, b, c, d, e, f;
                    707: {
                    708:     char buf[1025];
                    709:
                    710:     buf[1024] = 0x15;
                    711:     (void) sprintf(buf, format, a, b, c, d, e, f);
                    712:     if (buf[1024] != 0x15) ABORT("GC_err_printf clobbered stack");
                    713:     if (WRITE(GC_stderr, buf, strlen(buf)) < 0) ABORT("write to stderr failed");
                    714: }
                    715:
                    716: void GC_err_puts(s)
                    717: char *s;
                    718: {
                    719:     if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed");
                    720: }
                    721:
                    722: # if defined(__STDC__) || defined(__cplusplus)
                    723:     void GC_default_warn_proc(char *msg, GC_word arg)
                    724: # else
                    725:     void GC_default_warn_proc(msg, arg)
                    726:     char *msg;
                    727:     GC_word arg;
                    728: # endif
                    729: {
                    730:     GC_err_printf1(msg, (unsigned long)arg);
                    731: }
                    732:
                    733: GC_warn_proc GC_current_warn_proc = GC_default_warn_proc;
                    734:
                    735: # if defined(__STDC__) || defined(__cplusplus)
                    736:     GC_warn_proc GC_set_warn_proc(GC_warn_proc p)
                    737: # else
                    738:     GC_warn_proc GC_set_warn_proc(p)
                    739:     GC_warn_proc p;
                    740: # endif
                    741: {
                    742:     GC_warn_proc result;
                    743:
                    744:     LOCK();
                    745:     result = GC_current_warn_proc;
                    746:     GC_current_warn_proc = p;
                    747:     UNLOCK();
                    748:     return(result);
                    749: }
                    750:
                    751:
                    752: #ifndef PCR
                    753: void GC_abort(msg)
                    754: char * msg;
                    755: {
                    756:     GC_err_printf1("%s\n", msg);
                    757:     (void) abort();
                    758: }
                    759: #endif
                    760:
                    761: #ifdef NEED_CALLINFO
                    762:
                    763: void GC_print_callers (info)
                    764: struct callinfo info[NFRAMES];
                    765: {
                    766:     register int i;
                    767:
                    768: #   if NFRAMES == 1
                    769:       GC_err_printf0("\tCaller at allocation:\n");
                    770: #   else
                    771:       GC_err_printf0("\tCall chain at allocation:\n");
                    772: #   endif
                    773:     for (i = 0; i < NFRAMES; i++) {
                    774:        if (info[i].ci_pc == 0) break;
                    775: #      if NARGS > 0
                    776:        {
                    777:          int j;
                    778:
                    779:          GC_err_printf0("\t\targs: ");
                    780:          for (j = 0; j < NARGS; j++) {
                    781:            if (j != 0) GC_err_printf0(", ");
                    782:            GC_err_printf2("%d (0x%X)", ~(info[i].ci_arg[j]),
                    783:                                        ~(info[i].ci_arg[j]));
                    784:          }
                    785:          GC_err_printf0("\n");
                    786:        }
                    787: #      endif
                    788:        GC_err_printf1("\t\t##PC##= 0x%X\n", info[i].ci_pc);
                    789:     }
                    790: }
                    791:
                    792: #endif /* SAVE_CALL_CHAIN */
                    793:
                    794: # ifdef SRC_M3
                    795: void GC_enable()
                    796: {
                    797:     GC_dont_gc--;
                    798: }
                    799:
                    800: void GC_disable()
                    801: {
                    802:     GC_dont_gc++;
                    803: }
                    804: # endif
                    805:
                    806: #if !defined(NO_DEBUGGING)
                    807:
                    808: void GC_dump()
                    809: {
                    810:     GC_printf0("***Static roots:\n");
                    811:     GC_print_static_roots();
                    812:     GC_printf0("\n***Heap sections:\n");
                    813:     GC_print_heap_sects();
                    814:     GC_printf0("\n***Free blocks:\n");
                    815:     GC_print_hblkfreelist();
                    816:     GC_printf0("\n***Blocks in use:\n");
                    817:     GC_print_block_list();
                    818: }
                    819:
                    820: # endif /* NO_DEBUGGING */

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