From: Ivan Maidanski Date: Tue, 11 Sep 2012 19:03:55 +0000 (+0400) Subject: Enable 'Force GC at every GC_malloc' debug-related functionality X-Git-Tag: gc7_4_0~213 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9dbe549fded38f9a456004831a9eced840a6ce36;p=gc Enable 'Force GC at every GC_malloc' debug-related functionality * doc/README.environment (GC_COLLECT_AT_MALLOC): Document. * doc/README.macros (GC_COLLECT_AT_MALLOC): Likewise. * fnlz_mlc.c (GC_core_finalized_malloc): Insert GC_DBG_COLLECT_AT_MALLOC invocation (before LOCK). * gcj_mlc.c (GC_core_gcj_malloc, GC_gcj_malloc_ignore_off_page): Likewise. * malloc.c (GC_generic_malloc, GC_malloc_atomic, GC_malloc, GC_malloc_uncollectable): Likewise. * mallocx.c (GC_generic_malloc_ignore_off_page, GC_generic_malloc_many, GC_malloc_atomic_uncollectable): Likewise. * typd_mlc.c (GC_malloc_explicitly_typed, GC_malloc_explicitly_typed_ignore_off_page): Likewise. * include/private/gc_priv.h (GC_COLLECT_AT_MALLOC): Recognize new macro. (GC_dbg_collect_at_malloc_min_lb): New global variable declaration (only if GC_COLLECT_AT_MALLOC defined). (GC_DBG_COLLECT_AT_MALLOC): Define new macro (invoking GC_gcollect). * malloc.c (GC_dbg_collect_at_malloc_min_lb): New global variable (only if GC_COLLECT_AT_MALLOC defined). * misc.c (GC_init): Test "GC_COLLECT_AT_MALLOC" environment variable and alter default GC_dbg_collect_at_malloc_min_lb value (only if GC_COLLECT_AT_MALLOC macro defined). --- diff --git a/doc/README.environment b/doc/README.environment index 866e9055..79752f78 100644 --- a/doc/README.environment +++ b/doc/README.environment @@ -34,6 +34,10 @@ GC_DUMP_REGULARLY - Generate a GC debugging dump GC_dump() on startup if you have a bug to report, but please include only the last complete dump. +GC_COLLECT_AT_MALLOC= - Override the default value specified by + GC_COLLECT_AT_MALLOC macro. Has no effect unless + GC is built with GC_COLLECT_AT_MALLOC defined. + GC_BACKTRACES= - Generate n random back-traces (for heap profiling) after each GC. Collector must have been built with KEEP_BACK_PTRS. This won't generate useful output unless diff --git a/doc/README.macros b/doc/README.macros index 86334a4f..6f3a8f50 100644 --- a/doc/README.macros +++ b/doc/README.macros @@ -235,6 +235,10 @@ NO_DEBUGGING Removes GC_dump and the debugging routines it calls. DEBUG_THREADS Turn on printing additional thread-support debugging information. +GC_COLLECT_AT_MALLOC= Force garbage collection at every + GC_malloc_* call with the size greater than the specified value. + (Might be useful for application debugging or in find-leak mode.) + JAVA_FINALIZATION Makes it somewhat safer to finalize objects out of order by specifying a nonstandard finalization mark procedure (see finalize.c). Objects reachable from finalizable objects will be marked diff --git a/fnlz_mlc.c b/fnlz_mlc.c index 5017a700..df1fd4ca 100644 --- a/fnlz_mlc.c +++ b/fnlz_mlc.c @@ -93,6 +93,7 @@ GC_API void GC_CALL GC_register_disclaim_proc(int kind, GC_disclaim_proc proc, lb += sizeof(void *); GC_ASSERT(done_init); if (EXPECT(SMALL_OBJ(lb), TRUE)) { + GC_DBG_COLLECT_AT_MALLOC(lb); lg = GC_size_map[lb]; opp = &GC_finalized_objfreelist[lg]; LOCK(); diff --git a/gcj_mlc.c b/gcj_mlc.c index a749c622..ea5c8816 100644 --- a/gcj_mlc.c +++ b/gcj_mlc.c @@ -168,6 +168,7 @@ static void maybe_finalize(void) word lg; DCL_LOCK_STATE; + GC_DBG_COLLECT_AT_MALLOC(lb); if(SMALL_OBJ(lb)) { lg = GC_size_map[lb]; opp = &(GC_gcjobjfreelist[lg]); @@ -243,6 +244,7 @@ GC_API void * GC_CALL GC_gcj_malloc_ignore_off_page(size_t lb, word lg; DCL_LOCK_STATE; + GC_DBG_COLLECT_AT_MALLOC(lb); if(SMALL_OBJ(lb)) { lg = GC_size_map[lb]; opp = &(GC_gcjobjfreelist[lg]); diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 823e2c5f..0df1a228 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -1806,6 +1806,16 @@ GC_INNER ptr_t GC_allocobj(size_t sz, int kind); #define GENERAL_MALLOC_IOP(lb,k) \ GC_clear_stack(GC_generic_malloc_ignore_off_page(lb, k)) +#ifdef GC_COLLECT_AT_MALLOC + extern size_t GC_dbg_collect_at_malloc_min_lb; + /* variable visible outside for debugging */ +# define GC_DBG_COLLECT_AT_MALLOC(lb) \ + (void)((lb) >= GC_dbg_collect_at_malloc_min_lb ? \ + (GC_gcollect(), 0) : 0) +#else +# define GC_DBG_COLLECT_AT_MALLOC(lb) (void)0 +#endif /* !GC_COLLECT_AT_MALLOC */ + /* Allocation routines that bypass the thread local cache. */ #ifdef THREAD_LOCAL_ALLOC GC_INNER void * GC_core_malloc(size_t); diff --git a/malloc.c b/malloc.c index 8e5552f8..0bf84b22 100644 --- a/malloc.c +++ b/malloc.c @@ -161,6 +161,12 @@ GC_INNER void * GC_generic_malloc_inner_ignore_off_page(size_t lb, int k) return op; } +#ifdef GC_COLLECT_AT_MALLOC + /* Parameter to force GC at every malloc of size greater or equal to */ + /* the given value. This might be handy during debugging. */ + size_t GC_dbg_collect_at_malloc_min_lb = (GC_COLLECT_AT_MALLOC); +#endif + GC_API void * GC_CALL GC_generic_malloc(size_t lb, int k) { void * result; @@ -169,6 +175,7 @@ GC_API void * GC_CALL GC_generic_malloc(size_t lb, int k) if (EXPECT(GC_have_errors, FALSE)) GC_print_all_errors(); GC_INVOKE_FINALIZERS(); + GC_DBG_COLLECT_AT_MALLOC(lb); if (SMALL_OBJ(lb)) { LOCK(); result = GC_generic_malloc_inner((word)lb, k); @@ -178,6 +185,7 @@ GC_API void * GC_CALL GC_generic_malloc(size_t lb, int k) size_t lb_rounded; word n_blocks; GC_bool init; + lg = ROUNDED_UP_GRANULES(lb); lb_rounded = GRANULES_TO_BYTES(lg); if (lb_rounded < lb) @@ -226,6 +234,7 @@ GC_API void * GC_CALL GC_generic_malloc(size_t lb, int k) DCL_LOCK_STATE; if(SMALL_OBJ(lb)) { + GC_DBG_COLLECT_AT_MALLOC(lb); lg = GC_size_map[lb]; opp = &(GC_aobjfreelist[lg]); LOCK(); @@ -255,6 +264,7 @@ GC_API void * GC_CALL GC_generic_malloc(size_t lb, int k) DCL_LOCK_STATE; if(SMALL_OBJ(lb)) { + GC_DBG_COLLECT_AT_MALLOC(lb); lg = GC_size_map[lb]; opp = (void **)&(GC_objfreelist[lg]); LOCK(); @@ -286,6 +296,7 @@ GC_API void * GC_CALL GC_malloc_uncollectable(size_t lb) DCL_LOCK_STATE; if( SMALL_OBJ(lb) ) { + GC_DBG_COLLECT_AT_MALLOC(lb); if (EXTRA_BYTES != 0 && lb != 0) lb--; /* We don't need the extra byte, since this won't be */ /* collected anyway. */ diff --git a/mallocx.c b/mallocx.c index 6f3b2064..bf7f9f06 100644 --- a/mallocx.c +++ b/mallocx.c @@ -189,6 +189,7 @@ GC_INNER void * GC_generic_malloc_ignore_off_page(size_t lb, int k) 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 (0 != result) { @@ -293,6 +294,7 @@ GC_API void GC_CALL GC_generic_malloc_many(size_t lb, int k, void **result) if (EXPECT(GC_have_errors, FALSE)) GC_print_all_errors(); GC_INVOKE_FINALIZERS(); + GC_DBG_COLLECT_AT_MALLOC(lb); LOCK(); if (!EXPECT(GC_is_initialized, TRUE)) GC_init(); /* Do our share of marking work */ @@ -513,6 +515,7 @@ GC_API int GC_CALL GC_posix_memalign(void **memptr, size_t align, size_t lb) DCL_LOCK_STATE; if( SMALL_OBJ(lb) ) { + GC_DBG_COLLECT_AT_MALLOC(lb); if (EXTRA_BYTES != 0 && lb != 0) lb--; /* We don't need the extra byte, since this won't be */ /* collected anyway. */ diff --git a/misc.c b/misc.c index 0133c1a6..c886d717 100644 --- a/misc.c +++ b/misc.c @@ -876,6 +876,16 @@ GC_API void GC_CALL GC_init(void) # endif } } +# ifdef GC_COLLECT_AT_MALLOC + { + char * string = GETENV("GC_COLLECT_AT_MALLOC"); + if (0 != string) { + size_t min_lb = (size_t)STRTOULL(string, NULL, 10); + if (min_lb > 0) + GC_dbg_collect_at_malloc_min_lb = min_lb; + } + } +# endif # ifndef GC_DISABLE_INCREMENTAL { char * time_limit_string = GETENV("GC_PAUSE_TIME_TARGET"); diff --git a/typd_mlc.c b/typd_mlc.c index 9a223047..827cc4f3 100644 --- a/typd_mlc.c +++ b/typd_mlc.c @@ -592,6 +592,7 @@ GC_API void * GC_CALL GC_malloc_explicitly_typed(size_t lb, GC_descr d) lb += TYPD_EXTRA_BYTES; if(SMALL_OBJ(lb)) { + GC_DBG_COLLECT_AT_MALLOC(lb); lg = GC_size_map[lb]; opp = &(GC_eobjfreelist[lg]); LOCK(); @@ -628,6 +629,7 @@ GC_API void * GC_CALL GC_malloc_explicitly_typed_ignore_off_page(size_t lb, lb += TYPD_EXTRA_BYTES; if( SMALL_OBJ(lb) ) { + GC_DBG_COLLECT_AT_MALLOC(lb); lg = GC_size_map[lb]; opp = &(GC_eobjfreelist[lg]); LOCK();