void mono_threads_state_poll (void) { MonoThreadInfo *info; g_assert (mono_threads_is_coop_enabled ()); ++coop_do_polling_count; info = mono_thread_info_current_unchecked (); if (!info) return; THREADS_SUSPEND_DEBUG ("FINISH SELF SUSPEND OF %p\n", mono_thread_info_get_tid (info)); /* Fast check for pending suspend requests */ if (!(info->thread_state & (STATE_ASYNC_SUSPEND_REQUESTED | STATE_SELF_SUSPEND_REQUESTED))) return; ++coop_save_count; mono_threads_get_runtime_callbacks ()->thread_state_init (&info->thread_saved_state [SELF_SUSPEND_STATE_INDEX]); /* commit the saved state and notify others if needed */ switch (mono_threads_transition_state_poll (info)) { case SelfSuspendResumed: return; case SelfSuspendWait: mono_thread_info_wait_for_resume (info); break; case SelfSuspendNotifyAndWait: mono_threads_notify_initiator_of_suspend (info); mono_thread_info_wait_for_resume (info); break; } }
void mono_thread_info_end_self_suspend (void) { MonoThreadInfo *info; info = mono_thread_info_current (); if (!info) return; THREADS_SUSPEND_DEBUG ("FINISH SELF SUSPEND OF %p\n", info); mono_threads_get_runtime_callbacks ()->thread_state_init (&info->thread_saved_state [SELF_SUSPEND_STATE_INDEX]); /* commit the saved state and notify others if needed */ switch (mono_threads_transition_state_poll (info)) { case SelfSuspendResumed: return; case SelfSuspendWait: mono_thread_info_wait_for_resume (info); break; case SelfSuspendNotifyAndWait: mono_threads_notify_initiator_of_suspend (info); mono_thread_info_wait_for_resume (info); mono_threads_notify_initiator_of_resume (info); break; } }
void mono_threads_finish_blocking (void *cookie, void* stackdata) { static gboolean warned_about_bad_transition; MonoThreadInfo *info; if (!mono_threads_is_coop_enabled ()) return; info = cookie; if (!info) return; g_assert (info == mono_thread_info_current_unchecked ()); switch (mono_threads_transition_done_blocking (info)) { case DoneBlockingAborted: if (!warned_about_bad_transition) { warned_about_bad_transition = TRUE; g_warning ("[%p] Blocking call ended in running state for, this might lead to unbound GC pauses.", mono_thread_info_get_tid (info)); } mono_threads_state_poll (); break; case DoneBlockingOk: info->thread_saved_state [SELF_SUSPEND_STATE_INDEX].valid = FALSE; break; case DoneBlockingWait: THREADS_SUSPEND_DEBUG ("state polling done, notifying of resume\n"); mono_thread_info_wait_for_resume (info); break; default: g_error ("Unknown thread state"); } }
gpointer mono_threads_enter_gc_unsafe_region_unbalanced_with_info (MonoThreadInfo *info, gpointer *stackdata) { if (!mono_threads_is_coop_enabled ()) return NULL; ++coop_reset_blocking_count; check_info (info, "enter", "unsafe"); copy_stack_data (info, stackdata); switch (mono_threads_transition_abort_blocking (info)) { case AbortBlockingIgnore: info->thread_saved_state [SELF_SUSPEND_STATE_INDEX].valid = FALSE; return NULL; case AbortBlockingIgnoreAndPoll: mono_threads_state_poll_with_info (info); return NULL; case AbortBlockingOk: info->thread_saved_state [SELF_SUSPEND_STATE_INDEX].valid = FALSE; break; case AbortBlockingWait: mono_thread_info_wait_for_resume (info); break; default: g_error ("Unknown thread state"); } return info; }
void mono_threads_exit_gc_safe_region_unbalanced (gpointer cookie, gpointer *stackdata) { MonoThreadInfo *info; if (!mono_threads_is_coop_enabled ()) return; info = (MonoThreadInfo *)cookie; check_info (info, "exit", "safe"); switch (mono_threads_transition_done_blocking (info)) { case DoneBlockingOk: info->thread_saved_state [SELF_SUSPEND_STATE_INDEX].valid = FALSE; break; case DoneBlockingWait: THREADS_SUSPEND_DEBUG ("state polling done, notifying of resume\n"); mono_thread_info_wait_for_resume (info); break; default: g_error ("Unknown thread state"); } }