2 * mono-threads-posix.c: Low-level threading, posix version
5 * Rodrigo Kumpera (kumpera@gmail.com)
12 #include <mono/utils/mono-compiler.h>
13 #include <mono/utils/mono-semaphore.h>
14 #include <mono/utils/mono-threads.h>
15 #include <mono/utils/mono-tls.h>
16 #include <mono/metadata/threads-types.h>
20 #if defined(_POSIX_VERSION) || defined(__native_client__)
24 void *(*start_routine)(void*);
27 MonoSemType registered;
32 inner_start_thread (void *arg)
34 ThreadStartInfo *start_info = arg;
35 void *t_arg = start_info->arg;
37 void *(*start_func)(void*) = start_info->start_routine;
40 mono_thread_info_attach (&result);
42 post_result = MONO_SEM_POST (&(start_info->registered));
43 g_assert (!post_result);
45 result = start_func (t_arg);
46 g_assert (!mono_domain_get ());
53 mono_threads_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
55 ThreadStartInfo *start_info;
58 start_info = g_malloc0 (sizeof (ThreadStartInfo));
61 MONO_SEM_INIT (&(start_info->registered), 0);
62 start_info->arg = arg;
63 start_info->start_routine = start_routine;
65 result = mono_threads_get_callbacks ()->mono_gc_pthread_create (new_thread, attr, inner_start_thread, start_info);
67 while (MONO_SEM_WAIT (&(start_info->registered)) != 0) {
68 /*if (EINTR != errno) ABORT("sem_wait failed"); */
71 MONO_SEM_DESTROY (&(start_info->registered));
76 #if !defined (__MACH__)
78 #if !defined(__native_client__)
80 suspend_signal_handler (int _dummy, siginfo_t *info, void *context)
82 MonoThreadInfo *current = mono_thread_info_current ();
83 gboolean ret = mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (¤t->suspend_state, context);
87 if (current->self_suspend)
88 LeaveCriticalSection (¤t->suspend_lock);
90 MONO_SEM_POST (¤t->suspend_semaphore);
92 while (MONO_SEM_WAIT (¤t->resume_semaphore) != 0) {
93 /*if (EINTR != errno) ABORT("sem_wait failed"); */
96 if (current->async_target) {
97 #if MONO_ARCH_HAS_MONO_CONTEXT
98 MonoContext tmp = current->suspend_state.ctx;
99 mono_threads_get_runtime_callbacks ()->setup_async_callback (&tmp, current->async_target, current->user_data);
100 current->async_target = current->user_data = NULL;
101 mono_monoctx_to_sigctx (&tmp, context);
103 g_error ("The new interruption machinery requires a working mono-context");
107 MONO_SEM_POST (¤t->finish_resume_semaphore);
112 mono_posix_add_signal_handler (int signo, gpointer handler)
114 #if !defined(__native_client__)
115 /*FIXME, move the code from mini to utils and do the right thing!*/
117 struct sigaction previous_sa;
120 sa.sa_sigaction = handler;
121 sigemptyset (&sa.sa_mask);
122 sa.sa_flags = SA_SIGINFO;
123 ret = sigaction (signo, &sa, &previous_sa);
125 g_assert (ret != -1);
130 mono_threads_init_platform (void)
132 #if !defined(__native_client__)
134 FIXME we should use all macros from mini to make this more portable
135 FIXME it would be very sweet if sgen could end up using this too.
137 if (mono_thread_info_new_interrupt_enabled ())
138 mono_posix_add_signal_handler (mono_thread_get_abort_signal (), suspend_signal_handler);
142 /*nothing to be done here since suspend always abort syscalls due using signals*/
144 mono_threads_core_interrupt (MonoThreadInfo *info)
149 We self suspend using signals since thread_state_init_from_sigctx only supports
150 a null context on a few targets.
153 mono_threads_core_self_suspend (MonoThreadInfo *info)
155 /*FIXME, check return value*/
156 info->self_suspend = TRUE;
157 pthread_kill (mono_thread_info_get_tid (info), mono_thread_get_abort_signal ());
161 mono_threads_core_suspend (MonoThreadInfo *info)
163 /*FIXME, check return value*/
164 info->self_suspend = FALSE;
165 pthread_kill (mono_thread_info_get_tid (info), mono_thread_get_abort_signal ());
166 while (MONO_SEM_WAIT (&info->suspend_semaphore) != 0) {
167 /* g_assert (errno == EINTR); */
173 mono_threads_core_resume (MonoThreadInfo *info)
175 MONO_SEM_POST (&info->resume_semaphore);
176 while (MONO_SEM_WAIT (&info->finish_resume_semaphore) != 0) {
177 /* g_assert (errno == EINTR); */
184 mono_threads_platform_register (MonoThreadInfo *info)
186 MONO_SEM_INIT (&info->suspend_semaphore, 0);
187 MONO_SEM_INIT (&info->resume_semaphore, 0);
188 MONO_SEM_INIT (&info->finish_resume_semaphore, 0);
192 mono_threads_platform_free (MonoThreadInfo *info)
194 MONO_SEM_DESTROY (&info->suspend_semaphore);
195 MONO_SEM_DESTROY (&info->resume_semaphore);
196 MONO_SEM_DESTROY (&info->finish_resume_semaphore);
199 #endif /*!defined (__MACH__)*/