diff options
Diffstat (limited to 'mono/metadata/sgen-stw.c')
-rwxr-xr-x | mono/metadata/sgen-stw.c | 37 |
1 files changed, 17 insertions, 20 deletions
diff --git a/mono/metadata/sgen-stw.c b/mono/metadata/sgen-stw.c index 404307a161..54dc218b58 100755 --- a/mono/metadata/sgen-stw.c +++ b/mono/metadata/sgen-stw.c @@ -101,7 +101,7 @@ is_ip_in_managed_allocator (MonoDomain *domain, gpointer ip) if (!ji) return FALSE; - return sgen_is_critical_method (ji->method); + return sgen_is_critical_method (mono_jit_info_get_method (ji)); } static int @@ -117,9 +117,9 @@ restart_threads_until_none_in_managed_allocator (void) allocator */ FOREACH_THREAD_SAFE (info) { gboolean result; - if (info->skip || info->gc_disabled || !info->joined_stw) + if (info->skip || info->gc_disabled) continue; - if (!info->thread_is_dying && (!info->stack_start || info->in_critical_region || info->info.inside_critical_region || + if (mono_thread_info_run_state (info) == STATE_RUNNING && (!info->stack_start || info->in_critical_region || info->info.inside_critical_region || is_ip_in_managed_allocator (info->stopped_domain, info->stopped_ip))) { binary_protocol_thread_restart ((gpointer)mono_thread_info_get_tid (info)); SGEN_LOG (3, "thread %p resumed.", (void*) (size_t) info->info.native_handle); @@ -195,18 +195,6 @@ release_gc_locks (void) UNLOCK_INTERRUPTION; } -static void -stw_bridge_process (void) -{ - sgen_bridge_processing_stw_step (); -} - -static void -bridge_process (int generation) -{ - sgen_bridge_processing_finish (generation); -} - static TV_DECLARE (stop_world_time); static unsigned long max_pause_usec = 0; @@ -269,9 +257,6 @@ sgen_restart_world (int generation, GGTimingInfo *timing) #endif } END_FOREACH_THREAD - stw_bridge_process (); - release_gc_locks (); - count = sgen_thread_handshake (FALSE); TV_GETTIME (end_sw); usec = TV_ELAPSED (stop_world_time, end_sw); @@ -280,9 +265,21 @@ sgen_restart_world (int generation, GGTimingInfo *timing) mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD, generation); MONO_GC_WORLD_RESTART_END (generation); - mono_thread_hazardous_try_free_some (); + /* + * We must release the thread info suspend lock after doing + * the thread handshake. Otherwise, if the GC stops the world + * and a thread is in the process of starting up, but has not + * yet registered (it's not in the thread_list), it is + * possible that the thread does register while the world is + * stopped. When restarting the GC will then try to restart + * said thread, but since it never got the suspend signal, it + * cannot answer the restart signal, so a deadlock results. + */ + release_gc_locks (); + + sgen_try_free_some_memory = TRUE; - bridge_process (generation); + sgen_bridge_processing_finish (generation); TV_GETTIME (end_bridge); bridge_usec = TV_ELAPSED (end_sw, end_bridge); |