123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617 |
- #include "private/gc_priv.h"
- #include "gc_inline.h"
- #include <stdio.h>
- #include <string.h>
- #ifdef MSWINCE
- # ifndef WIN32_LEAN_AND_MEAN
- # define WIN32_LEAN_AND_MEAN 1
- # endif
- # define NOSERVICE
- # include <windows.h>
- #else
- # include <errno.h>
- #endif
- #include "gc_alloc_ptrs.h"
- void ** const GC_objfreelist_ptr = GC_objfreelist;
- void ** const GC_aobjfreelist_ptr = GC_aobjfreelist;
- void ** const GC_uobjfreelist_ptr = GC_uobjfreelist;
- # ifdef GC_ATOMIC_UNCOLLECTABLE
- void ** const GC_auobjfreelist_ptr = GC_auobjfreelist;
- # endif
- GC_API int GC_CALL GC_get_kind_and_size(const void * p, size_t * psize)
- {
- hdr * hhdr = HDR(p);
- if (psize != NULL) {
- *psize = (size_t)hhdr->hb_sz;
- }
- return hhdr -> hb_obj_kind;
- }
- GC_API GC_ATTR_MALLOC void * GC_CALL GC_generic_or_special_malloc(size_t lb,
- int knd)
- {
- switch(knd) {
- case PTRFREE:
- case NORMAL:
- return GC_malloc_kind(lb, knd);
- case UNCOLLECTABLE:
- # ifdef GC_ATOMIC_UNCOLLECTABLE
- case AUNCOLLECTABLE:
- # endif
- return GC_generic_malloc_uncollectable(lb, knd);
- default:
- return GC_generic_malloc(lb, knd);
- }
- }
- GC_API void * GC_CALL GC_realloc(void * p, size_t lb)
- {
- struct hblk * h;
- hdr * hhdr;
- void * result;
- size_t sz;
- size_t orig_sz;
- int obj_kind;
- if (p == 0) return(GC_malloc(lb));
- if (0 == lb) {
- # ifndef IGNORE_FREE
- GC_free(p);
- # endif
- return NULL;
- }
- h = HBLKPTR(p);
- hhdr = HDR(h);
- sz = (size_t)hhdr->hb_sz;
- obj_kind = hhdr -> hb_obj_kind;
- orig_sz = sz;
- if (sz > MAXOBJBYTES) {
-
- word descr = GC_obj_kinds[obj_kind].ok_descriptor;
- sz = (sz + HBLKSIZE-1) & ~HBLKMASK;
- if (GC_obj_kinds[obj_kind].ok_relocate_descr)
- descr += sz;
-
-
-
-
-
-
-
-
-
-
-
-
-
- # ifdef AO_HAVE_store
- GC_STATIC_ASSERT(sizeof(hhdr->hb_sz) == sizeof(AO_t));
- AO_store((volatile AO_t *)&hhdr->hb_sz, (AO_t)sz);
- AO_store((volatile AO_t *)&hhdr->hb_descr, (AO_t)descr);
- # else
- {
- DCL_LOCK_STATE;
- LOCK();
- hhdr -> hb_sz = sz;
- hhdr -> hb_descr = descr;
- UNLOCK();
- }
- # endif
- # ifdef MARK_BIT_PER_OBJ
- GC_ASSERT(hhdr -> hb_inv_sz == LARGE_INV_SZ);
- # endif
- # ifdef MARK_BIT_PER_GRANULE
- GC_ASSERT((hhdr -> hb_flags & LARGE_BLOCK) != 0
- && hhdr -> hb_map[ANY_INDEX] == 1);
- # endif
- if (IS_UNCOLLECTABLE(obj_kind)) GC_non_gc_bytes += (sz - orig_sz);
-
- }
- if (ADD_SLOP(lb) <= sz) {
- if (lb >= (sz >> 1)) {
- if (orig_sz > lb) {
-
-
- BZERO(((ptr_t)p) + lb, orig_sz - lb);
- }
- return(p);
- }
-
- sz = lb;
- }
- result = GC_generic_or_special_malloc((word)lb, obj_kind);
- if (result != NULL) {
-
-
- 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
- # define GC_debug_realloc_replacement(p, lb) \
- GC_debug_realloc(p, lb, GC_DBG_EXTRAS)
- # if !defined(REDIRECT_MALLOC_IN_HEADER)
- void * realloc(void * p, size_t lb)
- {
- return(REDIRECT_REALLOC(p, lb));
- }
- # endif
- # undef GC_debug_realloc_replacement
- # endif
- GC_API GC_ATTR_MALLOC void * GC_CALL
- GC_generic_malloc_ignore_off_page(size_t lb, int k)
- {
- void *result;
- size_t lg;
- size_t lb_rounded;
- word n_blocks;
- GC_bool init;
- DCL_LOCK_STATE;
- if (SMALL_OBJ(lb))
- return GC_generic_malloc(lb, k);
- GC_ASSERT(k < MAXOBJKINDS);
- lg = ROUNDED_UP_GRANULES(lb);
- lb_rounded = GRANULES_TO_BYTES(lg);
- n_blocks = OBJ_SZ_TO_BLOCKS(lb_rounded);
- init = GC_obj_kinds[k].ok_init;
- if (EXPECT(GC_have_errors, FALSE))
- GC_print_all_errors();
- GC_INVOKE_FINALIZERS();
- GC_DBG_COLLECT_AT_MALLOC(lb);
- LOCK();
- result = (ptr_t)GC_alloc_large(ADD_SLOP(lb), k, IGNORE_OFF_PAGE);
- if (NULL == result) {
- GC_oom_func oom_fn = GC_oom_fn;
- UNLOCK();
- return (*oom_fn)(lb);
- }
- if (GC_debugging_started) {
- BZERO(result, n_blocks * HBLKSIZE);
- } else {
- # ifdef THREADS
-
-
- ((word *)result)[0] = 0;
- ((word *)result)[1] = 0;
- ((word *)result)[GRANULES_TO_WORDS(lg)-1] = 0;
- ((word *)result)[GRANULES_TO_WORDS(lg)-2] = 0;
- # endif
- }
- GC_bytes_allocd += lb_rounded;
- UNLOCK();
- if (init && !GC_debugging_started) {
- BZERO(result, n_blocks * HBLKSIZE);
- }
- return(result);
- }
- GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_ignore_off_page(size_t lb)
- {
- return GC_generic_malloc_ignore_off_page(lb, NORMAL);
- }
- GC_API GC_ATTR_MALLOC void * GC_CALL
- GC_malloc_atomic_ignore_off_page(size_t lb)
- {
- return GC_generic_malloc_ignore_off_page(lb, PTRFREE);
- }
- GC_API void GC_CALL GC_incr_bytes_allocd(size_t n)
- {
- GC_bytes_allocd += n;
- }
- GC_API void GC_CALL GC_incr_bytes_freed(size_t n)
- {
- GC_bytes_freed += n;
- }
- GC_API size_t GC_CALL GC_get_expl_freed_bytes_since_gc(void)
- {
- return (size_t)GC_bytes_freed;
- }
- # ifdef PARALLEL_MARK
- STATIC volatile AO_t GC_bytes_allocd_tmp = 0;
-
-
-
-
-
-
-
-
- # endif
- GC_API void GC_CALL GC_generic_malloc_many(size_t lb, int k, void **result)
- {
- void *op;
- void *p;
- void **opp;
- size_t lw;
- size_t lg;
- signed_word my_bytes_allocd = 0;
- struct obj_kind * ok = &(GC_obj_kinds[k]);
- struct hblk ** rlh;
- DCL_LOCK_STATE;
- GC_ASSERT(lb != 0 && (lb & (GRANULE_BYTES-1)) == 0);
- if (!SMALL_OBJ(lb)) {
- op = GC_generic_malloc(lb, k);
- if (EXPECT(0 != op, TRUE))
- obj_link(op) = 0;
- *result = op;
- return;
- }
- GC_ASSERT(k < MAXOBJKINDS);
- lw = BYTES_TO_WORDS(lb);
- lg = BYTES_TO_GRANULES(lb);
- if (EXPECT(GC_have_errors, FALSE))
- GC_print_all_errors();
- GC_INVOKE_FINALIZERS();
- GC_DBG_COLLECT_AT_MALLOC(lb);
- if (!EXPECT(GC_is_initialized, TRUE)) GC_init();
- LOCK();
-
- if (GC_incremental && !GC_dont_gc) {
- ENTER_GC();
- GC_collect_a_little_inner(1);
- EXIT_GC();
- }
-
-
- rlh = ok -> ok_reclaim_list;
- if (rlh != NULL) {
- struct hblk * hbp;
- hdr * hhdr;
- rlh += lg;
- while ((hbp = *rlh) != 0) {
- hhdr = HDR(hbp);
- *rlh = hhdr -> hb_next;
- GC_ASSERT(hhdr -> hb_sz == lb);
- hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no;
- # ifdef PARALLEL_MARK
- if (GC_parallel) {
- signed_word my_bytes_allocd_tmp =
- (signed_word)AO_load(&GC_bytes_allocd_tmp);
- GC_ASSERT(my_bytes_allocd_tmp >= 0);
-
-
-
- if (my_bytes_allocd_tmp != 0) {
- (void)AO_fetch_and_add(&GC_bytes_allocd_tmp,
- (AO_t)(-my_bytes_allocd_tmp));
- GC_bytes_allocd += my_bytes_allocd_tmp;
- }
- GC_acquire_mark_lock();
- ++ GC_fl_builder_count;
- UNLOCK();
- GC_release_mark_lock();
- }
- # endif
- op = GC_reclaim_generic(hbp, hhdr, lb,
- ok -> ok_init, 0, &my_bytes_allocd);
- if (op != 0) {
- # ifdef PARALLEL_MARK
- if (GC_parallel) {
- *result = op;
- (void)AO_fetch_and_add(&GC_bytes_allocd_tmp,
- (AO_t)my_bytes_allocd);
- GC_acquire_mark_lock();
- -- GC_fl_builder_count;
- if (GC_fl_builder_count == 0) GC_notify_all_builder();
- # ifdef THREAD_SANITIZER
- GC_release_mark_lock();
- LOCK();
- GC_bytes_found += my_bytes_allocd;
- UNLOCK();
- # else
- GC_bytes_found += my_bytes_allocd;
-
- GC_release_mark_lock();
- # endif
- (void) GC_clear_stack(0);
- return;
- }
- # endif
-
-
- GC_bytes_found += my_bytes_allocd;
- GC_bytes_allocd += my_bytes_allocd;
- goto out;
- }
- # ifdef PARALLEL_MARK
- if (GC_parallel) {
- GC_acquire_mark_lock();
- -- GC_fl_builder_count;
- if (GC_fl_builder_count == 0) GC_notify_all_builder();
- GC_release_mark_lock();
- LOCK();
-
-
-
- }
- # endif
- }
- }
-
-
-
- opp = &(GC_obj_kinds[k].ok_freelist[lg]);
- if ( (op = *opp) != 0 ) {
- *opp = 0;
- my_bytes_allocd = 0;
- for (p = op; p != 0; p = obj_link(p)) {
- my_bytes_allocd += lb;
- if ((word)my_bytes_allocd >= HBLKSIZE) {
- *opp = obj_link(p);
- obj_link(p) = 0;
- break;
- }
- }
- GC_bytes_allocd += my_bytes_allocd;
- goto out;
- }
-
- {
- struct hblk *h = GC_allochblk(lb, k, 0);
- if (h != 0) {
- if (IS_UNCOLLECTABLE(k)) GC_set_hdr_marks(HDR(h));
- GC_bytes_allocd += HBLKSIZE - HBLKSIZE % lb;
- # ifdef PARALLEL_MARK
- if (GC_parallel) {
- GC_acquire_mark_lock();
- ++ GC_fl_builder_count;
- UNLOCK();
- GC_release_mark_lock();
- op = GC_build_fl(h, lw,
- (ok -> ok_init || GC_debugging_started), 0);
- *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;
- }
- # endif
- op = GC_build_fl(h, lw, (ok -> ok_init || GC_debugging_started), 0);
- goto out;
- }
- }
-
-
- op = GC_generic_malloc_inner(lb, k);
- if (0 != op) obj_link(op) = 0;
- out:
- *result = op;
- UNLOCK();
- (void) GC_clear_stack(0);
- }
- GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_many(size_t lb)
- {
- void *result;
-
- lb = SIZET_SAT_ADD(lb, EXTRA_BYTES + GRANULE_BYTES - 1)
- & ~(GRANULE_BYTES - 1);
- GC_generic_malloc_many(lb, NORMAL, &result);
- return result;
- }
- #include <limits.h>
- GC_API GC_ATTR_MALLOC void * GC_CALL GC_memalign(size_t align, size_t lb)
- {
- size_t new_lb;
- size_t offset;
- ptr_t result;
- if (align <= GRANULE_BYTES) return GC_malloc(lb);
- if (align >= HBLKSIZE/2 || lb >= HBLKSIZE/2) {
- if (align > HBLKSIZE) {
- return (*GC_get_oom_fn())(LONG_MAX-1024);
- }
- return GC_malloc(lb <= HBLKSIZE? HBLKSIZE : lb);
-
- }
-
-
- new_lb = SIZET_SAT_ADD(lb, align - 1);
- result = (ptr_t)GC_malloc(new_lb);
-
-
- offset = (word)result % align;
- if (offset != 0) {
- offset = align - offset;
- if (!GC_all_interior_pointers) {
- GC_STATIC_ASSERT(VALID_OFFSET_SZ <= HBLKSIZE);
- GC_ASSERT(offset < VALID_OFFSET_SZ);
- GC_register_displacement(offset);
- }
- }
- result += offset;
- GC_ASSERT((word)result % align == 0);
- return result;
- }
- GC_API int GC_CALL GC_posix_memalign(void **memptr, size_t align, size_t lb)
- {
-
- size_t align_minus_one = align - 1;
- if (align < sizeof(void *) || (align_minus_one & align) != 0) {
- # ifdef MSWINCE
- return ERROR_INVALID_PARAMETER;
- # else
- return EINVAL;
- # endif
- }
- if ((*memptr = GC_memalign(align, lb)) == NULL) {
- # ifdef MSWINCE
- return ERROR_NOT_ENOUGH_MEMORY;
- # else
- return ENOMEM;
- # endif
- }
- return 0;
- }
- GC_API GC_ATTR_MALLOC char * GC_CALL GC_strdup(const char *s)
- {
- char *copy;
- size_t lb;
- if (s == NULL) return NULL;
- lb = strlen(s) + 1;
- copy = (char *)GC_malloc_atomic(lb);
- if (NULL == copy) {
- # ifndef MSWINCE
- errno = ENOMEM;
- # endif
- return NULL;
- }
- BCOPY(s, copy, lb);
- return copy;
- }
- GC_API GC_ATTR_MALLOC char * GC_CALL GC_strndup(const char *str, size_t size)
- {
- char *copy;
- size_t len = strlen(str);
- if (len > size)
- len = size;
- copy = (char *)GC_malloc_atomic(len + 1);
- if (copy == NULL) {
- # ifndef MSWINCE
- errno = ENOMEM;
- # endif
- return NULL;
- }
- if (EXPECT(len > 0, TRUE))
- BCOPY(str, copy, len);
- copy[len] = '\0';
- return copy;
- }
- #ifdef GC_REQUIRE_WCSDUP
- # include <wchar.h> /* for wcslen() */
- GC_API GC_ATTR_MALLOC wchar_t * GC_CALL GC_wcsdup(const wchar_t *str)
- {
- size_t lb = (wcslen(str) + 1) * sizeof(wchar_t);
- wchar_t *copy = (wchar_t *)GC_malloc_atomic(lb);
- if (copy == NULL) {
- # ifndef MSWINCE
- errno = ENOMEM;
- # endif
- return NULL;
- }
- BCOPY(str, copy, lb);
- return copy;
- }
- #endif
- GC_API void * GC_CALL GC_malloc_stubborn(size_t lb)
- {
- return GC_malloc(lb);
- }
- GC_API void GC_CALL GC_change_stubborn(const void *p GC_ATTR_UNUSED)
- {
-
- }
- GC_API void GC_CALL GC_end_stubborn_change(const void *p)
- {
- GC_dirty(p);
- }
|