diff options
Diffstat (limited to 'misc.c')
-rw-r--r-- | misc.c | 394 |
1 files changed, 89 insertions, 305 deletions
@@ -1,6 +1,6 @@ /* * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers - * Copyright (c) 1991,1992 by Xerox Corporation. All rights reserved. + * Copyright (c) 1991-1993 by Xerox Corporation. All rights reserved. * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -21,14 +21,19 @@ # ifdef THREADS # ifdef PCR -# include "pcr/il/PCR_IL.h" +# include "il/PCR_IL.h" struct PCR_Th_MLRep GC_allocate_ml; # else +# ifdef SRC_M3 + /* Critical section counter is defined in the M3 runtime */ + /* That's all we use. */ +# else --> declare allocator lock here +# endif # endif # endif -struct _GC_arrays GC_arrays = { 0 }; +FAR struct _GC_arrays GC_arrays = { 0 }; /* Initialize GC_obj_kinds properly and standard free lists properly. */ /* This must be done statically since they may be accessed before */ @@ -38,23 +43,33 @@ struct obj_kind GC_obj_kinds[MAXOBJKINDS] = { GC_no_mark_proc, FALSE }, /* NORMAL */ { &GC_objfreelist[0], &GC_reclaim_list[0], GC_normal_mark_proc, TRUE }, +/* UNCOLLECTABLE */ + { &GC_uobjfreelist[0], &GC_ureclaim_list[0], + GC_normal_mark_proc, TRUE }, +# ifdef STUBBORN_ALLOC +/*STUBBORN*/ { &GC_sobjfreelist[0], &GC_sreclaim_list[0], + GC_normal_mark_proc, TRUE }, +# endif }; -ptr_t GC_stackbottom = 0; +# ifdef STUBBORN_ALLOC + int GC_n_kinds = 4; +# else + int GC_n_kinds = 3; +# endif + +bool GC_debugging_started = FALSE; + /* defined here so we don't have to load debug_malloc.o */ -word GC_hincr; +void (*GC_check_heap)() = (void (*)())0; -int GC_n_kinds = 2; +ptr_t GC_stackbottom = 0; bool GC_dont_gc = 0; -extern signed_word GC_mem_found; +bool GC_quiet = 0; -# ifdef ALL_INTERIOR_POINTERS -# define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1)) -# else -# define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1) -# endif +extern signed_word GC_mem_found; # ifdef MERGE_SIZES /* Set things up so that GC_size_map[i] >= words(i), */ @@ -62,11 +77,6 @@ extern signed_word GC_mem_found; /* and so that size_map contains relatively few distinct entries */ /* This is stolen from Russ Atkinson's Cedar quantization */ /* alogrithm (but we precompute it). */ - -# if (CPP_WORDSZ != 32) - --> fix the following code -# endif - void GC_init_size_map() @@ -77,11 +87,11 @@ extern signed_word GC_mem_found; /* Map size 0 to 1. This avoids problems at lower levels. */ GC_size_map[0] = 1; /* One word objects don't have to be 2 word aligned. */ - GC_size_map[1] = 1; - GC_size_map[2] = 1; - GC_size_map[3] = 1; - GC_size_map[4] = ROUNDED_UP_WORDS(4); - for (i = 5; i <= 32; i++) { + for (i = 1; i < sizeof(word); i++) { + GC_size_map[i] = 1; + } + GC_size_map[sizeof(word)] = ROUNDED_UP_WORDS(sizeof(word)); + for (i = sizeof(word) + 1; i <= 8 * sizeof(word); i++) { # ifdef ALIGN_DOUBLE GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1); # else @@ -89,7 +99,7 @@ extern signed_word GC_mem_found; # endif } - for (i = 33; i <= WORDS_TO_BYTES(MAXOBJSZ); i++) { + for (i = 8*sizeof(word)+1; i <= WORDS_TO_BYTES(MAXOBJSZ); i++) { if (sz_rounded_up < ROUNDED_UP_WORDS(i)) { register int size = ROUNDED_UP_WORDS(i); register unsigned m = 0; @@ -109,14 +119,6 @@ extern signed_word GC_mem_found; } # endif -# ifdef ALL_INTERIOR_POINTERS -# define SMALL_OBJ(bytes) ((bytes) < WORDS_TO_BYTES(MAXOBJSZ)) -# define ADD_SLOP(bytes) ((bytes)+1) -# else -# define SMALL_OBJ(bytes) ((bytes) <= WORDS_TO_BYTES(MAXOBJSZ)) -# define ADD_SLOP(bytes) (bytes) -# endif - /* * The following is a gross hack to deal with a problem that can occur * on machines that are sloppy about stack frame sizes, notably SPARC. @@ -191,237 +193,6 @@ void GC_clear_stack() # endif } -/* allocate lb bytes for an object of kind k */ -ptr_t GC_generic_malloc(lb, k) -register word lb; -register int k; -{ -register word lw; -register ptr_t op; -register ptr_t *opp; -DCL_LOCK_STATE; - - DISABLE_SIGNALS(); - LOCK(); - if( SMALL_OBJ(lb) ) { -# ifdef MERGE_SIZES - lw = GC_size_map[lb]; -# else - lw = ROUNDED_UP_WORDS(lb); - if (lw == 0) lw = 1; -# endif - opp = &(GC_obj_kinds[k].ok_freelist[lw]); - if( (op = *opp) == 0 ) { - if (!GC_is_initialized) { - GC_init_inner(); - ENABLE_SIGNALS(); - /* This may have fixed GC_size_map */ - UNLOCK(); - return(GC_generic_malloc(lb, k)); - } - GC_clear_stack(); - op = GC_allocobj(lw, k); - if (op == 0) goto out; - } - /* Here everything is in a consistent state. */ - /* We assume the following assignment is */ - /* atomic. If we get aborted */ - /* after the assignment, we lose an object, */ - /* but that's benign. */ - /* Volatile declarations may need to be added */ - /* to prevent the compiler from breaking things.*/ - *opp = obj_link(op); - obj_link(op) = 0; - } else { - register struct hblk * h; - - if (!GC_is_initialized) GC_init_inner(); - lw = ROUNDED_UP_WORDS(lb); - while ((h = GC_allochblk(lw, k)) == 0) { - GC_collect_or_expand(divHBLKSZ(lb) + 1); - } - if (h == 0) { - op = 0; - } else { - op = (ptr_t) (h -> hb_body); - } - } - GC_words_allocd += lw; - -out: - UNLOCK(); - ENABLE_SIGNALS(); - return((ptr_t)op); -} - -/* Analogous to the above, but assumes a small object size, and */ -/* bypasses MERGE_SIZES mechanism. Used by gc_inline.h. */ -ptr_t GC_generic_malloc_words_small(lw, k) -register word lw; -register int k; -{ -register ptr_t op; -register ptr_t *opp; -DCL_LOCK_STATE; - - LOCK(); - DISABLE_SIGNALS(); - opp = &(GC_obj_kinds[k].ok_freelist[lw]); - if( (op = *opp) == 0 ) { - if (!GC_is_initialized) { - GC_init_inner(); - } - GC_clear_stack(); - op = GC_allocobj(lw, k); - if (op == 0) goto out; - } - *opp = obj_link(op); - obj_link(op) = 0; - GC_words_allocd += lw; - -out: - UNLOCK(); - ENABLE_SIGNALS(); - return((ptr_t)op); -} - -/* Allocate lb bytes of atomic (pointerfree) data */ -# ifdef __STDC__ - extern_ptr_t GC_malloc_atomic(size_t lb) -# else - extern_ptr_t GC_malloc_atomic(lb) - size_t lb; -# endif -{ -register ptr_t op; -register ptr_t * opp; -register word lw; -DCL_LOCK_STATE; - - if( SMALL_OBJ(lb) ) { -# ifdef MERGE_SIZES - lw = GC_size_map[lb]; -# else - lw = ROUNDED_UP_WORDS(lb); -# endif - opp = &(GC_aobjfreelist[lw]); - FASTLOCK(); - if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) { - FASTUNLOCK(); - return(GC_generic_malloc((word)lb, PTRFREE)); - } - /* See above comment on signals. */ - *opp = obj_link(op); - GC_words_allocd += lw; - FASTUNLOCK(); - return((extern_ptr_t) op); - } else { - return((extern_ptr_t) - GC_generic_malloc((word)lb, PTRFREE)); - } -} - -/* Allocate lb bytes of composite (pointerful) data */ -# ifdef __STDC__ - extern_ptr_t GC_malloc(size_t lb) -# else - extern_ptr_t GC_malloc(lb) - size_t lb; -# endif -{ -register ptr_t op; -register ptr_t *opp; -register word lw; -DCL_LOCK_STATE; - - if( SMALL_OBJ(lb) ) { -# ifdef MERGE_SIZES - lw = GC_size_map[lb]; -# else - lw = ROUNDED_UP_WORDS(lb); -# endif - opp = &(GC_objfreelist[lw]); - FASTLOCK(); - if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) { - FASTUNLOCK(); - return(GC_generic_malloc((word)lb, NORMAL)); - } - /* See above comment on signals. */ - *opp = obj_link(op); - obj_link(op) = 0; - GC_words_allocd += lw; - FASTUNLOCK(); - return((extern_ptr_t) op); - } else { - return((extern_ptr_t) - GC_generic_malloc((word)lb, NORMAL)); - } -} - -/* Change the size of the block pointed to by p to contain at least */ -/* lb bytes. The object may be (and quite likely will be) moved. */ -/* The kind (e.g. atomic) is the same as that of the old. */ -/* Shrinking of large blocks is not implemented well. */ -# ifdef __STDC__ - extern_ptr_t GC_realloc(extern_ptr_t p, size_t lb) -# else - extern_ptr_t GC_realloc(p,lb) - extern_ptr_t p; - size_t lb; -# endif -{ -register struct hblk * h; -register hdr * hhdr; -register signed_word sz; /* Current size in bytes */ -register word orig_sz; /* Original sz in bytes */ -int obj_kind; - - if (p == 0) return(GC_malloc(lb)); /* Required by ANSI */ - h = HBLKPTR(p); - hhdr = HDR(h); - sz = hhdr -> hb_sz; - obj_kind = hhdr -> hb_obj_kind; - sz = WORDS_TO_BYTES(sz); - orig_sz = sz; - - if (sz > WORDS_TO_BYTES(MAXOBJSZ)) { - /* Round it up to the next whole heap block */ - - sz = (sz+HDR_BYTES+HBLKSIZE-1) - & (~HBLKMASK); - sz -= HDR_BYTES; - hhdr -> hb_sz = BYTES_TO_WORDS(sz); - /* Extra area is already cleared by allochblk. */ - } - if (ADD_SLOP(lb) <= sz) { - if (lb >= (sz >> 1)) { - if (orig_sz > lb) { - /* Clear unneeded part of object to avoid bogus pointer */ - /* tracing. */ - bzero(((char *)p) + lb, (int)(orig_sz - lb)); - } - return(p); - } else { - /* shrink */ - extern_ptr_t result = GC_generic_malloc((word)lb, obj_kind); - - if (result == 0) return(0); - /* Could also return original object. But this */ - /* gives the client warning of imminent disaster. */ - bcopy(p, result, (int)lb); - GC_free(p); - return(result); - } - } else { - /* grow */ - extern_ptr_t result = GC_generic_malloc((word)lb, obj_kind); - - if (result == 0) return(0); - bcopy(p, result, (int)sz); - GC_free(p); - return(result); - } -} /* Return a pointer to the base address of p, given a pointer to a */ /* an address within an object. Return 0 o.w. */ @@ -459,7 +230,7 @@ int obj_kind; correction = offset % sz; r -= (WORDS_TO_BYTES(correction)); if (((word *)r + sz) > (word *)(h + 1) - && sz <= MAXOBJSZ) { + && sz <= BYTES_TO_WORDS(HBLKSIZE) - HDR_WORDS) { return(0); } } @@ -487,41 +258,6 @@ int obj_kind; } } -/* Explicitly deallocate an object p. */ -# ifdef __STDC__ - void GC_free(extern_ptr_t p) -# else - void GC_free(p) - extern_ptr_t p; -# endif -{ - register struct hblk *h; - register hdr *hhdr; - register signed_word sz; - register ptr_t * flh; - register struct obj_kind * ok; - - if (p == 0) return; - /* Required by ANSI. It's not my fault ... */ - h = HBLKPTR(p); - hhdr = HDR(h); - sz = hhdr -> hb_sz; - GC_mem_freed += sz; - ok = &GC_obj_kinds[hhdr -> hb_obj_kind]; - - if (sz > MAXOBJSZ) { - GC_freehblk(h); - } else { - ok = &GC_obj_kinds[hhdr -> hb_obj_kind]; - if (ok -> ok_init) { - bzero((char *)((word *)p + 1), (int)(WORDS_TO_BYTES(sz-1))); - } - flh = &(ok -> ok_freelist[sz]); - obj_link(p) = *flh; - *flh = (ptr_t)p; - } -} - bool GC_is_initialized = FALSE; void GC_init() @@ -604,14 +340,19 @@ void GC_init_inner() ABORT("signed_word"); } - GC_hincr = HINCR; GC_init_headers(); GC_bl_init(); GC_mark_init(); - if (!GC_expand_hp_inner(GC_hincr)) { - GC_printf0("Can't start up: no memory\n"); + if (!GC_expand_hp_inner((word)MINHINCR)) { + GC_err_printf0("Can't start up: not enough memory\n"); EXIT(); } + /* Preallocate large object map. It's otherwise inconvenient to */ + /* deal with failure. */ + if (!GC_add_map_entry((word)0)) { + GC_err_printf0("Can't start up: not enough memory\n"); + EXIT(); + } GC_register_displacement_inner(0L); # ifdef MERGE_SIZES GC_init_size_map(); @@ -624,14 +365,45 @@ void GC_init_inner() GC_pcr_install(); # endif /* Get black list set up */ - (void)GC_gcollect_inner(TRUE); - (void)GC_gcollect_inner(TRUE); + GC_gcollect_inner(); +# ifdef STUBBORN_ALLOC + GC_stubborn_init(); +# endif /* Convince lint that some things are used */ +# ifdef LINT { extern char * GC_copyright[]; - GC_noop(GC_copyright, GC_find_header, - GC_tl_mark, GC_call_with_alloc_lock); + extern GC_read(); + + GC_noop(GC_copyright, GC_find_header, GC_print_block_list, + GC_push_one, GC_call_with_alloc_lock, GC_read, + GC_print_hblkfreelist, GC_dont_expand); } +# endif +} + +void GC_enable_incremental() +{ + DCL_LOCK_STATE; + +# ifndef FIND_LEAK + DISABLE_SIGNALS(); + LOCK(); + if (!GC_is_initialized) { + GC_init_inner(); + } + if (GC_words_allocd > 0) { + /* There may be unmarked reachable objects */ + GC_gcollect_inner(); + } /* else we're OK in assumeing everything's */ + /* clean since nothing can point to an */ + /* unmarked object. */ + GC_dirty_init(); + GC_read_dirty(); + GC_incremental = TRUE; + UNLOCK(); + ENABLE_SIGNALS(); +# endif } /* A version of printf that is unlikely to call malloc, and is thus safer */ @@ -646,6 +418,7 @@ long a, b, c, d, e, f; { char buf[1025]; + if (GC_quiet) return; buf[1024] = 0x15; (void) sprintf(buf, format, a, b, c, d, e, f); if (buf[1024] != 0x15) ABORT("GC_printf clobbered stack"); @@ -688,3 +461,14 @@ char *s; # endif } +# ifdef SRC_M3 +void GC_enable() +{ + GC_dont_gc--; +} + +void GC_disable() +{ + GC_dont_gc++; +} +# endif |