[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     ! 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>