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