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

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.
1.6     ! noro        4:  * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved.
1.1       noro        5:  *
                      6:  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
                      7:  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
                      8:  *
                      9:  * Permission is hereby granted to use or copy this program
                     10:  * for any purpose,  provided the above notices are retained on all copies.
                     11:  * Permission to modify the code and to distribute modified code is granted,
                     12:  * provided the above notices are retained, and a notice that the code was
                     13:  * modified is included with the above copyright notice.
                     14:  */
                     15: /* Boehm, July 31, 1995 5:02 pm PDT */
                     16:
                     17:
                     18: #include <stdio.h>
1.6     ! noro       19: #include <limits.h>
1.4       noro       20: #ifndef _WIN32_WCE
1.1       noro       21: #include <signal.h>
1.4       noro       22: #endif
1.1       noro       23:
                     24: #define I_HIDE_POINTERS        /* To make GC_call_with_alloc_lock visible */
1.4       noro       25: #include "private/gc_pmark.h"
1.1       noro       26:
1.6     ! noro       27: #ifdef GC_SOLARIS_THREADS
1.1       noro       28: # include <sys/syscall.h>
                     29: #endif
1.4       noro       30: #if defined(MSWIN32) || defined(MSWINCE)
                     31: # define WIN32_LEAN_AND_MEAN
                     32: # define NOSERVICE
1.1       noro       33: # include <windows.h>
1.4       noro       34: # include <tchar.h>
1.1       noro       35: #endif
                     36:
                     37: # ifdef THREADS
                     38: #   ifdef PCR
                     39: #     include "il/PCR_IL.h"
                     40:       PCR_Th_ML GC_allocate_ml;
                     41: #   else
                     42: #     ifdef SRC_M3
                     43:        /* Critical section counter is defined in the M3 runtime        */
                     44:        /* That's all we use.                                           */
                     45: #     else
1.6     ! noro       46: #      ifdef GC_SOLARIS_THREADS
1.1       noro       47:          mutex_t GC_allocate_ml;       /* Implicitly initialized.      */
                     48: #      else
1.6     ! noro       49: #          if defined(GC_WIN32_THREADS)
        !            50: #             if defined(GC_PTHREADS)
        !            51:                  pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
        !            52: #            elif !defined(GC_NOT_DLL) && (defined(_DLL) || defined(GC_DLL))
1.4       noro       53:                 __declspec(dllexport) CRITICAL_SECTION GC_allocate_ml;
                     54: #            else
                     55:                 CRITICAL_SECTION GC_allocate_ml;
                     56: #            endif
1.1       noro       57: #          else
1.6     ! noro       58: #             if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS)
        !            59: #              if defined(USE_SPIN_LOCK)
        !            60:                  pthread_t GC_lock_holder = NO_THREAD;
        !            61: #              else
1.2       noro       62:                  pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
1.4       noro       63:                  pthread_t GC_lock_holder = NO_THREAD;
                     64:                        /* Used only for assertions, and to prevent      */
                     65:                        /* recursive reentry in the system call wrapper. */
1.6     ! noro       66: #              endif
        !            67: #            else
1.2       noro       68:                  --> declare allocator lock here
1.1       noro       69: #            endif
                     70: #         endif
                     71: #      endif
                     72: #     endif
                     73: #   endif
                     74: # endif
                     75:
1.6     ! noro       76: #if defined(NOSYS) || defined(ECOS)
        !            77: #undef STACKBASE
        !            78: #endif
        !            79:
1.1       noro       80: GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */;
                     81:
                     82:
                     83: GC_bool GC_debugging_started = FALSE;
                     84:        /* defined here so we don't have to load debug_malloc.o */
                     85:
1.4       noro       86: void (*GC_check_heap) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0;
1.6     ! noro       87: void (*GC_print_all_smashed) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0;
1.1       noro       88:
1.4       noro       89: void (*GC_start_call_back) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0;
1.1       noro       90:
                     91: ptr_t GC_stackbottom = 0;
                     92:
1.4       noro       93: #ifdef IA64
                     94:   ptr_t GC_register_stackbottom = 0;
                     95: #endif
                     96:
1.1       noro       97: GC_bool GC_dont_gc = 0;
                     98:
1.4       noro       99: GC_bool GC_dont_precollect = 0;
                    100:
1.1       noro      101: GC_bool GC_quiet = 0;
                    102:
1.4       noro      103: GC_bool GC_print_stats = 0;
                    104:
1.6     ! noro      105: GC_bool GC_print_back_height = 0;
        !           106:
1.2       noro      107: #ifdef FIND_LEAK
                    108:   int GC_find_leak = 1;
                    109: #else
                    110:   int GC_find_leak = 0;
                    111: #endif
                    112:
1.4       noro      113: #ifdef ALL_INTERIOR_POINTERS
                    114:   int GC_all_interior_pointers = 1;
                    115: #else
                    116:   int GC_all_interior_pointers = 0;
                    117: #endif
                    118:
1.6     ! noro      119: long GC_large_alloc_warn_interval = 5;
        !           120:        /* Interval between unsuppressed warnings.      */
        !           121:
        !           122: long GC_large_alloc_warn_suppressed = 0;
        !           123:        /* Number of warnings suppressed so far.        */
        !           124:
1.1       noro      125: /*ARGSUSED*/
                    126: GC_PTR GC_default_oom_fn GC_PROTO((size_t bytes_requested))
                    127: {
                    128:     return(0);
                    129: }
                    130:
                    131: GC_PTR (*GC_oom_fn) GC_PROTO((size_t bytes_requested)) = GC_default_oom_fn;
                    132:
                    133: extern signed_word GC_mem_found;
                    134:
                    135: # ifdef MERGE_SIZES
                    136:     /* Set things up so that GC_size_map[i] >= words(i),               */
                    137:     /* but not too much bigger                                         */
                    138:     /* and so that size_map contains relatively few distinct entries   */
                    139:     /* This is stolen from Russ Atkinson's Cedar quantization          */
                    140:     /* alogrithm (but we precompute it).                               */
                    141:
                    142:
                    143:     void GC_init_size_map()
                    144:     {
                    145:        register unsigned i;
                    146:
1.4       noro      147:        /* Map size 0 to something bigger.                      */
                    148:        /* This avoids problems at lower levels.                */
                    149:        /* One word objects don't have to be 2 word aligned,    */
                    150:        /* unless we're using mark bytes.                       */
                    151:          for (i = 0; i < sizeof(word); i++) {
                    152:              GC_size_map[i] = MIN_WORDS;
1.1       noro      153:          }
1.4       noro      154: #        if MIN_WORDS > 1
                    155:            GC_size_map[sizeof(word)] = MIN_WORDS;
                    156: #        else
                    157:            GC_size_map[sizeof(word)] = ROUNDED_UP_WORDS(sizeof(word));
                    158: #        endif
1.1       noro      159:        for (i = sizeof(word) + 1; i <= 8 * sizeof(word); i++) {
1.4       noro      160:            GC_size_map[i] = ALIGNED_WORDS(i);
1.1       noro      161:        }
                    162:        for (i = 8*sizeof(word) + 1; i <= 16 * sizeof(word); i++) {
                    163:              GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1);
                    164:        }
1.3       noro      165: #      ifdef GC_GCJ_SUPPORT
                    166:           /* Make all sizes up to 32 words predictable, so that a      */
                    167:           /* compiler can statically perform the same computation,     */
                    168:           /* or at least a computation that results in similar size    */
                    169:           /* classes.                                                  */
                    170:           for (i = 16*sizeof(word) + 1; i <= 32 * sizeof(word); i++) {
                    171:              GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 3) & (~3);
                    172:           }
                    173: #      endif
1.1       noro      174:        /* We leave the rest of the array to be filled in on demand. */
                    175:     }
                    176:
                    177:     /* Fill in additional entries in GC_size_map, including the ith one */
                    178:     /* We assume the ith entry is currently 0.                         */
                    179:     /* Note that a filled in section of the array ending at n always    */
                    180:     /* has length at least n/4.                                                */
                    181:     void GC_extend_size_map(i)
                    182:     word i;
                    183:     {
                    184:         word orig_word_sz = ROUNDED_UP_WORDS(i);
                    185:         word word_sz = orig_word_sz;
                    186:        register word byte_sz = WORDS_TO_BYTES(word_sz);
                    187:                                /* The size we try to preserve.         */
                    188:                                /* Close to to i, unless this would     */
                    189:                                /* introduce too many distinct sizes.   */
                    190:        word smaller_than_i = byte_sz - (byte_sz >> 3);
                    191:        word much_smaller_than_i = byte_sz - (byte_sz >> 2);
                    192:        register word low_limit;        /* The lowest indexed entry we  */
                    193:                                        /* initialize.                  */
                    194:        register word j;
                    195:
                    196:        if (GC_size_map[smaller_than_i] == 0) {
                    197:            low_limit = much_smaller_than_i;
                    198:            while (GC_size_map[low_limit] != 0) low_limit++;
                    199:        } else {
                    200:            low_limit = smaller_than_i + 1;
                    201:            while (GC_size_map[low_limit] != 0) low_limit++;
                    202:            word_sz = ROUNDED_UP_WORDS(low_limit);
                    203:            word_sz += word_sz >> 3;
                    204:            if (word_sz < orig_word_sz) word_sz = orig_word_sz;
                    205:        }
                    206: #      ifdef ALIGN_DOUBLE
                    207:            word_sz += 1;
                    208:            word_sz &= ~1;
                    209: #      endif
                    210:        if (word_sz > MAXOBJSZ) {
                    211:            word_sz = MAXOBJSZ;
                    212:        }
                    213:        /* If we can fit the same number of larger objects in a block,  */
                    214:        /* do so.                                                       */
                    215:        {
                    216:            size_t number_of_objs = BODY_SZ/word_sz;
                    217:            word_sz = BODY_SZ/number_of_objs;
                    218: #          ifdef ALIGN_DOUBLE
                    219:                word_sz &= ~1;
                    220: #          endif
                    221:        }
                    222:        byte_sz = WORDS_TO_BYTES(word_sz);
1.4       noro      223:        if (GC_all_interior_pointers) {
1.1       noro      224:            /* We need one extra byte; don't fill in GC_size_map[byte_sz] */
                    225:            byte_sz--;
1.4       noro      226:        }
1.1       noro      227:
                    228:        for (j = low_limit; j <= byte_sz; j++) GC_size_map[j] = word_sz;
                    229:     }
                    230: # endif
                    231:
                    232:
                    233: /*
                    234:  * The following is a gross hack to deal with a problem that can occur
                    235:  * on machines that are sloppy about stack frame sizes, notably SPARC.
                    236:  * Bogus pointers may be written to the stack and not cleared for
                    237:  * a LONG time, because they always fall into holes in stack frames
                    238:  * that are not written.  We partially address this by clearing
                    239:  * sections of the stack whenever we get control.
                    240:  */
                    241: word GC_stack_last_cleared = 0;        /* GC_no when we last did this */
                    242: # ifdef THREADS
1.4       noro      243: #   define BIG_CLEAR_SIZE 2048 /* Clear this much now and then.        */
                    244: #   define SMALL_CLEAR_SIZE 256 /* Clear this much every time.         */
1.1       noro      245: # endif
1.4       noro      246: # define CLEAR_SIZE 213  /* Granularity for GC_clear_stack_inner */
1.1       noro      247: # define DEGRADE_RATE 50
                    248:
                    249: word GC_min_sp;                /* Coolest stack pointer value from which we've */
                    250:                        /* already cleared the stack.                   */
                    251:
                    252: word GC_high_water;
                    253:                        /* "hottest" stack pointer value we have seen   */
                    254:                        /* recently.  Degrades over time.               */
                    255:
                    256: word GC_words_allocd_at_reset;
                    257:
1.4       noro      258: #if defined(ASM_CLEAR_CODE)
1.1       noro      259:   extern ptr_t GC_clear_stack_inner();
1.4       noro      260: #else
1.1       noro      261: /* Clear the stack up to about limit.  Return arg. */
                    262: /*ARGSUSED*/
                    263: ptr_t GC_clear_stack_inner(arg, limit)
                    264: ptr_t arg;
                    265: word limit;
                    266: {
                    267:     word dummy[CLEAR_SIZE];
                    268:
                    269:     BZERO(dummy, CLEAR_SIZE*sizeof(word));
                    270:     if ((word)(dummy) COOLER_THAN limit) {
                    271:         (void) GC_clear_stack_inner(arg, limit);
                    272:     }
                    273:     /* Make sure the recursive call is not a tail call, and the bzero  */
                    274:     /* call is not recognized as dead code.                            */
                    275:     GC_noop1((word)dummy);
                    276:     return(arg);
                    277: }
                    278: #endif
                    279:
                    280: /* Clear some of the inaccessible part of the stack.  Returns its      */
                    281: /* argument, so it can be used in a tail call position, hence clearing  */
                    282: /* another frame.                                                      */
                    283: ptr_t GC_clear_stack(arg)
                    284: ptr_t arg;
                    285: {
                    286:     register word sp = (word)GC_approx_sp();  /* Hotter than actual sp */
                    287: #   ifdef THREADS
1.4       noro      288:         word dummy[SMALL_CLEAR_SIZE];
                    289:        static unsigned random_no = 0;
                    290:                                         /* Should be more random than it is ... */
                    291:                                 /* Used to occasionally clear a bigger  */
                    292:                                 /* chunk.                               */
1.1       noro      293: #   endif
1.4       noro      294:     register word limit;
1.1       noro      295:
                    296: #   define SLOP 400
                    297:        /* Extra bytes we clear every time.  This clears our own        */
                    298:        /* activation record, and should cause more frequent            */
                    299:        /* clearing near the cold end of the stack, a good thing.       */
                    300: #   define GC_SLOP 4000
                    301:        /* We make GC_high_water this much hotter than we really saw    */
                    302:        /* saw it, to cover for GC noise etc. above our current frame.  */
                    303: #   define CLEAR_THRESHOLD 100000
                    304:        /* We restart the clearing process after this many bytes of     */
                    305:        /* allocation.  Otherwise very heavily recursive programs       */
                    306:        /* with sparse stacks may result in heaps that grow almost      */
                    307:        /* without bounds.  As the heap gets larger, collection         */
                    308:        /* frequency decreases, thus clearing frequency would decrease, */
                    309:        /* thus more junk remains accessible, thus the heap gets        */
                    310:        /* larger ...                                                   */
                    311: # ifdef THREADS
1.4       noro      312:     if (++random_no % 13 == 0) {
                    313:        limit = sp;
                    314:        MAKE_HOTTER(limit, BIG_CLEAR_SIZE*sizeof(word));
1.6     ! noro      315:         limit &= ~0xf; /* Make it sufficiently aligned for assembly    */
        !           316:                        /* implementations of GC_clear_stack_inner.     */
1.4       noro      317:        return GC_clear_stack_inner(arg, limit);
                    318:     } else {
                    319:        BZERO(dummy, SMALL_CLEAR_SIZE*sizeof(word));
                    320:        return arg;
                    321:     }
1.1       noro      322: # else
                    323:     if (GC_gc_no > GC_stack_last_cleared) {
                    324:         /* Start things over, so we clear the entire stack again */
                    325:         if (GC_stack_last_cleared == 0) GC_high_water = (word) GC_stackbottom;
                    326:         GC_min_sp = GC_high_water;
                    327:         GC_stack_last_cleared = GC_gc_no;
                    328:         GC_words_allocd_at_reset = GC_words_allocd;
                    329:     }
                    330:     /* Adjust GC_high_water */
                    331:         MAKE_COOLER(GC_high_water, WORDS_TO_BYTES(DEGRADE_RATE) + GC_SLOP);
                    332:         if (sp HOTTER_THAN GC_high_water) {
                    333:             GC_high_water = sp;
                    334:         }
                    335:         MAKE_HOTTER(GC_high_water, GC_SLOP);
                    336:     limit = GC_min_sp;
                    337:     MAKE_HOTTER(limit, SLOP);
                    338:     if (sp COOLER_THAN limit) {
                    339:         limit &= ~0xf; /* Make it sufficiently aligned for assembly    */
                    340:                        /* implementations of GC_clear_stack_inner.     */
                    341:         GC_min_sp = sp;
                    342:         return(GC_clear_stack_inner(arg, limit));
                    343:     } else if (WORDS_TO_BYTES(GC_words_allocd - GC_words_allocd_at_reset)
                    344:               > CLEAR_THRESHOLD) {
                    345:        /* Restart clearing process, but limit how much clearing we do. */
                    346:        GC_min_sp = sp;
                    347:        MAKE_HOTTER(GC_min_sp, CLEAR_THRESHOLD/4);
                    348:        if (GC_min_sp HOTTER_THAN GC_high_water) GC_min_sp = GC_high_water;
                    349:        GC_words_allocd_at_reset = GC_words_allocd;
                    350:     }
1.4       noro      351:     return(arg);
1.1       noro      352: # endif
                    353: }
                    354:
                    355:
                    356: /* Return a pointer to the base address of p, given a pointer to a     */
                    357: /* an address within an object.  Return 0 o.w.                         */
                    358: # ifdef __STDC__
                    359:     GC_PTR GC_base(GC_PTR p)
                    360: # else
                    361:     GC_PTR GC_base(p)
                    362:     GC_PTR p;
                    363: # endif
                    364: {
                    365:     register word r;
                    366:     register struct hblk *h;
                    367:     register bottom_index *bi;
                    368:     register hdr *candidate_hdr;
                    369:     register word limit;
                    370:
                    371:     r = (word)p;
                    372:     if (!GC_is_initialized) return 0;
                    373:     h = HBLKPTR(r);
                    374:     GET_BI(r, bi);
                    375:     candidate_hdr = HDR_FROM_BI(bi, r);
                    376:     if (candidate_hdr == 0) return(0);
                    377:     /* If it's a pointer to the middle of a large object, move it      */
                    378:     /* to the beginning.                                               */
                    379:        while (IS_FORWARDING_ADDR_OR_NIL(candidate_hdr)) {
                    380:           h = FORWARDED_ADDR(h,candidate_hdr);
1.4       noro      381:           r = (word)h;
1.1       noro      382:           candidate_hdr = HDR(h);
                    383:        }
                    384:     if (candidate_hdr -> hb_map == GC_invalid_map) return(0);
                    385:     /* Make sure r points to the beginning of the object */
                    386:        r &= ~(WORDS_TO_BYTES(1) - 1);
                    387:         {
1.4       noro      388:            register int offset = HBLKDISPL(r);
1.1       noro      389:            register signed_word sz = candidate_hdr -> hb_sz;
1.4       noro      390:            register signed_word map_entry;
1.1       noro      391:
1.4       noro      392:            map_entry = MAP_ENTRY((candidate_hdr -> hb_map), offset);
                    393:            if (map_entry > CPP_MAX_OFFSET) {
                    394:                map_entry = (signed_word)(BYTES_TO_WORDS(offset)) % sz;
                    395:             }
                    396:             r -= WORDS_TO_BYTES(map_entry);
                    397:             limit = r + WORDS_TO_BYTES(sz);
                    398:            if (limit > (word)(h + 1)
                    399:                && sz <= BYTES_TO_WORDS(HBLKSIZE)) {
1.1       noro      400:                return(0);
1.4       noro      401:            }
1.1       noro      402:            if ((word)p >= limit) return(0);
                    403:        }
                    404:     return((GC_PTR)r);
                    405: }
                    406:
                    407:
                    408: /* Return the size of an object, given a pointer to its base.          */
                    409: /* (For small obects this also happens to work from interior pointers, */
                    410: /* but that shouldn't be relied upon.)                                 */
                    411: # ifdef __STDC__
                    412:     size_t GC_size(GC_PTR p)
                    413: # else
                    414:     size_t GC_size(p)
                    415:     GC_PTR p;
                    416: # endif
                    417: {
                    418:     register int sz;
                    419:     register hdr * hhdr = HDR(p);
                    420:
                    421:     sz = WORDS_TO_BYTES(hhdr -> hb_sz);
1.4       noro      422:     return(sz);
1.1       noro      423: }
                    424:
                    425: size_t GC_get_heap_size GC_PROTO(())
                    426: {
                    427:     return ((size_t) GC_heapsize);
                    428: }
                    429:
1.2       noro      430: size_t GC_get_free_bytes GC_PROTO(())
                    431: {
                    432:     return ((size_t) GC_large_free_bytes);
                    433: }
                    434:
1.1       noro      435: size_t GC_get_bytes_since_gc GC_PROTO(())
                    436: {
                    437:     return ((size_t) WORDS_TO_BYTES(GC_words_allocd));
                    438: }
                    439:
1.4       noro      440: size_t GC_get_total_bytes GC_PROTO(())
                    441: {
                    442:     return ((size_t) WORDS_TO_BYTES(GC_words_allocd+GC_words_allocd_before_gc));
                    443: }
                    444:
1.1       noro      445: GC_bool GC_is_initialized = FALSE;
                    446:
                    447: void GC_init()
                    448: {
                    449:     DCL_LOCK_STATE;
                    450:
                    451:     DISABLE_SIGNALS();
1.6     ! noro      452:
        !           453: #if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
        !           454:     if (!GC_is_initialized) InitializeCriticalSection(&GC_allocate_ml);
        !           455: #endif /* MSWIN32 */
        !           456:
1.1       noro      457:     LOCK();
                    458:     GC_init_inner();
                    459:     UNLOCK();
                    460:     ENABLE_SIGNALS();
                    461:
1.6     ! noro      462: #   if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
        !           463:        /* Make sure marker threads and started and thread local */
        !           464:        /* allocation is initialized, in case we didn't get      */
        !           465:        /* called from GC_init_parallel();                       */
        !           466:         {
        !           467:          extern void GC_init_parallel(void);
        !           468:          GC_init_parallel();
        !           469:        }
        !           470: #   endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
1.1       noro      471: }
                    472:
1.4       noro      473: #if defined(MSWIN32) || defined(MSWINCE)
                    474:     CRITICAL_SECTION GC_write_cs;
                    475: #endif
                    476:
1.1       noro      477: #ifdef MSWIN32
1.4       noro      478:     extern void GC_init_win32 GC_PROTO((void));
1.1       noro      479: #endif
                    480:
                    481: extern void GC_setpagesize();
                    482:
1.4       noro      483: #ifdef UNIX_LIKE
                    484:
                    485: extern void GC_set_and_save_fault_handler GC_PROTO((void (*handler)(int)));
                    486:
                    487: static void looping_handler(sig)
                    488: int sig;
                    489: {
                    490:     GC_err_printf1("Caught signal %d: looping in handler\n", sig);
                    491:     for(;;);
                    492: }
                    493: #endif
                    494:
1.6     ! noro      495: #ifdef MSWIN32
        !           496: extern GC_bool GC_no_win32_dlls;
        !           497: #else
        !           498: # define GC_no_win32_dlls FALSE
        !           499: #endif
        !           500:
1.1       noro      501: void GC_init_inner()
                    502: {
1.4       noro      503: #   if !defined(THREADS) && defined(GC_ASSERTIONS)
1.1       noro      504:         word dummy;
                    505: #   endif
1.4       noro      506:     word initial_heap_sz = (word)MINHINCR;
1.1       noro      507:
                    508:     if (GC_is_initialized) return;
1.4       noro      509: #   ifdef PRINTSTATS
                    510:       GC_print_stats = 1;
                    511: #   endif
1.6     ! noro      512: #   if defined(MSWIN32) || defined(MSWINCE)
        !           513:       InitializeCriticalSection(&GC_write_cs);
        !           514: #   endif
1.4       noro      515:     if (0 != GETENV("GC_PRINT_STATS")) {
                    516:       GC_print_stats = 1;
                    517:     }
                    518:     if (0 != GETENV("GC_FIND_LEAK")) {
                    519:       GC_find_leak = 1;
                    520:     }
                    521:     if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) {
                    522:       GC_all_interior_pointers = 1;
                    523:     }
                    524:     if (0 != GETENV("GC_DONT_GC")) {
                    525:       GC_dont_gc = 1;
                    526:     }
1.6     ! noro      527:     if (0 != GETENV("GC_PRINT_BACK_HEIGHT")) {
        !           528:       GC_print_back_height = 1;
        !           529:     }
        !           530:     if (0 != GETENV("GC_NO_BLACKLIST_WARNING")) {
        !           531:       GC_large_alloc_warn_interval = LONG_MAX;
        !           532:     }
        !           533:     {
        !           534:       char * time_limit_string = GETENV("GC_PAUSE_TIME_TARGET");
        !           535:       if (0 != time_limit_string) {
        !           536:         long time_limit = atol(time_limit_string);
        !           537:         if (time_limit < 5) {
        !           538:          WARN("GC_PAUSE_TIME_TARGET environment variable value too small "
        !           539:               "or bad syntax: Ignoring\n", 0);
        !           540:         } else {
        !           541:          GC_time_limit = time_limit;
        !           542:         }
        !           543:       }
        !           544:     }
        !           545:     {
        !           546:       char * interval_string = GETENV("GC_LARGE_ALLOC_WARN_INTERVAL");
        !           547:       if (0 != interval_string) {
        !           548:         long interval = atol(interval_string);
        !           549:         if (interval <= 0) {
        !           550:          WARN("GC_LARGE_ALLOC_WARN_INTERVAL environment variable has "
        !           551:               "bad value: Ignoring\n", 0);
        !           552:         } else {
        !           553:          GC_large_alloc_warn_interval = interval;
        !           554:         }
        !           555:       }
        !           556:     }
1.4       noro      557: #   ifdef UNIX_LIKE
                    558:       if (0 != GETENV("GC_LOOP_ON_ABORT")) {
                    559:         GC_set_and_save_fault_handler(looping_handler);
                    560:       }
                    561: #   endif
                    562:     /* Adjust normal object descriptor for extra allocation.   */
                    563:     if (ALIGNMENT > GC_DS_TAGS && EXTRA_BYTES != 0) {
                    564:       GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH);
                    565:     }
1.1       noro      566:     GC_setpagesize();
1.4       noro      567:     GC_exclude_static_roots(beginGC_arrays, endGC_arrays);
                    568:     GC_exclude_static_roots(beginGC_obj_kinds, endGC_obj_kinds);
                    569: #   ifdef SEPARATE_GLOBALS
                    570:       GC_exclude_static_roots(beginGC_objfreelist, endGC_objfreelist);
                    571:       GC_exclude_static_roots(beginGC_aobjfreelist, endGC_aobjfreelist);
1.1       noro      572: #   endif
                    573: #   ifdef MSWIN32
                    574:        GC_init_win32();
                    575: #   endif
1.3       noro      576: #   if defined(SEARCH_FOR_DATA_START)
1.1       noro      577:        GC_init_linux_data_start();
                    578: #   endif
1.6     ! noro      579: #   if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
1.4       noro      580:        GC_init_netbsd_elf();
                    581: #   endif
1.6     ! noro      582: #   if defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS)
1.4       noro      583:         GC_thr_init();
                    584: #   endif
1.6     ! noro      585: #   ifdef GC_SOLARIS_THREADS
1.1       noro      586:        /* We need dirty bits in order to find live stack sections.     */
                    587:         GC_dirty_init();
                    588: #   endif
1.6     ! noro      589: #   if !defined(THREADS) || defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) \
        !           590:        || defined(GC_SOLARIS_THREADS)
1.1       noro      591:       if (GC_stackbottom == 0) {
                    592:        GC_stackbottom = GC_get_stack_base();
1.4       noro      593: #       if defined(LINUX) && defined(IA64)
                    594:          GC_register_stackbottom = GC_get_register_stack_base();
                    595: #       endif
1.1       noro      596:       }
                    597: #   endif
1.4       noro      598:     GC_ASSERT(sizeof (ptr_t) == sizeof(word));
                    599:     GC_ASSERT(sizeof (signed_word) == sizeof(word));
                    600:     GC_ASSERT(sizeof (struct hblk) == HBLKSIZE);
1.1       noro      601: #   ifndef THREADS
                    602: #     if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)
                    603:        ABORT(
                    604:          "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
                    605: #     endif
                    606: #     if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN)
                    607:        ABORT(
                    608:          "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
                    609: #     endif
                    610: #     ifdef STACK_GROWS_DOWN
1.4       noro      611:         GC_ASSERT((word)(&dummy) <= (word)GC_stackbottom);
1.1       noro      612: #     else
1.4       noro      613:         GC_ASSERT((word)(&dummy) >= (word)GC_stackbottom);
1.1       noro      614: #     endif
                    615: #   endif
                    616: #   if !defined(_AUX_SOURCE) || defined(__GNUC__)
1.4       noro      617:       GC_ASSERT((word)(-1) > (word)0);
                    618:       /* word should be unsigned */
1.1       noro      619: #   endif
1.4       noro      620:     GC_ASSERT((signed_word)(-1) < (signed_word)0);
1.1       noro      621:
                    622:     /* Add initial guess of root sets.  Do this first, since sbrk(0)   */
                    623:     /* might be used.                                                  */
                    624:       GC_register_data_segments();
                    625:     GC_init_headers();
                    626:     GC_bl_init();
                    627:     GC_mark_init();
1.4       noro      628:     {
                    629:        char * sz_str = GETENV("GC_INITIAL_HEAP_SIZE");
                    630:        if (sz_str != NULL) {
                    631:          initial_heap_sz = atoi(sz_str);
                    632:          if (initial_heap_sz <= MINHINCR * HBLKSIZE) {
                    633:            WARN("Bad initial heap size %s - ignoring it.\n",
                    634:                 sz_str);
                    635:          }
                    636:          initial_heap_sz = divHBLKSZ(initial_heap_sz);
                    637:        }
                    638:     }
                    639:     if (!GC_expand_hp_inner(initial_heap_sz)) {
1.1       noro      640:         GC_err_printf0("Can't start up: not enough memory\n");
                    641:         EXIT();
                    642:     }
                    643:     /* Preallocate large object map.  It's otherwise inconvenient to   */
                    644:     /* deal with failure.                                              */
                    645:       if (!GC_add_map_entry((word)0)) {
                    646:         GC_err_printf0("Can't start up: not enough memory\n");
                    647:         EXIT();
                    648:       }
                    649:     GC_register_displacement_inner(0L);
                    650: #   ifdef MERGE_SIZES
                    651:       GC_init_size_map();
                    652: #   endif
                    653: #   ifdef PCR
                    654:       if (PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever)
                    655:           != PCR_ERes_okay) {
                    656:           ABORT("Can't lock load state\n");
                    657:       } else if (PCR_IL_Unlock() != PCR_ERes_okay) {
                    658:           ABORT("Can't unlock load state\n");
                    659:       }
                    660:       PCR_IL_Unlock();
                    661:       GC_pcr_install();
                    662: #   endif
1.6     ! noro      663: #   if !defined(SMALL_CONFIG)
        !           664:       if (!GC_no_win32_dlls && 0 != GETENV("GC_ENABLE_INCREMENTAL")) {
        !           665:        GC_ASSERT(!GC_incremental);
        !           666:         GC_setpagesize();
        !           667: #       ifndef GC_SOLARIS_THREADS
        !           668:           GC_dirty_init();
        !           669: #       endif
        !           670:         GC_ASSERT(GC_words_allocd == 0)
        !           671:        GC_incremental = TRUE;
        !           672:       }
        !           673: #   endif /* !SMALL_CONFIG */
        !           674:     /* Get black list set up and/or incrmental GC started */
        !           675:       if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner();
1.4       noro      676:     GC_is_initialized = TRUE;
1.1       noro      677: #   ifdef STUBBORN_ALLOC
                    678:        GC_stubborn_init();
                    679: #   endif
                    680:     /* Convince lint that some things are used */
                    681: #   ifdef LINT
                    682:       {
                    683:           extern char * GC_copyright[];
                    684:           extern int GC_read();
                    685:           extern void GC_register_finalizer_no_order();
                    686:
                    687:           GC_noop(GC_copyright, GC_find_header,
                    688:                   GC_push_one, GC_call_with_alloc_lock, GC_read,
                    689:                   GC_dont_expand,
                    690: #                ifndef NO_DEBUGGING
                    691:                    GC_dump,
                    692: #                endif
                    693:                   GC_register_finalizer_no_order);
                    694:       }
                    695: #   endif
                    696: }
                    697:
                    698: void GC_enable_incremental GC_PROTO(())
                    699: {
1.2       noro      700: # if !defined(SMALL_CONFIG)
                    701:   if (!GC_find_leak) {
1.1       noro      702:     DCL_LOCK_STATE;
                    703:
                    704:     DISABLE_SIGNALS();
                    705:     LOCK();
                    706:     if (GC_incremental) goto out;
                    707:     GC_setpagesize();
1.6     ! noro      708:     if (GC_no_win32_dlls) goto out;
        !           709: #   ifndef GC_SOLARIS_THREADS
1.1       noro      710:         GC_dirty_init();
                    711: #   endif
                    712:     if (!GC_is_initialized) {
                    713:         GC_init_inner();
                    714:     }
1.6     ! noro      715:     if (GC_incremental) goto out;
1.1       noro      716:     if (GC_dont_gc) {
                    717:         /* Can't easily do it. */
                    718:         UNLOCK();
                    719:        ENABLE_SIGNALS();
                    720:        return;
                    721:     }
                    722:     if (GC_words_allocd > 0) {
                    723:        /* There may be unmarked reachable objects      */
                    724:        GC_gcollect_inner();
                    725:     }   /* else we're OK in assuming everything's      */
                    726:        /* clean since nothing can point to an          */
                    727:        /* unmarked object.                             */
                    728:     GC_read_dirty();
                    729:     GC_incremental = TRUE;
                    730: out:
                    731:     UNLOCK();
                    732:     ENABLE_SIGNALS();
1.2       noro      733:   }
1.1       noro      734: # endif
                    735: }
                    736:
                    737:
1.4       noro      738: #if defined(MSWIN32) || defined(MSWINCE)
                    739: # define LOG_FILE _T("gc.log")
                    740:
                    741:   HANDLE GC_stdout = 0;
1.1       noro      742:
1.4       noro      743:   void GC_deinit()
                    744:   {
                    745:       if (GC_is_initialized) {
                    746:        DeleteCriticalSection(&GC_write_cs);
                    747:       }
                    748:   }
1.1       noro      749:
1.4       noro      750:   int GC_write(buf, len)
1.6     ! noro      751:   GC_CONST char * buf;
1.4       noro      752:   size_t len;
1.1       noro      753:   {
1.4       noro      754:       BOOL tmp;
                    755:       DWORD written;
                    756:       if (len == 0)
                    757:          return 0;
                    758:       EnterCriticalSection(&GC_write_cs);
                    759:       if (GC_stdout == INVALID_HANDLE_VALUE) {
                    760:          return -1;
                    761:       } else if (GC_stdout == 0) {
                    762:          GC_stdout = CreateFile(LOG_FILE, GENERIC_WRITE,
                    763:                                 FILE_SHARE_READ | FILE_SHARE_WRITE,
                    764:                                 NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,
                    765:                                 NULL);
                    766:          if (GC_stdout == INVALID_HANDLE_VALUE) ABORT("Open of log file failed");
                    767:       }
                    768:       tmp = WriteFile(GC_stdout, buf, len, &written, NULL);
                    769:       if (!tmp)
                    770:          DebugBreak();
                    771:       LeaveCriticalSection(&GC_write_cs);
                    772:       return tmp ? (int)written : -1;
1.1       noro      773:   }
                    774:
                    775: #endif
                    776:
                    777: #if defined(OS2) || defined(MACOS)
                    778: FILE * GC_stdout = NULL;
                    779: FILE * GC_stderr = NULL;
                    780: int GC_tmp;  /* Should really be local ... */
                    781:
                    782:   void GC_set_files()
                    783:   {
                    784:       if (GC_stdout == NULL) {
                    785:        GC_stdout = stdout;
                    786:     }
                    787:     if (GC_stderr == NULL) {
                    788:        GC_stderr = stderr;
                    789:     }
                    790:   }
                    791: #endif
                    792:
1.4       noro      793: #if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE)
1.1       noro      794:   int GC_stdout = 1;
                    795:   int GC_stderr = 2;
                    796: # if !defined(AMIGA)
                    797: #   include <unistd.h>
                    798: # endif
                    799: #endif
                    800:
1.6     ! noro      801: #if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) \
        !           802:     && !defined(MACOS)  && !defined(ECOS) && !defined(NOSYS)
1.1       noro      803: int GC_write(fd, buf, len)
                    804: int fd;
1.6     ! noro      805: GC_CONST char *buf;
1.1       noro      806: size_t len;
                    807: {
                    808:      register int bytes_written = 0;
                    809:      register int result;
                    810:
                    811:      while (bytes_written < len) {
1.6     ! noro      812: #      ifdef GC_SOLARIS_THREADS
1.1       noro      813:            result = syscall(SYS_write, fd, buf + bytes_written,
                    814:                                            len - bytes_written);
                    815: #      else
                    816:            result = write(fd, buf + bytes_written, len - bytes_written);
                    817: #      endif
                    818:        if (-1 == result) return(result);
                    819:        bytes_written += result;
                    820:     }
                    821:     return(bytes_written);
                    822: }
                    823: #endif /* UN*X */
                    824:
1.6     ! noro      825: #ifdef ECOS
        !           826: int GC_write(fd, buf, len)
        !           827: {
        !           828:   _Jv_diag_write (buf, len);
        !           829:   return len;
        !           830: }
        !           831: #endif
        !           832:
        !           833: #ifdef NOSYS
        !           834: int GC_write(fd, buf, len)
        !           835: {
        !           836:   /* No writing.  */
        !           837:   return len;
        !           838: }
        !           839: #endif
        !           840:
        !           841:
1.4       noro      842: #if defined(MSWIN32) || defined(MSWINCE)
                    843: #   define WRITE(f, buf, len) GC_write(buf, len)
1.1       noro      844: #else
                    845: #   if defined(OS2) || defined(MACOS)
                    846: #   define WRITE(f, buf, len) (GC_set_files(), \
                    847:                               GC_tmp = fwrite((buf), 1, (len), (f)), \
                    848:                               fflush(f), GC_tmp)
                    849: #   else
                    850: #     define WRITE(f, buf, len) GC_write((f), (buf), (len))
                    851: #   endif
                    852: #endif
                    853:
                    854: /* A version of printf that is unlikely to call malloc, and is thus safer */
                    855: /* to call from the collector in case malloc has been bound to GC_malloc. */
                    856: /* Assumes that no more than 1023 characters are written at once.        */
                    857: /* Assumes that all arguments have been converted to something of the    */
                    858: /* same size as long, and that the format conversions expect something   */
                    859: /* of that size.                                                         */
                    860: void GC_printf(format, a, b, c, d, e, f)
1.4       noro      861: GC_CONST char * format;
1.1       noro      862: long a, b, c, d, e, f;
                    863: {
                    864:     char buf[1025];
                    865:
                    866:     if (GC_quiet) return;
                    867:     buf[1024] = 0x15;
                    868:     (void) sprintf(buf, format, a, b, c, d, e, f);
                    869:     if (buf[1024] != 0x15) ABORT("GC_printf clobbered stack");
                    870:     if (WRITE(GC_stdout, buf, strlen(buf)) < 0) ABORT("write to stdout failed");
                    871: }
                    872:
                    873: void GC_err_printf(format, a, b, c, d, e, f)
1.4       noro      874: GC_CONST char * format;
1.1       noro      875: long a, b, c, d, e, f;
                    876: {
                    877:     char buf[1025];
                    878:
                    879:     buf[1024] = 0x15;
                    880:     (void) sprintf(buf, format, a, b, c, d, e, f);
                    881:     if (buf[1024] != 0x15) ABORT("GC_err_printf clobbered stack");
                    882:     if (WRITE(GC_stderr, buf, strlen(buf)) < 0) ABORT("write to stderr failed");
                    883: }
                    884:
                    885: void GC_err_puts(s)
1.4       noro      886: GC_CONST char *s;
1.1       noro      887: {
                    888:     if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed");
                    889: }
                    890:
1.4       noro      891: #if defined(LINUX) && !defined(SMALL_CONFIG)
                    892: void GC_err_write(buf, len)
                    893: GC_CONST char *buf;
                    894: size_t len;
                    895: {
                    896:     if (WRITE(GC_stderr, buf, len) < 0) ABORT("write to stderr failed");
                    897: }
                    898: #endif
                    899:
1.1       noro      900: # if defined(__STDC__) || defined(__cplusplus)
                    901:     void GC_default_warn_proc(char *msg, GC_word arg)
                    902: # else
                    903:     void GC_default_warn_proc(msg, arg)
                    904:     char *msg;
                    905:     GC_word arg;
                    906: # endif
                    907: {
                    908:     GC_err_printf1(msg, (unsigned long)arg);
                    909: }
                    910:
                    911: GC_warn_proc GC_current_warn_proc = GC_default_warn_proc;
                    912:
                    913: # if defined(__STDC__) || defined(__cplusplus)
                    914:     GC_warn_proc GC_set_warn_proc(GC_warn_proc p)
                    915: # else
                    916:     GC_warn_proc GC_set_warn_proc(p)
                    917:     GC_warn_proc p;
                    918: # endif
                    919: {
                    920:     GC_warn_proc result;
                    921:
                    922:     LOCK();
                    923:     result = GC_current_warn_proc;
                    924:     GC_current_warn_proc = p;
                    925:     UNLOCK();
                    926:     return(result);
                    927: }
                    928:
                    929:
                    930: #ifndef PCR
                    931: void GC_abort(msg)
1.4       noro      932: GC_CONST char * msg;
1.1       noro      933: {
1.4       noro      934: #   if defined(MSWIN32)
                    935:       (void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK);
                    936:       DebugBreak();
                    937: #   else
                    938:       GC_err_printf1("%s\n", msg);
                    939: #   endif
                    940:     if (GETENV("GC_LOOP_ON_ABORT") != NULL) {
                    941:            /* In many cases it's easier to debug a running process.    */
                    942:            /* It's arguably nicer to sleep, but that makes it harder   */
                    943:            /* to look at the thread if the debugger doesn't know much  */
                    944:            /* about threads.                                           */
1.6     ! noro      945:            for(;;) {}
1.4       noro      946:     }
                    947: #   ifdef MSWIN32
                    948:        DebugBreak();
                    949: #   else
                    950:         (void) abort();
                    951: #   endif
1.1       noro      952: }
                    953: #endif
                    954:
                    955:
1.3       noro      956: /* Needed by SRC_M3, gcj, and should perhaps be the official interface */
                    957: /* to GC_dont_gc.                                                      */
1.1       noro      958: void GC_enable()
                    959: {
                    960:     GC_dont_gc--;
                    961: }
                    962:
                    963: void GC_disable()
                    964: {
                    965:     GC_dont_gc++;
                    966: }
                    967:
                    968: #if !defined(NO_DEBUGGING)
                    969:
                    970: void GC_dump()
                    971: {
                    972:     GC_printf0("***Static roots:\n");
                    973:     GC_print_static_roots();
                    974:     GC_printf0("\n***Heap sections:\n");
                    975:     GC_print_heap_sects();
                    976:     GC_printf0("\n***Free blocks:\n");
                    977:     GC_print_hblkfreelist();
                    978:     GC_printf0("\n***Blocks in use:\n");
                    979:     GC_print_block_list();
                    980: }
                    981:
1.4       noro      982: #endif /* NO_DEBUGGING */

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