diff options
-rw-r--r-- | dbg_mlc.c | 40 | ||||
-rw-r--r-- | include/gc_mark.h | 24 | ||||
-rw-r--r-- | mallocx.c | 11 | ||||
-rw-r--r-- | tests/test.c | 22 |
4 files changed, 96 insertions, 1 deletions
@@ -565,6 +565,23 @@ GC_API void * GC_CALL GC_debug_malloc_atomic_ignore_off_page(size_t lb, return (GC_store_debug_info(result, (word)lb, s, i)); } +STATIC void * GC_debug_generic_malloc(size_t lb, int knd, GC_EXTRA_PARAMS) +{ + void * result = GC_generic_malloc(lb + DEBUG_BYTES, knd); + + if (NULL == result) { + GC_err_printf( + "GC_debug_generic_malloc(%lu, %d) returning NULL (%s:%d)\n", + (unsigned long)lb, knd, s, i); + return NULL; + } + if (!GC_debugging_started) { + GC_start_debugging(); + } + ADD_CALL_CHAIN(result, ra); + return GC_store_debug_info(result, (word)lb, s, i); +} + #ifdef DBG_HDRS_ALL /* An allocation function for internal use. Normally internally */ /* allocated objects do not have debug information. But in this */ @@ -924,6 +941,29 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) return(result); } +GC_API void * GC_CALL GC_debug_generic_or_special_malloc(size_t lb, int knd, + GC_EXTRA_PARAMS) +{ + switch (knd) { +# ifdef STUBBORN_ALLOC + case STUBBORN: + return GC_debug_malloc_stubborn(lb, OPT_RA s, i); +# endif + case PTRFREE: + return GC_debug_malloc_atomic(lb, OPT_RA s, i); + case NORMAL: + return GC_debug_malloc(lb, OPT_RA s, i); + case UNCOLLECTABLE: + return GC_debug_malloc_uncollectable(lb, OPT_RA s, i); +# ifdef ATOMIC_UNCOLLECTABLE + case AUNCOLLECTABLE: + return GC_debug_malloc_atomic_uncollectable(lb, OPT_RA s, i); +# endif + default: + return GC_debug_generic_malloc(lb, knd, OPT_RA s, i); + } +} + #ifndef SHORT_DBG_HDRS /* List of smashed (clobbered) locations. We defer printing these, */ diff --git a/include/gc_mark.h b/include/gc_mark.h index 56bee583..dcadf42e 100644 --- a/include/gc_mark.h +++ b/include/gc_mark.h @@ -204,6 +204,30 @@ GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL /* first page of the resulting object */ /* are ignored. */ +/* Same as above but primary for allocating an object of the same kind */ +/* as an existing one (kind obtained by GC_get_kind_and_size). */ +/* Not suitable for GCJ and typed-malloc kinds. */ +GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL + GC_generic_or_special_malloc( + size_t /* size */, int /* knd */); +GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL + GC_debug_generic_or_special_malloc( + size_t /* size */, int /* knd */, + GC_EXTRA_PARAMS); + +#ifdef GC_DEBUG +# define GC_GENERIC_OR_SPECIAL_MALLOC(sz, knd) \ + GC_debug_generic_or_special_malloc(sz, knd, GC_EXTRAS) +#else +# define GC_GENERIC_OR_SPECIAL_MALLOC(sz, knd) \ + GC_generic_or_special_malloc(sz, knd) +#endif /* !GC_DEBUG */ + +/* Similar to GC_size but returns object kind. Size is returned too */ +/* if psize is not NULL. */ +GC_API int GC_CALL GC_get_kind_and_size(const void *, size_t * /* psize */) + GC_ATTR_NONNULL(1); + typedef void (GC_CALLBACK * GC_describe_type_fn)(void * /* p */, char * /* out_buf */); /* A procedure which */ @@ -46,8 +46,17 @@ void ** const GC_uobjfreelist_ptr = GC_uobjfreelist; 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 = hhdr -> hb_sz; + } + return hhdr -> hb_obj_kind; +} -STATIC void * GC_generic_or_special_malloc(size_t lb, int knd) +GC_API void * GC_CALL GC_generic_or_special_malloc(size_t lb, int knd) { switch(knd) { # ifdef STUBBORN_ALLOC diff --git a/tests/test.c b/tests/test.c index 34c6307b..6f412c8f 100644 --- a/tests/test.c +++ b/tests/test.c @@ -548,6 +548,25 @@ void check_marks_int_list(sexpr x) #endif +void test_generic_malloc_or_special(void *p) { + size_t size; + int kind = GC_get_kind_and_size(p, &size); + void *p2; + + if (size != GC_size(p)) { + GC_printf("GC_get_kind_and_size returned size not matching GC_size\n"); + FAIL; + } + p2 = GC_GENERIC_OR_SPECIAL_MALLOC(10, kind); + CHECK_OUT_OF_MEMORY(p2); + if (GC_get_kind_and_size(p2, NULL) != kind) { + GC_printf("GC_generic_or_special_malloc:" + " unexpected kind of returned object\n"); + FAIL; + } + GC_FREE(p2); +} + /* Try to force a to be strangely aligned */ struct { char dummy; @@ -596,6 +615,7 @@ void *GC_CALLBACK reverse_test_inner(void *data) b = ints(1, 50); c = ints(1, BIG); d = uncollectable_ints(1, 100); + test_generic_malloc_or_special(d); e = uncollectable_ints(1, 1); /* Check that realloc updates object descriptors correctly */ collectable_count++; @@ -606,6 +626,7 @@ void *GC_CALLBACK reverse_test_inner(void *data) f[5] = ints(1,17); collectable_count++; g = (sexpr *)GC_MALLOC(513 * sizeof(sexpr)); + test_generic_malloc_or_special(g); realloc_count++; g = (sexpr *)GC_REALLOC((void *)g, 800 * sizeof(sexpr)); CHECK_OUT_OF_MEMORY(g); @@ -1283,6 +1304,7 @@ void run_one_test(void) GC_FREE(GC_MALLOC(0)); (void)GC_MALLOC_ATOMIC(0); GC_FREE(GC_MALLOC_ATOMIC(0)); + test_generic_malloc_or_special(GC_malloc_atomic(1)); } } # ifdef GC_GCJ_SUPPORT |