2 * mono-threads.c: Coop threading
5 * Rodrigo Kumpera (kumpera@gmail.com)
7 * Copyright 2015 Xamarin, Inc (http://www.xamarin.com)
10 #include <mono/utils/mono-compiler.h>
11 #include <mono/utils/mono-semaphore.h>
12 #include <mono/utils/mono-threads.h>
13 #include <mono/utils/mono-tls.h>
14 #include <mono/utils/hazard-pointer.h>
15 #include <mono/utils/mono-memory-model.h>
16 #include <mono/utils/mono-mmap.h>
17 #include <mono/utils/atomic.h>
18 #include <mono/utils/mono-time.h>
20 #ifdef USE_COOP_BACKEND
24 mono_threads_state_poll (void)
28 info = mono_thread_info_current_unchecked ();
31 THREADS_SUSPEND_DEBUG ("FINISH SELF SUSPEND OF %p\n", mono_thread_info_get_tid (info));
33 /* Fast check for pending suspend requests */
34 if (!(info->thread_state & (STATE_ASYNC_SUSPEND_REQUESTED | STATE_SELF_SUSPEND_REQUESTED)))
37 g_assert (mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (&info->thread_saved_state [SELF_SUSPEND_STATE_INDEX], NULL));
39 /* commit the saved state and notify others if needed */
40 switch (mono_threads_transition_state_poll (info)) {
41 case SelfSuspendResumed:
44 mono_thread_info_wait_for_resume (info);
46 case SelfSuspendNotifyAndWait:
47 mono_threads_notify_initiator_of_suspend (info);
48 mono_thread_info_wait_for_resume (info);
54 mono_threads_prepare_blocking (void)
58 info = mono_thread_info_current_unchecked ();
59 /* If the thread is not attached, it doesn't make sense prepare for suspend. */
60 if (!info || !mono_thread_info_is_live (info)) {
61 THREADS_SUSPEND_DEBUG ("PREPARE-BLOCKING failed %p\n", mono_thread_info_get_tid (info));
66 /*The JIT might not be able to save*/
67 if (!mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (&info->thread_saved_state [SELF_SUSPEND_STATE_INDEX], NULL)) {
68 THREADS_SUSPEND_DEBUG ("PREPARE-BLOCKING failed %p to save thread state\n", mono_thread_info_get_tid (info));
72 switch (mono_threads_transition_do_blocking (info)) {
73 case DoBlockingContinue:
75 case DoBlockingPollAndRetry:
76 mono_threads_state_poll ();
84 mono_threads_finish_blocking (void *cookie)
86 static gboolean warned_about_bad_transition;
87 MonoThreadInfo *info = cookie;
92 g_assert (info == mono_thread_info_current_unchecked ());
94 switch (mono_threads_transition_done_blocking (info)) {
95 case DoneBlockingAborted:
96 if (!warned_about_bad_transition) {
97 warned_about_bad_transition = TRUE;
98 g_warning ("[%p] Blocking call ended in running state for, this might lead to unbound GC pauses.", mono_thread_info_get_tid (info));
100 mono_threads_state_poll ();
103 info->thread_saved_state [SELF_SUSPEND_STATE_INDEX].valid = FALSE;
105 case DoneBlockingWait:
106 THREADS_SUSPEND_DEBUG ("state polling done, notifying of resume\n");
107 mono_thread_info_wait_for_resume (info);
110 g_error ("Unknown thread state");
116 mono_threads_reset_blocking_start (void)
118 MonoThreadInfo *info = mono_thread_info_current_unchecked ();
120 /* If the thread is not attached, it doesn't make sense prepare for suspend. */
121 if (!info || !mono_thread_info_is_live (info))
124 switch (mono_threads_transition_abort_blocking (info)) {
125 case AbortBlockingIgnore:
126 info->thread_saved_state [SELF_SUSPEND_STATE_INDEX].valid = FALSE;
128 case AbortBlockingIgnoreAndPoll:
129 mono_threads_state_poll ();
131 case AbortBlockingOk:
132 info->thread_saved_state [SELF_SUSPEND_STATE_INDEX].valid = FALSE;
134 case AbortBlockingOkAndPool:
135 mono_threads_state_poll ();
138 g_error ("Unknown thread state");
143 mono_threads_reset_blocking_end (void *cookie)
145 MonoThreadInfo *info = cookie;
150 g_assert (info == mono_thread_info_current_unchecked ());
151 mono_threads_prepare_blocking ();
156 mono_threads_core_abort_syscall (MonoThreadInfo *info)
162 mono_threads_core_begin_async_resume (MonoThreadInfo *info)
169 mono_threads_core_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel)
171 mono_threads_add_to_pending_operation_set (info);
172 /* There's nothing else to do after we async request the thread to suspend */
177 mono_threads_core_check_suspend_result (MonoThreadInfo *info)
179 /* Async suspend can't async fail on coop */
184 mono_threads_core_needs_abort_syscall (void)
188 Syscall abort can't be handled by the suspend machinery even though it's kind of implemented
189 in a similar way (with, like, signals).
191 So, having it here is wrong, it should be on mono-threads-(mach|posix|windows).
192 Ideally we would slice this in (coop|preemp) and target. Then have this file set:
193 mono-threads-mach, mono-threads-mach-preempt and mono-threads-mach-coop.
194 More files, less ifdef hell.
200 mono_threads_init_platform (void)
202 //See the above for what's wrong here.
206 mono_threads_platform_free (MonoThreadInfo *info)
208 //See the above for what's wrong here.
212 mono_threads_platform_register (MonoThreadInfo *info)
214 //See the above for what's wrong here.