From: Vlad Brezae Date: Mon, 7 Dec 2015 22:09:17 +0000 (-0500) Subject: Merge pull request #2246 from BrzVlad/feature-concurrent-evacuation X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=44f4429237816e808e42136783c6fb885e13a5dd;hp=-c;p=mono.git Merge pull request #2246 from BrzVlad/feature-concurrent-evacuation Feature evacuation with concurrent sgen --- 44f4429237816e808e42136783c6fb885e13a5dd diff --combined mono/metadata/boehm-gc.c index 0401c5cf2d7,c511bff8118..a29e83ed57b --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@@ -29,7 -29,7 +29,7 @@@ #include #include #include -#include +#include #include #if HAVE_BOEHM_GC @@@ -64,8 -64,8 +64,8 @@@ static MonoGCFinalizerCallbacks fin_cal /* GC Handles */ static mono_mutex_t handle_section; -#define lock_handles(handles) mono_mutex_lock (&handle_section) -#define unlock_handles(handles) mono_mutex_unlock (&handle_section) +#define lock_handles(handles) mono_os_mutex_lock (&handle_section) +#define unlock_handles(handles) mono_os_mutex_unlock (&handle_section) typedef struct { guint32 *bitmap; @@@ -196,7 -196,6 +196,7 @@@ mono_gc_base_init (void GC_finalizer_notifier = mono_gc_finalize_notify; GC_init_gcj_malloc (5, NULL); + GC_allow_register_threads (); if ((env = g_getenv ("MONO_GC_PARAMS"))) { char **ptr, **opts = g_strsplit (env, ",", -1); @@@ -238,8 -237,8 +238,8 @@@ cb.mono_method_is_critical = (gpointer)mono_runtime_is_critical_method; mono_threads_init (&cb, sizeof (MonoThreadInfo)); - mono_mutex_init (&mono_gc_lock); - mono_mutex_init_recursive (&handle_section); + mono_os_mutex_init (&mono_gc_lock); + mono_os_mutex_init_recursive (&handle_section); mono_thread_info_attach (&dummy); @@@ -371,6 -370,8 +371,6 @@@ mono_gc_is_gc_thread (void return GC_thread_is_registered (); } -extern int GC_thread_register_foreign (void *base_addr); - gboolean mono_gc_register_thread (void *baseptr) { @@@ -380,15 -381,13 +380,15 @@@ static void* boehm_thread_register (MonoThreadInfo* info, void *baseptr) { - if (mono_gc_is_gc_thread()) - return info; -#if !defined(HOST_WIN32) - return GC_thread_register_foreign (baseptr) ? info : NULL; -#else - return NULL; -#endif + struct GC_stack_base sb; + int res; + + /* TODO: use GC_get_stack_base instead of baseptr. */ + sb.mem_base = baseptr; + res = GC_register_my_thread (&sb); + if (res == GC_UNIMPLEMENTED) + return NULL; /* Cannot happen with GC v7+. */ + return info; } static void @@@ -417,7 -416,7 +417,7 @@@ mono_gc_walk_heap (int flags, MonoGCRef static gint64 gc_start_time; static void -on_gc_notification (GCEventType event) +on_gc_notification (GC_EventType event) { MonoGCEvent e = (MonoGCEvent)event; @@@ -496,7 -495,7 +496,7 @@@ on_gc_heap_resize (size_t new_size void mono_gc_enable_events (void) { - GC_notify_event = on_gc_notification; + GC_set_on_collection_event (on_gc_notification); GC_on_heap_resize = on_gc_heap_resize; } @@@ -806,7 -805,7 +806,7 @@@ mono_gc_get_suspend_signal (void int mono_gc_get_restart_signal (void) { - return GC_get_restart_signal (); + return GC_get_thr_restart_signal (); } #if defined(USE_COMPILER_TLS) && defined(__linux__) && (defined(__i386__) || defined(__x86_64__)) @@@ -925,17 -924,11 +925,17 @@@ create_allocator (int atype, int tls_ke mono_mb_emit_byte (mb, 0x0D); /* CEE_MONO_TLS */ mono_mb_emit_i4 (mb, tls_key); if (atype == ATYPE_FREEPTR || atype == ATYPE_FREEPTR_FOR_BOX || atype == ATYPE_STRING) - mono_mb_emit_icon (mb, G_STRUCT_OFFSET (struct GC_Thread_Rep, ptrfree_freelists)); + mono_mb_emit_icon (mb, G_STRUCT_OFFSET (struct GC_Thread_Rep, tlfs) + + G_STRUCT_OFFSET (struct thread_local_freelists, + ptrfree_freelists)); else if (atype == ATYPE_NORMAL) - mono_mb_emit_icon (mb, G_STRUCT_OFFSET (struct GC_Thread_Rep, normal_freelists)); + mono_mb_emit_icon (mb, G_STRUCT_OFFSET (struct GC_Thread_Rep, tlfs) + + G_STRUCT_OFFSET (struct thread_local_freelists, + normal_freelists)); else if (atype == ATYPE_GCJ) - mono_mb_emit_icon (mb, G_STRUCT_OFFSET (struct GC_Thread_Rep, gcj_freelists)); + mono_mb_emit_icon (mb, G_STRUCT_OFFSET (struct GC_Thread_Rep, tlfs) + + G_STRUCT_OFFSET (struct thread_local_freelists, + gcj_freelists)); else g_assert_not_reached (); mono_mb_emit_byte (mb, MONO_CEE_ADD); @@@ -1148,7 -1141,7 +1148,7 @@@ mono_gc_get_managed_allocator_by_type ( return res; res = create_allocator (atype, TLS_KEY_BOEHM_GC_THREAD, slowpath); - mono_mutex_lock (&mono_gc_lock); + mono_os_mutex_lock (&mono_gc_lock); if (cache [atype]) { mono_free_method (res); res = cache [atype]; @@@ -1156,7 -1149,7 +1156,7 @@@ mono_memory_barrier (); cache [atype] = res; } - mono_mutex_unlock (&mono_gc_lock); + mono_os_mutex_unlock (&mono_gc_lock); return res; } @@@ -1427,24 -1420,18 +1427,19 @@@ mono_gc_make_root_descr_user (MonoGCRoo return NULL; } - gboolean - mono_gc_set_allow_synchronous_major (gboolean flag) - { - return flag; - } /* Toggleref support */ void mono_gc_toggleref_add (MonoObject *object, mono_bool strong_ref) { - GC_toggleref_add ((GC_PTR)object, (int)strong_ref); + if (GC_toggleref_add ((GC_PTR)object, (int)strong_ref) != GC_SUCCESS) + g_error ("GC_toggleref_add failed\n"); } void mono_gc_toggleref_register_callback (MonoToggleRefStatus (*proccess_toggleref) (MonoObject *obj)) { - GC_toggleref_register_callback ((int (*) (GC_PTR obj)) proccess_toggleref); + GC_set_toggleref_func ((GC_ToggleRefStatus (*) (GC_PTR obj)) proccess_toggleref); } /* Test support code */ @@@ -1493,7 -1480,7 +1488,7 @@@ mono_gc_register_finalizer_callbacks (M fin_callbacks = *callbacks; - GC_set_finalizer_notify_proc ((void (*) (GC_PTR))fin_notifier); + GC_set_await_finalize_proc ((void (*) (GC_PTR))fin_notifier); } #define BITMAP_SIZE (sizeof (*((HandleData *)NULL)->bitmap) * CHAR_BIT) diff --combined mono/metadata/gc-internals.h index b4ded9b5772,3c53082930e..bc9edcbe3ad --- a/mono/metadata/gc-internals.h +++ b/mono/metadata/gc-internals.h @@@ -17,8 -17,8 +17,8 @@@ #include #include -#define mono_domain_finalizers_lock(domain) mono_mutex_lock (&(domain)->finalizable_objects_hash_lock); -#define mono_domain_finalizers_unlock(domain) mono_mutex_unlock (&(domain)->finalizable_objects_hash_lock); +#define mono_domain_finalizers_lock(domain) mono_os_mutex_lock (&(domain)->finalizable_objects_hash_lock); +#define mono_domain_finalizers_unlock(domain) mono_os_mutex_unlock (&(domain)->finalizable_objects_hash_lock); /* Register a memory area as a conservatively scanned GC root */ #define MONO_GC_REGISTER_ROOT_PINNING(x,src,msg) mono_gc_register_root ((char*)&(x), sizeof(x), MONO_GC_DESCRIPTOR_NULL, (src), (msg)) @@@ -80,7 -80,6 +80,6 @@@ gpointer ves_icall_System_GCHandle_G void ves_icall_System_GC_register_ephemeron_array (MonoObject *array); MonoObject *ves_icall_System_GC_get_ephemeron_tombstone (void); - MonoBoolean ves_icall_Mono_Runtime_SetGCAllowSynchronousMajor (MonoBoolean flag); extern void mono_gc_init (void); extern void mono_gc_base_init (void); @@@ -111,9 -110,6 +110,6 @@@ void mono_gchandle_set_target (guint32 /*Ephemeron functionality. Sgen only*/ gboolean mono_gc_ephemeron_array_add (MonoObject *obj); - /* To disable synchronous, evacuating collections - concurrent SGen only */ - gboolean mono_gc_set_allow_synchronous_major (gboolean flag); - MonoBoolean mono_gc_GCHandle_CheckCurrentDomain (guint32 gchandle); diff --combined mono/metadata/gc.c index a82c4201114,61fa63033c9..deca78d4e4e --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@@ -31,14 -31,13 +31,14 @@@ #include /* for mono_delegate_free_ftnptr () */ #include #include -#include +#include #include #include #include #include #include #include +#include #ifndef HOST_WIN32 #include @@@ -57,17 -56,17 +57,17 @@@ gboolean log_finalizers = FALSE gboolean mono_do_not_finalize = FALSE; gchar **mono_do_not_finalize_class_names = NULL; -#define mono_finalizer_lock() mono_mutex_lock (&finalizer_mutex) -#define mono_finalizer_unlock() mono_mutex_unlock (&finalizer_mutex) -static mono_mutex_t finalizer_mutex; -static mono_mutex_t reference_queue_mutex; +#define mono_finalizer_lock() mono_coop_mutex_lock (&finalizer_mutex) +#define mono_finalizer_unlock() mono_coop_mutex_unlock (&finalizer_mutex) +static MonoCoopMutex finalizer_mutex; +static MonoCoopMutex reference_queue_mutex; static GSList *domains_to_finalize= NULL; static MonoMList *threads_to_finalize = NULL; static gboolean finalizer_thread_exited; /* Uses finalizer_mutex */ -static mono_cond_t exited_cond; +static MonoCoopCond exited_cond; static MonoInternalThread *gc_thread; @@@ -335,8 -334,11 +335,8 @@@ object_register_finalizer (MonoObject * * end up running them while or after the domain is being cleared, so * the objects will not be valid anymore. */ - if (!mono_domain_is_unloading (domain)) { - MONO_TRY_BLOCKING; + if (!mono_domain_is_unloading (domain)) mono_gc_register_for_finalization (obj, callback); - MONO_FINISH_TRY_BLOCKING; - } #endif } @@@ -538,6 -540,10 +538,6 @@@ ves_icall_System_GC_get_ephemeron_tombs return mono_domain_get ()->ephemeron_tombstone; } -#define mono_allocator_lock() mono_mutex_lock (&allocator_section) -#define mono_allocator_unlock() mono_mutex_unlock (&allocator_section) -static mono_mutex_t allocator_section; - MonoObject * ves_icall_System_GCHandle_GetTarget (guint32 handle) { @@@ -601,19 -607,16 +601,13 @@@ ves_icall_System_GCHandle_GetAddrOfPinn return NULL; } - MonoBoolean - ves_icall_Mono_Runtime_SetGCAllowSynchronousMajor (MonoBoolean flag) - { - return mono_gc_set_allow_synchronous_major (flag); - } - MonoBoolean mono_gc_GCHandle_CheckCurrentDomain (guint32 gchandle) { return mono_gchandle_is_in_domain (gchandle, mono_domain_get ()); } -#ifdef MONO_HAS_SEMAPHORES -static MonoSemType finalizer_sem; -#endif -static HANDLE finalizer_event; +static MonoCoopSem finalizer_sem; static volatile gboolean finished=FALSE; void @@@ -626,7 -629,11 +620,7 @@@ mono_gc_finalize_notify (void if (mono_gc_is_null ()) return; -#ifdef MONO_HAS_SEMAPHORES - MONO_SEM_POST (&finalizer_sem); -#else - SetEvent (finalizer_event); -#endif + mono_coop_sem_post (&finalizer_sem); } #ifdef HAVE_BOEHM_GC @@@ -711,13 -718,18 +705,13 @@@ finalizer_thread (gpointer unused g_assert (mono_domain_get () == mono_get_root_domain ()); mono_gc_set_skip_thread (TRUE); - MONO_PREPARE_BLOCKING; if (wait) { - /* An alertable wait is required so this thread can be suspended on windows */ -#ifdef MONO_HAS_SEMAPHORES - MONO_SEM_WAIT_ALERTABLE (&finalizer_sem, TRUE); -#else - WaitForSingleObjectEx (finalizer_event, INFINITE, TRUE); -#endif + /* An alertable wait is required so this thread can be suspended on windows */ + mono_coop_sem_wait (&finalizer_sem, MONO_SEM_FLAGS_ALERTABLE); } wait = TRUE; - MONO_FINISH_BLOCKING; + mono_gc_set_skip_thread (FALSE); mono_threads_perform_thread_dump (); @@@ -748,18 -760,21 +742,18 @@@ reference_queue_proccess_all (); -#ifdef MONO_HAS_SEMAPHORES /* Avoid posting the pending done event until there are pending finalizers */ - if (MONO_SEM_TIMEDWAIT (&finalizer_sem, 0) == 0) + if (mono_coop_sem_timedwait (&finalizer_sem, 0, MONO_SEM_FLAGS_NONE) == 0) { /* Don't wait again at the start of the loop */ wait = FALSE; - else - SetEvent (pending_done_event); -#else + } else { SetEvent (pending_done_event); -#endif + } } mono_finalizer_lock (); finalizer_thread_exited = TRUE; - mono_cond_signal (&exited_cond); + mono_coop_cond_signal (&exited_cond); mono_finalizer_unlock (); return 0; @@@ -778,8 -793,10 +772,8 @@@ mono_gc_init_finalizer_thread (void void mono_gc_init (void) { - mono_mutex_init_recursive (&allocator_section); - - mono_mutex_init_recursive (&finalizer_mutex); - mono_mutex_init_recursive (&reference_queue_mutex); + mono_coop_mutex_init_recursive (&finalizer_mutex); + mono_coop_mutex_init_recursive (&reference_queue_mutex); mono_counters_register ("Minor GC collections", MONO_COUNTER_GC | MONO_COUNTER_UINT, &gc_stats.minor_gc_count); mono_counters_register ("Major GC collections", MONO_COUNTER_GC | MONO_COUNTER_UINT, &gc_stats.major_gc_count); @@@ -793,11 -810,15 +787,11 @@@ gc_disabled = TRUE; return; } - - finalizer_event = CreateEvent (NULL, FALSE, FALSE, NULL); - g_assert (finalizer_event); + pending_done_event = CreateEvent (NULL, TRUE, FALSE, NULL); g_assert (pending_done_event); - mono_cond_init (&exited_cond, 0); -#ifdef MONO_HAS_SEMAPHORES - MONO_SEM_INIT (&finalizer_sem, 0); -#endif + mono_coop_cond_init (&exited_cond); + mono_coop_sem_init (&finalizer_sem, 0); #ifndef LAZY_GC_THREAD_CREATION mono_gc_init_finalizer_thread (); @@@ -832,10 -853,12 +826,10 @@@ mono_gc_cleanup (void break; else timeout = end_ticks - current_ticks; - MONO_PREPARE_BLOCKING; mono_finalizer_lock (); if (!finalizer_thread_exited) - mono_cond_timedwait_ms (&exited_cond, &finalizer_mutex, timeout); + mono_coop_cond_timedwait (&exited_cond, &finalizer_mutex, timeout); mono_finalizer_unlock (); - MONO_FINISH_BLOCKING; } if (!finalizer_thread_exited) { @@@ -877,8 -900,9 +871,8 @@@ mono_reference_queue_cleanup (); - mono_mutex_destroy (&allocator_section); - mono_mutex_destroy (&finalizer_mutex); - mono_mutex_destroy (&reference_queue_mutex); + mono_coop_mutex_destroy (&finalizer_mutex); + mono_coop_mutex_destroy (&reference_queue_mutex); } gboolean @@@ -977,7 -1001,7 +971,7 @@@ reference_queue_proccess_all (void reference_queue_proccess (queue); restart: - mono_mutex_lock (&reference_queue_mutex); + mono_coop_mutex_lock (&reference_queue_mutex); for (iter = &ref_queues; *iter;) { queue = *iter; if (!queue->should_be_deleted) { @@@ -985,14 -1009,14 +979,14 @@@ continue; } if (queue->queue) { - mono_mutex_unlock (&reference_queue_mutex); + mono_coop_mutex_unlock (&reference_queue_mutex); reference_queue_proccess (queue); goto restart; } *iter = queue->next; g_free (queue); } - mono_mutex_unlock (&reference_queue_mutex); + mono_coop_mutex_unlock (&reference_queue_mutex); } static void @@@ -1046,10 -1070,10 +1040,10 @@@ mono_gc_reference_queue_new (mono_refer MonoReferenceQueue *res = g_new0 (MonoReferenceQueue, 1); res->callback = callback; - mono_mutex_lock (&reference_queue_mutex); + mono_coop_mutex_lock (&reference_queue_mutex); res->next = ref_queues; ref_queues = res; - mono_mutex_unlock (&reference_queue_mutex); + mono_coop_mutex_unlock (&reference_queue_mutex); return res; } diff --combined mono/metadata/sgen-client-mono.h index 7dcf6ce4009,0ba15a0b37b..d1e92469b74 --- a/mono/metadata/sgen-client-mono.h +++ b/mono/metadata/sgen-client-mono.h @@@ -90,7 -90,7 +90,7 @@@ struct _SgenClientThreadInfo #include "utils/mono-counters.h" #include "utils/mono-logger-internals.h" #include "utils/mono-time.h" -#include "utils/mono-semaphore.h" +#include "utils/mono-os-semaphore.h" #include "metadata/sgen-bridge-internals.h" extern void mono_sgen_register_moved_object (void *obj, void *destination); @@@ -114,7 -114,7 +114,7 @@@ sgen_mono_array_size (GCVTable vtable, else element_size = vtable->klass->sizes.element_size; - size_without_bounds = size = sizeof (MonoArray) + element_size * mono_array_length_fast (array); + size_without_bounds = size = MONO_SIZEOF_MONO_ARRAY + element_size * mono_array_length_fast (array); if (G_UNLIKELY (array->bounds)) { size += sizeof (mono_array_size_t) - 1; @@@ -560,6 -560,11 +560,11 @@@ sgen_client_binary_protocol_global_rems #endif } + static void G_GNUC_UNUSED + sgen_client_binary_protocol_mod_union_remset (gpointer obj, gpointer ptr, gpointer value, gpointer value_vtable) + { + } + static void G_GNUC_UNUSED sgen_client_binary_protocol_ptr_update (gpointer ptr, gpointer old_value, gpointer new_value, gpointer vtable, size_t size) { @@@ -694,9 -699,9 +699,9 @@@ extern MonoNativeTlsKey thread_info_key typedef MonoSemType SgenSemaphore; -#define SGEN_SEMAPHORE_INIT(sem,initial) MONO_SEM_INIT ((sem), (initial)) -#define SGEN_SEMAPHORE_POST(sem) MONO_SEM_POST ((sem)) -#define SGEN_SEMAPHORE_WAIT(sem) MONO_SEM_WAIT ((sem)) +#define SGEN_SEMAPHORE_INIT(sem,initial) mono_os_sem_init ((sem), (initial)) +#define SGEN_SEMAPHORE_POST(sem) mono_os_sem_post ((sem)) +#define SGEN_SEMAPHORE_WAIT(sem) mono_os_sem_wait ((sem), MONO_SEM_FLAGS_NONE) gboolean sgen_has_critical_method (void); gboolean sgen_is_critical_method (MonoMethod *method); diff --combined mono/metadata/sgen-mono.c index a133f91030f,3ab15956480..456fe45c7ee --- a/mono/metadata/sgen-mono.c +++ b/mono/metadata/sgen-mono.c @@@ -376,7 -376,7 +376,7 @@@ get_array_fill_vtable (void klass.element_class = mono_defaults.byte_class; klass.rank = 1; - klass.instance_size = sizeof (MonoArray); + klass.instance_size = MONO_SIZEOF_MONO_ARRAY; klass.sizes.element_size = 1; klass.name = "array_filler_type"; @@@ -395,7 -395,7 +395,7 @@@ sgen_client_array_fill_range (char *sta { MonoArray *o; - if (size < sizeof (MonoArray)) { + if (size < MONO_SIZEOF_MONO_ARRAY) { memset (start, 0, size); return FALSE; } @@@ -405,7 -405,7 +405,7 @@@ /* Mark this as not a real object */ o->obj.synchronisation = GINT_TO_POINTER (-1); o->bounds = NULL; - o->max_length = (mono_array_size_t)(size - sizeof (MonoArray)); + o->max_length = (mono_array_size_t)(size - MONO_SIZEOF_MONO_ARRAY); return TRUE; } @@@ -413,10 -413,10 +413,10 @@@ void sgen_client_zero_array_fill_header (void *p, size_t size) { - if (size >= sizeof (MonoArray)) { - memset (p, 0, sizeof (MonoArray)); + if (size >= MONO_SIZEOF_MONO_ARRAY) { + memset (p, 0, MONO_SIZEOF_MONO_ARRAY); } else { - static guint8 zeros [sizeof (MonoArray)]; + static guint8 zeros [MONO_SIZEOF_MONO_ARRAY]; SGEN_ASSERT (0, !memcmp (p, zeros, size), "TLAB segment must be zeroed out."); } @@@ -1185,7 -1185,7 +1185,7 @@@ create_allocator (int atype, gboolean s mono_mb_emit_ldarg (mb, 1); mono_mb_emit_byte (mb, CEE_MUL_OVF_UN); /* + sizeof (MonoArray) */ - mono_mb_emit_icon (mb, sizeof (MonoArray)); + mono_mb_emit_icon (mb, MONO_SIZEOF_MONO_ARRAY); mono_mb_emit_byte (mb, CEE_ADD_OVF_UN); mono_mb_emit_stloc (mb, size_var); @@@ -2687,12 -2687,6 +2687,6 @@@ sgen_client_ensure_weak_gchandles_acces mono_gc_wait_for_bridge_processing (); } - gboolean - mono_gc_set_allow_synchronous_major (gboolean flag) - { - return sgen_set_allow_synchronous_major (flag); - } - void* mono_gc_invoke_with_gc_lock (MonoGCLockedCallbackFunc func, void *data) { diff --combined mono/sgen/sgen-gc.c index d559a9285ee,4ffceb8390e..7189811c50e --- a/mono/sgen/sgen-gc.c +++ b/mono/sgen/sgen-gc.c @@@ -239,12 -239,6 +239,6 @@@ static gboolean do_concurrent_checks = each collection */ static gboolean do_scan_starts_check = FALSE; - /* - * If the major collector is concurrent and this is FALSE, we will - * never initiate a synchronous major collection, unless requested via - * GC.Collect(). - */ - static gboolean allow_synchronous_major = TRUE; static gboolean disable_minor_collections = FALSE; static gboolean disable_major_collections = FALSE; static gboolean do_verify_nursery = FALSE; @@@ -346,7 -340,7 +340,7 @@@ nursery_canaries_enabled (void * ######## Global data. * ###################################################################### */ -LOCK_DECLARE (gc_mutex); +MonoCoopMutex gc_mutex; gboolean sgen_try_free_some_memory; #define SCAN_START_SIZE SGEN_SCAN_START_SIZE @@@ -359,7 -353,7 +353,7 @@@ GCMemSection *nursery_section = NULL static volatile mword lowest_heap_address = ~(mword)0; static volatile mword highest_heap_address = 0; -LOCK_DECLARE (sgen_interruption_mutex); +MonoCoopMutex sgen_interruption_mutex; int current_collection_generation = -1; static volatile gboolean concurrent_collection_in_progress = FALSE; @@@ -2244,17 -2238,6 +2238,6 @@@ sgen_perform_collection (size_t request goto done; } - /* - * If we've been asked to do a major collection, and the major collector wants to - * run synchronously (to evacuate), we set the flag to do that. - */ - if (generation_to_collect == GENERATION_OLD && - allow_synchronous_major && - major_collector.want_synchronous_collection && - *major_collector.want_synchronous_collection) { - wait_to_finish = TRUE; - } - SGEN_ASSERT (0, !concurrent_collection_in_progress, "Why did this not get handled above?"); /* @@@ -2726,16 -2709,6 +2709,6 @@@ sgen_gc_get_used_size (void return tot; } - gboolean - sgen_set_allow_synchronous_major (gboolean flag) - { - if (!major_collector.is_concurrent) - return flag; - - allow_synchronous_major = flag; - return TRUE; - } - void sgen_env_var_error (const char *env_var, const char *fallback, const char *description_format, ...) { @@@ -2807,11 -2780,11 +2780,11 @@@ sgen_gc_init (void mono_thread_smr_init (); #endif - LOCK_INIT (gc_mutex); + mono_coop_mutex_init (&gc_mutex); gc_debug_file = stderr; - LOCK_INIT (sgen_interruption_mutex); + mono_coop_mutex_init (&sgen_interruption_mutex); if ((env = g_getenv (MONO_GC_PARAMS_NAME))) { opts = g_strsplit (env, ",", -1); @@@ -2952,23 -2925,6 +2925,6 @@@ } continue; } - if (g_str_has_prefix (opt, "allow-synchronous-major=")) { - if (!major_collector.is_concurrent) { - sgen_env_var_error (MONO_GC_PARAMS_NAME, "Ignoring.", "`allow-synchronous-major` is only valid for the concurrent major collector."); - continue; - } - - opt = strchr (opt, '=') + 1; - - if (!strcmp (opt, "yes")) { - allow_synchronous_major = TRUE; - } else if (!strcmp (opt, "no")) { - allow_synchronous_major = FALSE; - } else { - sgen_env_var_error (MONO_GC_PARAMS_NAME, "Using default value.", "`allow-synchronous-major` must be either `yes' or `no'."); - continue; - } - } if (!strcmp (opt, "cementing")) { cement_enabled = TRUE; @@@ -3001,8 -2957,6 +2957,6 @@@ fprintf (stderr, " minor=COLLECTOR (where COLLECTOR is `simple' or `split')\n"); fprintf (stderr, " wbarrier=WBARRIER (where WBARRIER is `remset' or `cardtable')\n"); fprintf (stderr, " [no-]cementing\n"); - if (major_collector.is_concurrent) - fprintf (stderr, " allow-synchronous-major=FLAG (where FLAG is `yes' or `no')\n"); if (major_collector.print_gc_param_usage) major_collector.print_gc_param_usage (); if (sgen_minor_collector.print_gc_param_usage) @@@ -3191,7 -3145,7 +3145,7 @@@ sgen_get_nursery_clear_policy (void void sgen_gc_lock (void) { - LOCK_GC; + mono_coop_mutex_lock (&gc_mutex); } void @@@ -3199,7 -3153,7 +3153,7 @@@ sgen_gc_unlock (void { gboolean try_free = sgen_try_free_some_memory; sgen_try_free_some_memory = FALSE; - mono_mutex_unlock (&gc_mutex); + mono_coop_mutex_unlock (&gc_mutex); if (try_free) mono_thread_hazardous_try_free_some (); } diff --combined mono/sgen/sgen-gc.h index 0b5d182ff4a,d47a978a619..089ba85a1fb --- a/mono/sgen/sgen-gc.h +++ b/mono/sgen/sgen-gc.h @@@ -39,8 -39,7 +39,8 @@@ typedef struct _SgenThreadInfo SgenThre #include #include "mono/utils/mono-compiler.h" #include "mono/utils/atomic.h" -#include "mono/utils/mono-mutex.h" +#include "mono/utils/mono-os-mutex.h" +#include "mono/utils/mono-coop-mutex.h" #include "mono/sgen/sgen-conf.h" #include "mono/sgen/sgen-hash-table.h" #include "mono/sgen/sgen-protocol.h" @@@ -90,14 -89,23 +90,14 @@@ struct _GCMemSection #define LOCK_DECLARE(name) mono_mutex_t name /* if changing LOCK_INIT to something that isn't idempotent, look at its use in mono_gc_base_init in sgen-gc.c */ -#define LOCK_INIT(name) mono_mutex_init (&(name)) -#define LOCK_GC do { \ - MONO_TRY_BLOCKING \ - mono_mutex_lock (&gc_mutex); \ - MONO_FINISH_TRY_BLOCKING \ - } while (0) +#define LOCK_INIT(name) mono_os_mutex_init (&(name)) +#define LOCK_GC do { sgen_gc_lock (); } while (0) #define UNLOCK_GC do { sgen_gc_unlock (); } while (0) -extern LOCK_DECLARE (sgen_interruption_mutex); - -#define LOCK_INTERRUPTION do { \ - MONO_TRY_BLOCKING \ - mono_mutex_lock (&sgen_interruption_mutex); \ - MONO_FINISH_TRY_BLOCKING \ -} while (0) +extern MonoCoopMutex sgen_interruption_mutex; -#define UNLOCK_INTERRUPTION mono_mutex_unlock (&sgen_interruption_mutex) +#define LOCK_INTERRUPTION mono_coop_mutex_lock (&sgen_interruption_mutex) +#define UNLOCK_INTERRUPTION mono_coop_mutex_unlock (&sgen_interruption_mutex) /* FIXME: Use InterlockedAdd & InterlockedAdd64 to reduce the CAS cost. */ #define SGEN_CAS InterlockedCompareExchange @@@ -599,13 -607,6 +599,6 @@@ struct _SgenMajorCollector gboolean supports_cardtable; gboolean sweeps_lazily; - /* - * This is set to TRUE by the sweep if the next major - * collection should be synchronous (for evacuation). For - * non-concurrent collectors, this should be NULL. - */ - gboolean *want_synchronous_collection; - void* (*alloc_heap) (mword nursery_size, mword nursery_align, int nursery_bits); gboolean (*is_object_live) (GCObject *obj); GCObject* (*alloc_small_pinned_obj) (GCVTable vtable, size_t size, gboolean has_references); @@@ -958,7 -959,7 +951,7 @@@ extern guint32 tlab_size extern NurseryClearPolicy nursery_clear_policy; extern gboolean sgen_try_free_some_memory; -extern LOCK_DECLARE (gc_mutex); +extern MonoCoopMutex gc_mutex; /* Nursery helpers. */ diff --combined mono/sgen/sgen-marksweep.c index 780e4adff1e,9cbf2e8eda0..5b344b6d658 --- a/mono/sgen/sgen-marksweep.c +++ b/mono/sgen/sgen-marksweep.c @@@ -170,8 -170,6 +170,6 @@@ static int fast_block_obj_size_indexes static gboolean *evacuate_block_obj_sizes; static float evacuation_threshold = 0.666f; - static float concurrent_evacuation_threshold = 0.666f; - static gboolean want_evacuation = FALSE; static gboolean lazy_sweep = FALSE; @@@ -245,7 -243,6 +243,6 @@@ static MSBlockInfo * volatile *free_blo static guint64 stat_major_blocks_alloced = 0; static guint64 stat_major_blocks_freed = 0; static guint64 stat_major_blocks_lazy_swept = 0; - static guint64 stat_major_objects_evacuated = 0; #if SIZEOF_VOID_P != 8 static guint64 stat_major_blocks_freed_ideal = 0; @@@ -271,9 -268,9 +268,9 @@@ add_scanned_object (void *ptr if (!binary_protocol_is_enabled ()) return; - mono_mutex_lock (&scanned_objects_list_lock); + mono_os_mutex_lock (&scanned_objects_list_lock); sgen_pointer_queue_add (&scanned_objects_list, ptr); - mono_mutex_unlock (&scanned_objects_list_lock); + mono_os_mutex_unlock (&scanned_objects_list_lock); } #endif @@@ -533,10 -530,11 +530,11 @@@ ms_alloc_block (int size_index, gboolea * Blocks that are to-space are not evacuated from. During an major collection * blocks are allocated for two reasons: evacuating objects from the nursery and * evacuating them from major blocks marked for evacuation. In both cases we don't - * want further evacuation. + * want further evacuation. We also don't want to evacuate objects allocated during + * the concurrent mark since it would add pointless stress on the finishing pause. */ - info->is_to_space = (sgen_get_current_collection_generation () == GENERATION_OLD); - info->state = (info->is_to_space || sgen_concurrent_collection_in_progress ()) ? BLOCK_STATE_MARKING : BLOCK_STATE_SWEPT; + info->is_to_space = (sgen_get_current_collection_generation () == GENERATION_OLD) || sgen_concurrent_collection_in_progress (); + info->state = info->is_to_space ? BLOCK_STATE_MARKING : BLOCK_STATE_SWEPT; SGEN_ASSERT (6, !sweep_in_progress () || info->state == BLOCK_STATE_SWEPT, "How do we add a new block to be swept while sweeping?"); info->cardtable_mod_union = NULL; @@@ -1067,7 -1065,7 +1065,7 @@@ major_get_cardtable_mod_union_for_refer * Mark the mod-union card for `ptr`, which must be a reference within the object `obj`. */ static void - mark_mod_union_card (GCObject *obj, void **ptr) + mark_mod_union_card (GCObject *obj, void **ptr, GCObject *value_obj) { int type = sgen_obj_get_descriptor (obj) & DESC_TYPE_MASK; if (sgen_safe_object_is_small (obj, type)) { @@@ -1077,6 -1075,18 +1075,18 @@@ } else { sgen_los_mark_mod_union_card (obj, ptr); } + + binary_protocol_mod_union_remset (obj, ptr, value_obj, SGEN_LOAD_VTABLE (value_obj)); + } + + static inline gboolean + major_block_is_evacuating (MSBlockInfo *block) + { + if (evacuate_block_obj_sizes [block->obj_size_index] && + !block->has_pinned && + !block->is_to_space) + return TRUE; + return FALSE; } #define LOAD_VTABLE SGEN_LOAD_VTABLE @@@ -1166,8 -1176,6 +1176,6 @@@ static guint64 stat_drain_prefetch_fill static guint64 stat_drain_loops; #endif - static void major_scan_object_with_evacuation (GCObject *start, mword desc, SgenGrayQueue *queue); - #define COPY_OR_MARK_FUNCTION_NAME major_copy_or_mark_object_no_evacuation #define SCAN_OBJECT_FUNCTION_NAME major_scan_object_no_evacuation #define DRAIN_GRAY_STACK_FUNCTION_NAME drain_gray_stack_no_evacuation @@@ -1221,7 -1229,7 +1229,7 @@@ major_copy_or_mark_object_concurrent_ca static void major_copy_or_mark_object_concurrent_finish_canonical (GCObject **ptr, SgenGrayQueue *queue) { - major_copy_or_mark_object_no_evacuation (ptr, *ptr, queue); + major_copy_or_mark_object_with_evacuation (ptr, *ptr, queue); } static void @@@ -1610,8 -1618,6 +1618,6 @@@ sweep_job_func (void *thread_data_untyp static void sweep_finish (void) { - mword total_evacuate_heap = 0; - mword total_evacuate_saved = 0; int i; for (i = 0; i < num_block_obj_sizes; ++i) { @@@ -1625,16 -1631,8 +1631,8 @@@ } else { evacuate_block_obj_sizes [i] = FALSE; } - { - mword total_bytes = block_obj_sizes [i] * sweep_slots_available [i]; - total_evacuate_heap += total_bytes; - if (evacuate_block_obj_sizes [i]) - total_evacuate_saved += total_bytes - block_obj_sizes [i] * sweep_slots_used [i]; - } } - want_evacuation = (float)total_evacuate_saved / (float)total_evacuate_heap > (1 - concurrent_evacuation_threshold); - set_sweep_state (SWEEP_STATE_SWEPT, SWEEP_STATE_COMPACTING); } @@@ -2411,7 -2409,6 +2409,6 @@@ sgen_marksweep_init_internal (SgenMajor mono_counters_register ("# major blocks allocated", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_alloced); mono_counters_register ("# major blocks freed", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed); mono_counters_register ("# major blocks lazy swept", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_lazy_swept); - mono_counters_register ("# major objects evacuated", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_objects_evacuated); #if SIZEOF_VOID_P != 8 mono_counters_register ("# major blocks freed ideally", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed_ideal); mono_counters_register ("# major blocks freed less ideally", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed_less_ideal); @@@ -2424,10 -2421,6 +2421,6 @@@ concurrent_mark = is_concurrent; collector->is_concurrent = is_concurrent; collector->needs_thread_pool = is_concurrent || concurrent_sweep; - if (is_concurrent) - collector->want_synchronous_collection = &want_evacuation; - else - collector->want_synchronous_collection = NULL; collector->get_and_reset_num_major_objects_marked = major_get_and_reset_num_major_objects_marked; collector->supports_cardtable = TRUE; @@@ -2481,9 -2474,9 +2474,9 @@@ collector->major_ops_concurrent_start.drain_gray_stack = drain_gray_stack_concurrent; collector->major_ops_concurrent_finish.copy_or_mark_object = major_copy_or_mark_object_concurrent_finish_canonical; - collector->major_ops_concurrent_finish.scan_object = major_scan_object_no_evacuation; + collector->major_ops_concurrent_finish.scan_object = major_scan_object_with_evacuation; collector->major_ops_concurrent_finish.scan_vtype = major_scan_vtype_concurrent_finish; - collector->major_ops_concurrent_finish.drain_gray_stack = drain_gray_stack_no_evacuation; + collector->major_ops_concurrent_finish.drain_gray_stack = drain_gray_stack; } #ifdef HEAVY_STATISTICS @@@ -2494,6 -2487,7 +2487,7 @@@ mono_counters_register ("Optimized copy major", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major); mono_counters_register ("Optimized copy major small fast", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_small_fast); mono_counters_register ("Optimized copy major small slow", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_small_slow); + mono_counters_register ("Optimized copy major small evacuate", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_small_evacuate); mono_counters_register ("Optimized copy major large", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_large); mono_counters_register ("Optimized major scan", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_major_scan); mono_counters_register ("Optimized major scan no refs", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_major_scan_no_refs); @@@ -2504,7 -2498,7 +2498,7 @@@ #endif #ifdef SGEN_HEAVY_BINARY_PROTOCOL - mono_mutex_init (&scanned_objects_list_lock); + mono_os_mutex_init (&scanned_objects_list_lock); #endif SGEN_ASSERT (0, SGEN_MAX_SMALL_OBJ_SIZE <= MS_BLOCK_FREE / 2, "MAX_SMALL_OBJ_SIZE must be at most MS_BLOCK_FREE / 2");