[coop] Do not allow transition on not-attached, not-current and not-live thread
authorLudovic Henry <ludovic@xamarin.com>
Mon, 30 May 2016 16:42:48 +0000 (18:42 +0200)
committerLudovic Henry <ludovic@xamarin.com>
Thu, 2 Jun 2016 21:25:31 +0000 (23:25 +0200)
mono/utils/mono-threads-coop.c
mono/utils/mono-threads.c
mono/utils/mono-threads.h

index c25d0959e861106fcb5553585112ef28b682721e..36f8b441d1e03e7641a988a2161e3e7d44bd3c77 100644 (file)
@@ -86,6 +86,17 @@ coop_tls_pop (gpointer received_cookie)
 
 #endif
 
+static void
+check_info (MonoThreadInfo *info, const gchar *action, const gchar *state)
+{
+       if (!info)
+               g_error ("Cannot %s GC %s region if the thread is not attached", action, state);
+       if (!mono_thread_info_is_current (info))
+               g_error ("[%p] Cannot %s GC %s region on a different thread", mono_thread_info_get_tid (info), action, state);
+       if (!mono_thread_info_is_live (info))
+               g_error ("[%p] Cannot %s GC %s region if the thread is not live", mono_thread_info_get_tid (info), action, state);
+}
+
 static int coop_reset_blocking_count;
 static int coop_try_blocking_count;
 static int coop_do_blocking_count;
@@ -190,12 +201,7 @@ mono_threads_enter_gc_safe_region_unbalanced (gpointer *stackdata)
 
        ++coop_do_blocking_count;
 
-       info = mono_thread_info_current_unchecked ();
-       /* If the thread is not attached, it doesn't make sense prepare for suspend. */
-       if (!info || !mono_thread_info_is_live (info)) {
-               THREADS_SUSPEND_DEBUG ("PREPARE-BLOCKING failed %p\n", info ? mono_thread_info_get_tid (info) : NULL);
-               return NULL;
-       }
+       check_info (info, "enter", "safe");
 
        copy_stack_data (info, stackdata);
 
@@ -237,10 +243,8 @@ mono_threads_exit_gc_safe_region_unbalanced (gpointer cookie, gpointer *stackdat
                return;
 
        info = (MonoThreadInfo *)cookie;
-       if (!info)
-               return;
 
-       g_assert (info == mono_thread_info_current_unchecked ());
+       check_info (info, "exit", "safe");
 
        switch (mono_threads_transition_done_blocking (info)) {
        case DoneBlockingOk:
@@ -289,11 +293,7 @@ mono_threads_enter_gc_unsafe_region_unbalanced (gpointer *stackdata)
 
        ++coop_reset_blocking_count;
 
-       info = mono_thread_info_current_unchecked ();
-
-       /* If the thread is not attached, it doesn't make sense prepare for suspend. */
-       if (!info || !mono_thread_info_is_live (info))
-               return NULL;
+       check_info (info, "enter", "unsafe");
 
        copy_stack_data (info, stackdata);
 
index 1919a00bc965d421efb0042e02ddfc4bd98ffb40..4fc4f5e64bab88434bf9f63803c6be9e0493da98 100644 (file)
@@ -1509,3 +1509,9 @@ mono_thread_info_describe_interrupt_token (MonoThreadInfo *info, GString *text)
        else
                g_string_append_printf (text, "waiting");
 }
+
+gboolean
+mono_thread_info_is_current (MonoThreadInfo *info)
+{
+       return mono_thread_info_get_tid (info) == mono_native_thread_id_get ();
+}
index a6f753222bbf60238a5a76e55a948b1f8766a5fe..7b66ce76bae13181b9accc01b0ce6bd7df86a0d4 100644 (file)
@@ -627,4 +627,7 @@ gboolean mono_threads_wait_pending_operations (void);
 void mono_threads_begin_global_suspend (void);
 void mono_threads_end_global_suspend (void);
 
+gboolean
+mono_thread_info_is_current (THREAD_INFO_TYPE *info);
+
 #endif /* __MONO_THREADS_H__ */