summaryrefslogtreecommitdiff
path: root/mono/metadata/sgen-stw.c
diff options
context:
space:
mode:
Diffstat (limited to 'mono/metadata/sgen-stw.c')
-rwxr-xr-xmono/metadata/sgen-stw.c37
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);