#include "mono/utils/hazard-pointer.h"
#include <mono/utils/memcheck.h>
+#include <mono/utils/mono-mmap-internals.h>
#undef pthread_create
#undef pthread_join
MonoCoopMutex sgen_interruption_mutex;
int current_collection_generation = -1;
-static volatile gboolean concurrent_collection_in_progress = FALSE;
+volatile gboolean concurrent_collection_in_progress = FALSE;
/* objects that are ready to be finalized */
static SgenPointerQueue fin_ready_queue = SGEN_POINTER_QUEUE_INIT (INTERNAL_MEM_FINALIZE_READY);
/* If there isn't enough space even for the nursery we should simply abort. */
g_assert (sgen_memgov_try_alloc_space (alloc_size, SPACE_NURSERY));
- data = (char *)major_collector.alloc_heap (alloc_size, alloc_size, DEFAULT_NURSERY_BITS);
+ data = (char *)major_collector.alloc_heap (alloc_size, alloc_size, sgen_nursery_bits);
sgen_update_heap_boundaries ((mword)data, (mword)(data + sgen_nursery_size));
SGEN_LOG (4, "Expanding nursery size (%p-%p): %lu, total: %lu", data, data + alloc_size, (unsigned long)sgen_nursery_size, (unsigned long)sgen_gc_get_total_heap_allocation ());
section->data = section->next_data = data;
return CONTEXT_FROM_OBJECT_OPERATIONS (job->ops, sgen_workers_get_job_gray_queue (worker_data, job->gc_thread_gray_queue));
}
-static void
-job_remembered_set_scan (void *worker_data_untyped, SgenThreadPoolJob *job)
-{
- SGEN_TV_DECLARE (atv);
- SGEN_TV_DECLARE (btv);
- ScanCopyContext ctx = scan_copy_context_for_scan_job (worker_data_untyped, (ScanJob*)job);
-
- SGEN_TV_GETTIME (atv);
- sgen_get_major_collector ()->scan_card_table (CARDTABLE_SCAN_GLOBAL, ctx, 0, 1);
- SGEN_TV_GETTIME (btv);
- time_minor_scan_major_blocks += SGEN_TV_ELAPSED (atv, btv);
-
- sgen_los_scan_card_table (CARDTABLE_SCAN_GLOBAL, ctx, 0, 1);
- SGEN_TV_GETTIME (atv);
- time_minor_scan_los += SGEN_TV_ELAPSED (btv, atv);
-
- sgen_wbroots_scan_card_table (ctx);
-}
-
typedef struct {
ScanJob scan_job;
char *heap_start;
scan_finalizer_entries (job_data->queue, ctx);
}
+static void
+job_scan_wbroots (void *worker_data_untyped, SgenThreadPoolJob *job)
+{
+ ScanJob *job_data = (ScanJob*)job;
+ ScanCopyContext ctx = scan_copy_context_for_scan_job (worker_data_untyped, job_data);
+
+ sgen_wbroots_scan_card_table (ctx);
+}
+
+static void
+job_scan_major_card_table (void *worker_data_untyped, SgenThreadPoolJob *job)
+{
+ SGEN_TV_DECLARE (atv);
+ SGEN_TV_DECLARE (btv);
+ ParallelScanJob *job_data = (ParallelScanJob*)job;
+ ScanCopyContext ctx = scan_copy_context_for_scan_job (worker_data_untyped, (ScanJob*)job_data);
+
+ SGEN_TV_GETTIME (atv);
+ major_collector.scan_card_table (CARDTABLE_SCAN_GLOBAL, ctx, job_data->job_index, sgen_workers_get_job_split_count ());
+ SGEN_TV_GETTIME (btv);
+ time_minor_scan_major_blocks += SGEN_TV_ELAPSED (atv, btv);
+}
+
+static void
+job_scan_los_card_table (void *worker_data_untyped, SgenThreadPoolJob *job)
+{
+ SGEN_TV_DECLARE (atv);
+ SGEN_TV_DECLARE (btv);
+ ParallelScanJob *job_data = (ParallelScanJob*)job;
+ ScanCopyContext ctx = scan_copy_context_for_scan_job (worker_data_untyped, (ScanJob*)job_data);
+
+ SGEN_TV_GETTIME (atv);
+ sgen_los_scan_card_table (CARDTABLE_SCAN_GLOBAL, ctx, job_data->job_index, sgen_workers_get_job_split_count ());
+ SGEN_TV_GETTIME (btv);
+ time_minor_scan_los += SGEN_TV_ELAPSED (atv, btv);
+}
+
static void
job_scan_major_mod_union_card_table (void *worker_data_untyped, SgenThreadPoolJob *job)
{
sgen_gray_object_queue_init (gc_thread_gray_queue, NULL, TRUE);
}
+static void
+enqueue_scan_remembered_set_jobs (SgenGrayQueue *gc_thread_gray_queue, SgenObjectOperations *ops, gboolean enqueue)
+{
+ int i, split_count = sgen_workers_get_job_split_count ();
+ ScanJob *sj;
+
+ sj = (ScanJob*)sgen_thread_pool_job_alloc ("scan wbroots", job_scan_wbroots, sizeof (ScanJob));
+ sj->ops = ops;
+ sj->gc_thread_gray_queue = gc_thread_gray_queue;
+ sgen_workers_enqueue_job (&sj->job, enqueue);
+
+ for (i = 0; i < split_count; i++) {
+ ParallelScanJob *psj;
+
+ psj = (ParallelScanJob*)sgen_thread_pool_job_alloc ("scan major remsets", job_scan_major_card_table, sizeof (ParallelScanJob));
+ psj->scan_job.ops = ops;
+ psj->scan_job.gc_thread_gray_queue = gc_thread_gray_queue;
+ psj->job_index = i;
+ sgen_workers_enqueue_job (&psj->scan_job.job, enqueue);
+
+ psj = (ParallelScanJob*)sgen_thread_pool_job_alloc ("scan LOS remsets", job_scan_los_card_table, sizeof (ParallelScanJob));
+ psj->scan_job.ops = ops;
+ psj->scan_job.gc_thread_gray_queue = gc_thread_gray_queue;
+ psj->job_index = i;
+ sgen_workers_enqueue_job (&psj->scan_job.job, enqueue);
+ }
+}
+
static void
enqueue_scan_from_roots_jobs (SgenGrayQueue *gc_thread_gray_queue, char *heap_start, char *heap_end, SgenObjectOperations *ops, gboolean enqueue)
{
size_t max_garbage_amount;
char *nursery_next;
mword fragment_total;
- ScanJob *sj;
SgenGrayQueue gc_thread_gray_queue;
SgenObjectOperations *object_ops_nopar, *object_ops_par = NULL;
ScanCopyContext ctx;
remset.start_scan_remsets ();
- sj = (ScanJob*)sgen_thread_pool_job_alloc ("scan remset", job_remembered_set_scan, sizeof (ScanJob));
- sj->ops = is_parallel ? object_ops_par : object_ops_nopar;
- sj->gc_thread_gray_queue = &gc_thread_gray_queue;
- sgen_workers_enqueue_job (&sj->job, is_parallel);
+ enqueue_scan_remembered_set_jobs (&gc_thread_gray_queue, is_parallel ? object_ops_par : object_ops_nopar, is_parallel);
/* we don't have complete write barrier yet, so we scan all the old generation sections */
TV_GETTIME (btv);
}
void
-sgen_wbarrier_value_copy_bitmap (gpointer _dest, gpointer _src, int size, unsigned bitmap)
+sgen_wbarrier_range_copy (gpointer _dest, gpointer _src, int size)
{
- GCObject **dest = (GCObject **)_dest;
- GCObject **src = (GCObject **)_src;
-
- while (size) {
- if (bitmap & 0x1)
- mono_gc_wbarrier_generic_store (dest, *src);
- else
- *dest = *src;
- ++src;
- ++dest;
- size -= SIZEOF_VOID_P;
- bitmap >>= 1;
- }
+ remset.wbarrier_range_copy (_dest,_src, size);
}
/*
void
sgen_gc_init (void)
{
- const char *env;
+ char *env;
char **opts, **ptr;
char *major_collector_opt = NULL;
char *minor_collector_opt = NULL;
if ((env = g_getenv (MONO_GC_PARAMS_NAME)) || gc_params_options) {
params_opts = g_strdup_printf ("%s,%s", gc_params_options ? gc_params_options : "", env ? env : "");
+ g_free (env);
}
if (params_opts) {
goto use_default_major;
}
- sgen_nursery_size = DEFAULT_NURSERY_SIZE;
-
if (opts) {
gboolean usage_printed = FALSE;
}
continue;
}
-
-#ifdef USER_CONFIG
if (g_str_has_prefix (opt, "nursery-size=")) {
size_t val;
opt = strchr (opt, '=') + 1;
}
continue;
}
-#endif
if (g_str_has_prefix (opt, "save-target-ratio=")) {
double val;
opt = strchr (opt, '=') + 1;
if ((env = g_getenv (MONO_GC_DEBUG_NAME)) || gc_debug_options) {
debug_opts = g_strdup_printf ("%s,%s", gc_debug_options ? gc_debug_options : "", env ? env : "");
+ g_free (env);
}
if (debug_opts) {
} else if (!strcmp (opt, "verify-before-allocs")) {
verify_before_allocs = 1;
has_per_allocation_action = TRUE;
+ } else if (g_str_has_prefix (opt, "max-valloc-size=")) {
+ size_t max_valloc_size;
+ char *arg = strchr (opt, '=') + 1;
+ if (*opt && mono_gc_parse_environment_string_extract_number (arg, &max_valloc_size)) {
+ mono_valloc_set_limit (max_valloc_size);
+ } else {
+ sgen_env_var_error (MONO_GC_DEBUG_NAME, NULL, "`max-valloc-size` must be an integer.");
+ }
+ continue;
} else if (g_str_has_prefix (opt, "verify-before-allocs=")) {
char *arg = strchr (opt, '=') + 1;
verify_before_allocs = atoi (arg);
fprintf (stderr, "Valid <option>s are:\n");
fprintf (stderr, " collect-before-allocs[=<n>]\n");
fprintf (stderr, " verify-before-allocs[=<n>]\n");
+ fprintf (stderr, " max-valloc-size=N (where N is an integer, possibly with a k, m or a g suffix)\n");
fprintf (stderr, " check-remset-consistency\n");
fprintf (stderr, " check-mark-bits\n");
fprintf (stderr, " check-nursery-pinned\n");
if (major_collector.post_param_init)
major_collector.post_param_init (&major_collector);
- if (major_collector.needs_thread_pool || sgen_minor_collector.is_parallel) {
+ if (major_collector.is_concurrent || sgen_minor_collector.is_parallel) {
int num_workers = 1;
if (major_collector.is_parallel || sgen_minor_collector.is_parallel) {
/* FIXME Detect the number of physical cores, instead of logical */