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

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

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