/*
* 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.
#ifndef GC_RATE
# define GC_RATE 10
#endif
+
#ifndef MAX_PRIOR_ATTEMPTS
# define MAX_PRIOR_ATTEMPTS 1
#endif
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;)
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
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);
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();
}
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 */
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);