123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696 |
- /*
- * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
- * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
- * Copyright (c) 1996 by Silicon Graphics. All rights reserved.
- * Copyright (c) 2000 by Hewlett-Packard Company. All rights reserved.
- *
- * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
- * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
- *
- * Permission is hereby granted to use or copy this program
- * for any purpose, provided the above notices are retained on all copies.
- * Permission to modify the code and to distribute modified code is granted,
- * provided the above notices are retained, and a notice that the code was
- * modified is included with the above copyright notice.
- */
- /*
- * These are extra allocation routines which are likely to be less
- * frequently used than those in malloc.c. They are separate in the
- * hope that the .o file will be excluded from statically linked
- * executables. We should probably break this up further.
- */
- #include <stdio.h>
- #include "private/gc_priv.h"
- extern ptr_t GC_clear_stack(); /* in misc.c, behaves like identity */
- void GC_extend_size_map(); /* in misc.c. */
- GC_bool GC_alloc_reclaim_list(); /* in malloc.c */
- /* Some externally visible but unadvertised variables to allow access to */
- /* free lists from inlined allocators without including gc_priv.h */
- /* or introducing dependencies on internal data structure layouts. */
- ptr_t * GC_CONST GC_objfreelist_ptr = GC_objfreelist;
- ptr_t * GC_CONST GC_aobjfreelist_ptr = GC_aobjfreelist;
- ptr_t * GC_CONST GC_uobjfreelist_ptr = GC_uobjfreelist;
- # ifdef ATOMIC_UNCOLLECTABLE
- ptr_t * GC_CONST GC_auobjfreelist_ptr = GC_auobjfreelist;
- # endif
- GC_PTR GC_generic_or_special_malloc(lb,knd)
- word lb;
- int knd;
- {
- switch(knd) {
- # ifdef STUBBORN_ALLOC
- case STUBBORN:
- return(GC_malloc_stubborn((size_t)lb));
- # endif
- case PTRFREE:
- return(GC_malloc_atomic((size_t)lb));
- case NORMAL:
- return(GC_malloc((size_t)lb));
- case UNCOLLECTABLE:
- return(GC_malloc_uncollectable((size_t)lb));
- # ifdef ATOMIC_UNCOLLECTABLE
- case AUNCOLLECTABLE:
- return(GC_malloc_atomic_uncollectable((size_t)lb));
- # endif /* ATOMIC_UNCOLLECTABLE */
- default:
- return(GC_generic_malloc(lb,knd));
- }
- }
- /* 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__
- GC_PTR GC_realloc(GC_PTR p, size_t lb)
- # else
- GC_PTR GC_realloc(p,lb)
- GC_PTR p;
- size_t lb;
- # endif
- {
- register struct hblk * h;
- register hdr * hhdr;
- register 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 > MAXOBJBYTES) {
- /* Round it up to the next whole heap block */
- register word descr;
-
- sz = (sz+HBLKSIZE-1) & (~HBLKMASK);
- hhdr -> hb_sz = BYTES_TO_WORDS(sz);
- descr = GC_obj_kinds[obj_kind].ok_descriptor;
- if (GC_obj_kinds[obj_kind].ok_relocate_descr) descr += sz;
- hhdr -> hb_descr = descr;
- if (IS_UNCOLLECTABLE(obj_kind)) GC_non_gc_bytes += (sz - orig_sz);
- /* Extra area is already cleared by GC_alloc_large_and_clear. */
- }
- if (ADD_SLOP(lb) <= sz) {
- if (lb >= (sz >> 1)) {
- # ifdef STUBBORN_ALLOC
- if (obj_kind == STUBBORN) GC_change_stubborn(p);
- # endif
- if (orig_sz > lb) {
- /* Clear unneeded part of object to avoid bogus pointer */
- /* tracing. */
- /* Safe for stubborn objects. */
- BZERO(((ptr_t)p) + lb, orig_sz - lb);
- }
- return(p);
- } else {
- /* shrink */
- GC_PTR result =
- GC_generic_or_special_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, lb);
- # ifndef IGNORE_FREE
- GC_free(p);
- # endif
- return(result);
- }
- } else {
- /* grow */
- GC_PTR result =
- GC_generic_or_special_malloc((word)lb, obj_kind);
- if (result == 0) return(0);
- BCOPY(p, result, sz);
- # ifndef IGNORE_FREE
- GC_free(p);
- # endif
- return(result);
- }
- }
- # if defined(REDIRECT_MALLOC) && !defined(REDIRECT_REALLOC)
- # define REDIRECT_REALLOC GC_realloc
- # endif
- # ifdef REDIRECT_REALLOC
- /* As with malloc, avoid two levels of extra calls here. */
- # ifdef GC_ADD_CALLER
- # define RA GC_RETURN_ADDR,
- # else
- # define RA
- # endif
- # define GC_debug_realloc_replacement(p, lb) \
- GC_debug_realloc(p, lb, RA "unknown", 0)
- # ifdef __STDC__
- GC_PTR realloc(GC_PTR p, size_t lb)
- # else
- GC_PTR realloc(p,lb)
- GC_PTR p;
- size_t lb;
- # endif
- {
- return(REDIRECT_REALLOC(p, lb));
- }
- # undef GC_debug_realloc_replacement
- # endif /* REDIRECT_REALLOC */
- /* Allocate memory such that only pointers to near the */
- /* beginning of the object are considered. */
- /* We avoid holding allocation lock while we clear memory. */
- ptr_t GC_generic_malloc_ignore_off_page(lb, k)
- register size_t lb;
- register int k;
- {
- register ptr_t result;
- word lw;
- word n_blocks;
- GC_bool init;
- DCL_LOCK_STATE;
-
- if (SMALL_OBJ(lb))
- return(GC_generic_malloc((word)lb, k));
- lw = ROUNDED_UP_WORDS(lb);
- n_blocks = OBJ_SZ_TO_BLOCKS(lw);
- init = GC_obj_kinds[k].ok_init;
- if (GC_have_errors) GC_print_all_errors();
- GC_INVOKE_FINALIZERS();
- DISABLE_SIGNALS();
- LOCK();
- result = (ptr_t)GC_alloc_large(lw, k, IGNORE_OFF_PAGE);
- if (0 != result) {
- if (GC_debugging_started) {
- BZERO(result, n_blocks * HBLKSIZE);
- } else {
- # ifdef THREADS
- /* Clear any memory that might be used for GC descriptors */
- /* before we release the lock. */
- ((word *)result)[0] = 0;
- ((word *)result)[1] = 0;
- ((word *)result)[lw-1] = 0;
- ((word *)result)[lw-2] = 0;
- # endif
- }
- }
- GC_words_allocd += lw;
- UNLOCK();
- ENABLE_SIGNALS();
- if (0 == result) {
- return((*GC_oom_fn)(lb));
- } else {
- if (init && !GC_debugging_started) {
- BZERO(result, n_blocks * HBLKSIZE);
- }
- return(result);
- }
- }
- # if defined(__STDC__) || defined(__cplusplus)
- void * GC_malloc_ignore_off_page(size_t lb)
- # else
- char * GC_malloc_ignore_off_page(lb)
- register size_t lb;
- # endif
- {
- return((GC_PTR)GC_generic_malloc_ignore_off_page(lb, NORMAL));
- }
- # if defined(__STDC__) || defined(__cplusplus)
- void * GC_malloc_atomic_ignore_off_page(size_t lb)
- # else
- char * GC_malloc_atomic_ignore_off_page(lb)
- register size_t lb;
- # endif
- {
- return((GC_PTR)GC_generic_malloc_ignore_off_page(lb, PTRFREE));
- }
- /* Increment GC_words_allocd from code that doesn't have direct access */
- /* to GC_arrays. */
- # ifdef __STDC__
- void GC_incr_words_allocd(size_t n)
- {
- GC_words_allocd += n;
- }
- /* The same for GC_mem_freed. */
- void GC_incr_mem_freed(size_t n)
- {
- GC_mem_freed += n;
- }
- # endif /* __STDC__ */
- /* 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_inner(lw, k)
- register word lw;
- register int k;
- {
- register ptr_t op;
- register ptr_t *opp;
- register struct obj_kind * kind = GC_obj_kinds + k;
- opp = &(kind -> ok_freelist[lw]);
- if( (op = *opp) == 0 ) {
- if (!GC_is_initialized) {
- GC_init_inner();
- }
- if (kind -> ok_reclaim_list != 0 || GC_alloc_reclaim_list(kind)) {
- op = GC_clear_stack(GC_allocobj((word)lw, k));
- }
- if (op == 0) {
- UNLOCK();
- ENABLE_SIGNALS();
- return ((*GC_oom_fn)(WORDS_TO_BYTES(lw)));
- }
- }
- *opp = obj_link(op);
- obj_link(op) = 0;
- GC_words_allocd += lw;
- return((ptr_t)op);
- }
- /* Analogous to the above, but assumes a small object size, and */
- /* bypasses MERGE_SIZES mechanism. Used by gc_inline.h. */
- #ifdef __STDC__
- ptr_t GC_generic_malloc_words_small(size_t lw, int k)
- #else
- ptr_t GC_generic_malloc_words_small(lw, k)
- register word lw;
- register int k;
- #endif
- {
- register ptr_t op;
- DCL_LOCK_STATE;
- if (GC_have_errors) GC_print_all_errors();
- GC_INVOKE_FINALIZERS();
- DISABLE_SIGNALS();
- LOCK();
- op = GC_generic_malloc_words_small_inner(lw, k);
- UNLOCK();
- ENABLE_SIGNALS();
- return((ptr_t)op);
- }
- #if defined(THREADS) && !defined(SRC_M3)
- extern signed_word GC_mem_found; /* Protected by GC lock. */
- #ifdef PARALLEL_MARK
- volatile signed_word GC_words_allocd_tmp = 0;
- /* Number of words of memory allocated since */
- /* we released the GC lock. Instead of */
- /* reacquiring the GC lock just to add this in, */
- /* we add it in the next time we reacquire */
- /* the lock. (Atomically adding it doesn't */
- /* work, since we would have to atomically */
- /* update it in GC_malloc, which is too */
- /* expensive. */
- #endif /* PARALLEL_MARK */
- /* See reclaim.c: */
- extern ptr_t GC_reclaim_generic();
- /* Return a list of 1 or more objects of the indicated size, linked */
- /* through the first word in the object. This has the advantage that */
- /* it acquires the allocation lock only once, and may greatly reduce */
- /* time wasted contending for the allocation lock. Typical usage would */
- /* be in a thread that requires many items of the same size. It would */
- /* keep its own free list in thread-local storage, and call */
- /* GC_malloc_many or friends to replenish it. (We do not round up */
- /* object sizes, since a call indicates the intention to consume many */
- /* objects of exactly this size.) */
- /* We return the free-list by assigning it to *result, since it is */
- /* not safe to return, e.g. a linked list of pointer-free objects, */
- /* since the collector would not retain the entire list if it were */
- /* invoked just as we were returning. */
- /* Note that the client should usually clear the link field. */
- void GC_generic_malloc_many(lb, k, result)
- register word lb;
- register int k;
- ptr_t *result;
- {
- ptr_t op;
- ptr_t p;
- ptr_t *opp;
- word lw;
- word my_words_allocd = 0;
- struct obj_kind * ok = &(GC_obj_kinds[k]);
- DCL_LOCK_STATE;
- # if defined(GATHERSTATS) || defined(PARALLEL_MARK)
- # define COUNT_ARG , &my_words_allocd
- # else
- # define COUNT_ARG
- # define NEED_TO_COUNT
- # endif
- if (!SMALL_OBJ(lb)) {
- op = GC_generic_malloc(lb, k);
- if(0 != op) obj_link(op) = 0;
- *result = op;
- return;
- }
- lw = ALIGNED_WORDS(lb);
- if (GC_have_errors) GC_print_all_errors();
- GC_INVOKE_FINALIZERS();
- DISABLE_SIGNALS();
- LOCK();
- if (!GC_is_initialized) GC_init_inner();
- /* Do our share of marking work */
- if (GC_incremental && !GC_dont_gc) {
- ENTER_GC();
- GC_collect_a_little_inner(1);
- EXIT_GC();
- }
- /* First see if we can reclaim a page of objects waiting to be */
- /* reclaimed. */
- {
- struct hblk ** rlh = ok -> ok_reclaim_list;
- struct hblk * hbp;
- hdr * hhdr;
- rlh += lw;
- while ((hbp = *rlh) != 0) {
- hhdr = HDR(hbp);
- *rlh = hhdr -> hb_next;
- hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no;
- # ifdef PARALLEL_MARK
- {
- signed_word my_words_allocd_tmp = GC_words_allocd_tmp;
- GC_ASSERT(my_words_allocd_tmp >= 0);
- /* We only decrement it while holding the GC lock. */
- /* Thus we can't accidentally adjust it down in more */
- /* than one thread simultaneously. */
- if (my_words_allocd_tmp != 0) {
- (void)GC_atomic_add(
- (volatile GC_word *)(&GC_words_allocd_tmp),
- (GC_word)(-my_words_allocd_tmp));
- GC_words_allocd += my_words_allocd_tmp;
- }
- }
- GC_acquire_mark_lock();
- ++ GC_fl_builder_count;
- UNLOCK();
- ENABLE_SIGNALS();
- GC_release_mark_lock();
- # endif
- op = GC_reclaim_generic(hbp, hhdr, lw,
- ok -> ok_init, 0 COUNT_ARG);
- if (op != 0) {
- # ifdef NEED_TO_COUNT
- /* We are neither gathering statistics, nor marking in */
- /* parallel. Thus GC_reclaim_generic doesn't count */
- /* for us. */
- for (p = op; p != 0; p = obj_link(p)) {
- my_words_allocd += lw;
- }
- # endif
- # if defined(GATHERSTATS)
- /* We also reclaimed memory, so we need to adjust */
- /* that count. */
- /* This should be atomic, so the results may be */
- /* inaccurate. */
- GC_mem_found += my_words_allocd;
- # endif
- # ifdef PARALLEL_MARK
- *result = op;
- (void)GC_atomic_add(
- (volatile GC_word *)(&GC_words_allocd_tmp),
- (GC_word)(my_words_allocd));
- GC_acquire_mark_lock();
- -- GC_fl_builder_count;
- if (GC_fl_builder_count == 0) GC_notify_all_builder();
- GC_release_mark_lock();
- (void) GC_clear_stack(0);
- return;
- # else
- GC_words_allocd += my_words_allocd;
- goto out;
- # endif
- }
- # ifdef PARALLEL_MARK
- GC_acquire_mark_lock();
- -- GC_fl_builder_count;
- if (GC_fl_builder_count == 0) GC_notify_all_builder();
- GC_release_mark_lock();
- DISABLE_SIGNALS();
- LOCK();
- /* GC lock is needed for reclaim list access. We */
- /* must decrement fl_builder_count before reaquiring GC */
- /* lock. Hopefully this path is rare. */
- # endif
- }
- }
- /* Next try to use prefix of global free list if there is one. */
- /* We don't refill it, but we need to use it up before allocating */
- /* a new block ourselves. */
- opp = &(GC_obj_kinds[k].ok_freelist[lw]);
- if ( (op = *opp) != 0 ) {
- *opp = 0;
- my_words_allocd = 0;
- for (p = op; p != 0; p = obj_link(p)) {
- my_words_allocd += lw;
- if (my_words_allocd >= BODY_SZ) {
- *opp = obj_link(p);
- obj_link(p) = 0;
- break;
- }
- }
- GC_words_allocd += my_words_allocd;
- goto out;
- }
- /* Next try to allocate a new block worth of objects of this size. */
- {
- struct hblk *h = GC_allochblk(lw, k, 0);
- if (h != 0) {
- if (IS_UNCOLLECTABLE(k)) GC_set_hdr_marks(HDR(h));
- GC_words_allocd += BYTES_TO_WORDS(HBLKSIZE)
- - BYTES_TO_WORDS(HBLKSIZE) % lw;
- # ifdef PARALLEL_MARK
- GC_acquire_mark_lock();
- ++ GC_fl_builder_count;
- UNLOCK();
- ENABLE_SIGNALS();
- GC_release_mark_lock();
- # endif
- op = GC_build_fl(h, lw, ok -> ok_init, 0);
- # ifdef PARALLEL_MARK
- *result = op;
- GC_acquire_mark_lock();
- -- GC_fl_builder_count;
- if (GC_fl_builder_count == 0) GC_notify_all_builder();
- GC_release_mark_lock();
- (void) GC_clear_stack(0);
- return;
- # else
- goto out;
- # endif
- }
- }
-
- /* As a last attempt, try allocating a single object. Note that */
- /* this may trigger a collection or expand the heap. */
- op = GC_generic_malloc_inner(lb, k);
- if (0 != op) obj_link(op) = 0;
-
- out:
- *result = op;
- UNLOCK();
- ENABLE_SIGNALS();
- (void) GC_clear_stack(0);
- }
- GC_PTR GC_malloc_many(size_t lb)
- {
- ptr_t result;
- GC_generic_malloc_many(lb, NORMAL, &result);
- return result;
- }
- /* Note that the "atomic" version of this would be unsafe, since the */
- /* links would not be seen by the collector. */
- # endif
- /* Allocate lb bytes of pointerful, traced, but not collectable data */
- # ifdef __STDC__
- GC_PTR GC_malloc_uncollectable(size_t lb)
- # else
- GC_PTR GC_malloc_uncollectable(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
- if (EXTRA_BYTES != 0 && lb != 0) lb--;
- /* We don't need the extra byte, since this won't be */
- /* collected anyway. */
- lw = GC_size_map[lb];
- # else
- lw = ALIGNED_WORDS(lb);
- # endif
- opp = &(GC_uobjfreelist[lw]);
- FASTLOCK();
- if( FASTLOCK_SUCCEEDED() && (op = *opp) != 0 ) {
- /* See above comment on signals. */
- *opp = obj_link(op);
- obj_link(op) = 0;
- GC_words_allocd += lw;
- /* Mark bit ws already set on free list. It will be */
- /* cleared only temporarily during a collection, as a */
- /* result of the normal free list mark bit clearing. */
- GC_non_gc_bytes += WORDS_TO_BYTES(lw);
- FASTUNLOCK();
- return((GC_PTR) op);
- }
- FASTUNLOCK();
- op = (ptr_t)GC_generic_malloc((word)lb, UNCOLLECTABLE);
- } else {
- op = (ptr_t)GC_generic_malloc((word)lb, UNCOLLECTABLE);
- }
- if (0 == op) return(0);
- /* We don't need the lock here, since we have an undisguised */
- /* pointer. We do need to hold the lock while we adjust */
- /* mark bits. */
- {
- register struct hblk * h;
-
- h = HBLKPTR(op);
- lw = HDR(h) -> hb_sz;
-
- DISABLE_SIGNALS();
- LOCK();
- GC_set_mark_bit(op);
- GC_non_gc_bytes += WORDS_TO_BYTES(lw);
- UNLOCK();
- ENABLE_SIGNALS();
- return((GC_PTR) op);
- }
- }
- #ifdef __STDC__
- /* Not well tested nor integrated. */
- /* Debug version is tricky and currently missing. */
- #include <limits.h>
- GC_PTR GC_memalign(size_t align, size_t lb)
- {
- size_t new_lb;
- size_t offset;
- ptr_t result;
- # ifdef ALIGN_DOUBLE
- if (align <= WORDS_TO_BYTES(2) && lb > align) return GC_malloc(lb);
- # endif
- if (align <= WORDS_TO_BYTES(1)) return GC_malloc(lb);
- if (align >= HBLKSIZE/2 || lb >= HBLKSIZE/2) {
- if (align > HBLKSIZE) return GC_oom_fn(LONG_MAX-1024) /* Fail */;
- return GC_malloc(lb <= HBLKSIZE? HBLKSIZE : lb);
- /* Will be HBLKSIZE aligned. */
- }
- /* We could also try to make sure that the real rounded-up object size */
- /* is a multiple of align. That would be correct up to HBLKSIZE. */
- new_lb = lb + align - 1;
- result = GC_malloc(new_lb);
- offset = (word)result % align;
- if (offset != 0) {
- offset = align - offset;
- if (!GC_all_interior_pointers) {
- if (offset >= VALID_OFFSET_SZ) return GC_malloc(HBLKSIZE);
- GC_register_displacement(offset);
- }
- }
- result = (GC_PTR) ((ptr_t)result + offset);
- GC_ASSERT((word)result % align == 0);
- return result;
- }
- #endif
- # ifdef ATOMIC_UNCOLLECTABLE
- /* Allocate lb bytes of pointerfree, untraced, uncollectable data */
- /* This is normally roughly equivalent to the system malloc. */
- /* But it may be useful if malloc is redefined. */
- # ifdef __STDC__
- GC_PTR GC_malloc_atomic_uncollectable(size_t lb)
- # else
- GC_PTR GC_malloc_atomic_uncollectable(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
- if (EXTRA_BYTES != 0 && lb != 0) lb--;
- /* We don't need the extra byte, since this won't be */
- /* collected anyway. */
- lw = GC_size_map[lb];
- # else
- lw = ALIGNED_WORDS(lb);
- # endif
- opp = &(GC_auobjfreelist[lw]);
- FASTLOCK();
- if( FASTLOCK_SUCCEEDED() && (op = *opp) != 0 ) {
- /* See above comment on signals. */
- *opp = obj_link(op);
- obj_link(op) = 0;
- GC_words_allocd += lw;
- /* Mark bit was already set while object was on free list. */
- GC_non_gc_bytes += WORDS_TO_BYTES(lw);
- FASTUNLOCK();
- return((GC_PTR) op);
- }
- FASTUNLOCK();
- op = (ptr_t)GC_generic_malloc((word)lb, AUNCOLLECTABLE);
- } else {
- op = (ptr_t)GC_generic_malloc((word)lb, AUNCOLLECTABLE);
- }
- if (0 == op) return(0);
- /* We don't need the lock here, since we have an undisguised */
- /* pointer. We do need to hold the lock while we adjust */
- /* mark bits. */
- {
- register struct hblk * h;
-
- h = HBLKPTR(op);
- lw = HDR(h) -> hb_sz;
-
- DISABLE_SIGNALS();
- LOCK();
- GC_set_mark_bit(op);
- GC_non_gc_bytes += WORDS_TO_BYTES(lw);
- UNLOCK();
- ENABLE_SIGNALS();
- return((GC_PTR) op);
- }
- }
- #endif /* ATOMIC_UNCOLLECTABLE */
|