Merge pull request #5459 from HinTak/patch-5
[mono.git] / mono / utils / mono-threads-state-machine.c
index 4b11800c818411a1a6f8b469c0c05e651ea89768..1518438babbb9a99d2f1844bf65b3a35888d8bd0 100644 (file)
@@ -1,3 +1,7 @@
+/**
+ * \file
+ */
+
 #include <config.h>
 
 #include <mono/utils/mono-compiler.h>
@@ -6,6 +10,7 @@
 #include <mono/utils/mono-memory-model.h>
 #include <mono/utils/atomic.h>
 #include <mono/utils/checked-build.h>
+#include <mono/utils/mono-threads-debug.h>
 
 #include <errno.h>
 
@@ -155,50 +160,6 @@ STATE_BLOCKING_AND_SUSPENDED: This is a bug in coop x suspend that resulted the
        }
 }
 
-/*
-This transition initiates the suspension of the current thread.
-*/
-void
-mono_threads_transition_request_self_suspension (MonoThreadInfo *info)
-{
-       int raw_state, cur_state, suspend_count;
-       g_assert (info ==  mono_thread_info_current ());
-
-retry_state_change:
-       UNWRAP_THREAD_STATE (raw_state, cur_state, suspend_count, info);
-
-       switch (cur_state) {
-       case STATE_RUNNING: //Post a self suspend request
-               if (!(suspend_count == 0))
-                       mono_fatal_with_history ("suspend_count = %d, but should be == 0", suspend_count);
-               if (InterlockedCompareExchange (&info->thread_state, build_thread_state (STATE_SELF_SUSPEND_REQUESTED, 1), raw_state) != raw_state)
-                       goto retry_state_change;
-               trace_state_change ("SELF_SUSPEND_REQUEST", info, raw_state, STATE_SELF_SUSPEND_REQUESTED, 1);
-               break;
-
-       case STATE_ASYNC_SUSPEND_REQUESTED: //Bump the suspend count but don't change the request type as async takes preference
-               if (!(suspend_count > 0 && suspend_count < THREAD_SUSPEND_COUNT_MAX))
-                       mono_fatal_with_history ("suspend_count = %d, but should be > 0 and < THREAD_SUSPEND_COUNT_MAX", suspend_count);
-               if (InterlockedCompareExchange (&info->thread_state, build_thread_state (cur_state, suspend_count + 1), raw_state) != raw_state)
-                       goto retry_state_change;
-               trace_state_change ("SUSPEND_REQUEST", info, raw_state, cur_state, 1);
-               break;
-/*
-Other states:
-STATE_ASYNC_SUSPENDED: Code should not be running while suspended.
-STATE_SELF_SUSPENDED: Code should not be running while suspended.
-STATE_SELF_SUSPEND_REQUESTED: Self suspends should not nest as begin/end should be paired. [1]
-STATE_BLOCKING:
-STATE_BLOCKING_AND_SUSPENDED: Self suspension cannot be started when the thread is in blocking state as it must finish first
-
-[1] This won't trap this sequence of requests: self suspend, async suspend and self suspend. 
-If this turns to be an issue we can introduce a new suspend request state for when both have been requested.
-*/
-       default:
-               mono_fatal_with_history ("Cannot transition thread %p from %s with SUSPEND_REQUEST", mono_thread_info_get_tid (info), state_name (cur_state));
-       }
-}
-
 /*
 This transition initiates the suspension of another thread.
 
@@ -282,7 +243,7 @@ MonoSelfSupendResult
 mono_threads_transition_state_poll (MonoThreadInfo *info)
 {
        int raw_state, cur_state, suspend_count;
-       g_assert (info == mono_thread_info_current ());
+       g_assert (mono_thread_info_is_current (info));
 
 retry_state_change:
        UNWRAP_THREAD_STATE (raw_state, cur_state, suspend_count, info);
@@ -519,11 +480,6 @@ mono_threads_transition_done_blocking (MonoThreadInfo* info)
 retry_state_change:
        UNWRAP_THREAD_STATE (raw_state, cur_state, suspend_count, info);
        switch (cur_state) {
-       case STATE_RUNNING: //Blocking was aborted and not properly restored
-       case STATE_ASYNC_SUSPEND_REQUESTED: //Blocking was aborted, not properly restored and now there's a pending suspend
-               trace_state_change ("DONE_BLOCKING", info, raw_state, cur_state, 0);
-               return DoneBlockingAborted;
-
        case STATE_BLOCKING:
                if (suspend_count == 0) {
                        if (InterlockedCompareExchange (&info->thread_state, build_thread_state (STATE_RUNNING, suspend_count), raw_state) != raw_state)
@@ -540,6 +496,8 @@ retry_state_change:
                }
 
 /*
+STATE_RUNNING: //Blocking was aborted and not properly restored
+STATE_ASYNC_SUSPEND_REQUESTED: //Blocking was aborted, not properly restored and now there's a pending suspend
 STATE_ASYNC_SUSPENDED
 STATE_SELF_SUSPENDED: Code should not be running while suspended.
 STATE_SELF_SUSPEND_REQUESTED: A blocking operation must not be done while trying to self suspend
@@ -675,3 +633,21 @@ mono_thread_state_name (int state)
 {
        return state_name (state);
 }
+
+gboolean
+mono_thread_is_gc_unsafe_mode (void)
+{
+       MonoThreadInfo *cur = mono_thread_info_current ();
+
+       if (!cur)
+               return FALSE;
+
+       switch (mono_thread_info_current_state (cur)) {
+       case STATE_RUNNING:
+       case STATE_ASYNC_SUSPEND_REQUESTED:
+       case STATE_SELF_SUSPEND_REQUESTED:
+               return TRUE;
+       default:
+               return FALSE;
+       }
+}