From: Jonathan Chambers Date: Tue, 10 Apr 2018 17:02:57 +0000 (-0400) Subject: Expose API to control rate and max prior attempts of collect_a_little X-Git-Tag: v8.0.0~220 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f0d18c37304e89ae18c745ba7ff1c930482ede8c;p=gc Expose API to control rate and max prior attempts of collect_a_little (a cherry-pick of commit d897344 from 'unity-release-7_4-incremental') * alloc.c (GC_RATE): Update comment. * alloc.c (GC_rate): New STATIC variable (initialized to GC_RATE). * alloc.c (GC_set_rate, GC_get_rate, GC_set_max_prior_attempts, GC_get_max_prior_attempts): New API function definition. * alloc.c (max_prior_attempts): New static variable (initialized to MAX_PRIOR_ATTEMPTS). * alloc.c (GC_collect_a_little_inner): Replace GC_RATE to GC_rate; declare max_deficit local variable and compute GC_rate*n once (per a function call); replace MAX_PRIOR_ATTEMPTS to max_prior_attempts. * include/gc.h (GC_set_rate, GC_get_rate, GC_set_max_prior_attempts, GC_get_max_prior_attempts): New API function declaration. * tests/test.c [GC_PTHREADS] (main): Call GC_set_rate, GC_get_rate, GC_set_max_prior_attempts, GC_get_max_prior_attempts. --- diff --git a/alloc.c b/alloc.c index d26178af..b81d8502 100644 --- a/alloc.c +++ b/alloc.c @@ -569,7 +569,7 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func) /* * Perform n units of garbage collection work. A unit is intended to touch - * roughly GC_RATE pages. Every once in a while, we do more than that. + * roughly GC_rate pages. Every once in a while, we do more than that. * This needs to be a fairly large number with our current incremental * GC strategy, since otherwise we allocate too much during GC, and the * cleanup gets expensive. @@ -577,6 +577,7 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func) #ifndef GC_RATE # define GC_RATE 10 #endif + #ifndef MAX_PRIOR_ATTEMPTS # define MAX_PRIOR_ATTEMPTS 1 #endif @@ -588,6 +589,32 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func) STATIC int GC_deficit = 0;/* The number of extra calls to GC_mark_some */ /* that we have made. */ +STATIC int GC_rate = GC_RATE; + +GC_API void GC_CALL GC_set_rate(int value) +{ + GC_ASSERT(value > 0); + GC_rate = value; +} + +GC_API int GC_CALL GC_get_rate(void) +{ + return GC_rate; +} + +static int max_prior_attempts = MAX_PRIOR_ATTEMPTS; + +GC_API void GC_CALL GC_set_max_prior_attempts(int value) +{ + GC_ASSERT(value >= 0); + max_prior_attempts = value; +} + +GC_API int GC_CALL GC_get_max_prior_attempts(void) +{ + return max_prior_attempts; +} + GC_INNER void GC_collect_a_little_inner(int n) { IF_CANCEL(int cancel_state;) @@ -598,8 +625,9 @@ GC_INNER void GC_collect_a_little_inner(int n) DISABLE_CANCEL(cancel_state); if (GC_incremental && GC_collection_in_progress()) { int i; + int max_deficit = GC_rate * n; - for (i = GC_deficit; i < GC_RATE*n; i++) { + for (i = GC_deficit; i < max_deficit; i++) { if (GC_mark_some((ptr_t)0)) { /* Need to finish a collection */ # ifdef SAVE_CALL_CHAIN @@ -609,7 +637,7 @@ GC_INNER void GC_collect_a_little_inner(int n) if (GC_parallel) GC_wait_for_reclaim(); # endif - if (GC_n_attempts < MAX_PRIOR_ATTEMPTS + if (GC_n_attempts < max_prior_attempts && GC_time_limit != GC_TIME_UNLIMITED) { # ifndef NO_CLOCK GET_TIME(GC_start_time); @@ -627,8 +655,11 @@ GC_INNER void GC_collect_a_little_inner(int n) break; } } - if (GC_deficit > 0) GC_deficit -= GC_RATE*n; - if (GC_deficit < 0) GC_deficit = 0; + if (GC_deficit > 0) { + GC_deficit -= max_deficit; + if (GC_deficit < 0) + GC_deficit = 0; + } } else { GC_maybe_gc(); } diff --git a/include/gc.h b/include/gc.h index 32f66f8c..5461987c 100644 --- a/include/gc.h +++ b/include/gc.h @@ -433,6 +433,16 @@ GC_API int GC_CALL GC_get_pages_executable(void); GC_API void GC_CALL GC_set_min_bytes_allocd(size_t); GC_API size_t GC_CALL GC_get_min_bytes_allocd(void); +/* Set/get the size in pages of units operated by GC_collect_a_little. */ +/* The value should not be zero. Not synchronized. */ +GC_API void GC_CALL GC_set_rate(int); +GC_API int GC_CALL GC_get_rate(void); + +/* Set/get the maximum number of prior attempts at the world-stop */ +/* marking. Not synchronized. */ +GC_API void GC_CALL GC_set_max_prior_attempts(int); +GC_API int GC_CALL GC_get_max_prior_attempts(void); + /* Overrides the default handle-fork mode. Non-zero value means GC */ /* should install proper pthread_atfork handlers. Has effect only if */ /* called before GC_INIT. Clients should invoke GC_set_handle_fork */ diff --git a/tests/test.c b/tests/test.c index 13fb90ea..e19ac0f7 100644 --- a/tests/test.c +++ b/tests/test.c @@ -2264,6 +2264,10 @@ int main(void) GC_set_min_bytes_allocd(1); if (GC_get_min_bytes_allocd() != 1) FAIL; + GC_set_rate(10); + GC_set_max_prior_attempts(1); + if (GC_get_rate() != 10 || GC_get_max_prior_attempts() != 1) + FAIL; GC_set_warn_proc(warn_proc); if ((code = pthread_key_create(&fl_key, 0)) != 0) { GC_printf("Key creation failed %d\n", code);