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)
23 void *(*start_routine)(void*);
26 MonoSemType registered;
31 inner_start_thread (void *arg)
33 ThreadStartInfo *start_info = arg;
34 void *t_arg = start_info->arg;
36 void *(*start_func)(void*) = start_info->start_routine;
39 mono_thread_info_attach (&result);
41 post_result = MONO_SEM_POST (&(start_info->registered));
42 g_assert (!post_result);
44 result = start_func (t_arg);
45 g_assert (!mono_domain_get ());
52 mono_threads_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
54 ThreadStartInfo *start_info;
57 start_info = g_malloc0 (sizeof (ThreadStartInfo));
60 MONO_SEM_INIT (&(start_info->registered), 0);
61 start_info->arg = arg;
62 start_info->start_routine = start_routine;
64 result = pthread_create (new_thread, attr, inner_start_thread, start_info);
66 while (MONO_SEM_WAIT (&(start_info->registered)) != 0) {
67 /*if (EINTR != errno) ABORT("sem_wait failed"); */
70 MONO_SEM_DESTROY (&(start_info->registered));
75 #if !defined (__MACH__)
78 suspend_signal_handler (int _dummy, siginfo_t *info, void *context)
80 MonoThreadInfo *current = mono_thread_info_current ();
81 gboolean ret = mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (¤t->suspend_state, context);
85 if (current->self_suspend)
86 LeaveCriticalSection (¤t->suspend_lock);
88 MONO_SEM_POST (¤t->suspend_semaphore);
90 while (MONO_SEM_WAIT (¤t->resume_semaphore) != 0) {
91 /*if (EINTR != errno) ABORT("sem_wait failed"); */
94 if (current->async_target) {
95 MonoContext tmp = current->suspend_state.ctx;
96 mono_threads_get_runtime_callbacks ()->setup_async_callback (&tmp, current->async_target, current->user_data);
97 current->async_target = current->user_data = NULL;
98 mono_monoctx_to_sigctx (&tmp, context);
101 MONO_SEM_POST (¤t->finish_resume_semaphore);
105 mono_posix_add_signal_handler (int signo, gpointer handler)
107 /*FIXME, move the code from mini to utils and do the right thing!*/
109 struct sigaction previous_sa;
112 sa.sa_sigaction = handler;
113 sigemptyset (&sa.sa_mask);
114 sa.sa_flags = SA_SIGINFO;
115 ret = sigaction (signo, &sa, &previous_sa);
117 g_assert (ret != -1);
121 mono_threads_init_platform (void)
124 FIXME we should use all macros from mini to make this more portable
125 FIXME it would be very sweet if sgen could end up using this too.
127 if (mono_thread_info_new_interrupt_enabled ())
128 mono_posix_add_signal_handler (mono_thread_get_abort_signal (), suspend_signal_handler);
131 /*nothing to be done here since suspend always abort syscalls due using signals*/
133 mono_threads_core_interrupt (MonoThreadInfo *info)
138 We self suspend using signals since thread_state_init_from_sigctx only supports
139 a null context on a few targets.
142 mono_threads_core_self_suspend (MonoThreadInfo *info)
144 /*FIXME, check return value*/
145 info->self_suspend = TRUE;
146 pthread_kill (mono_thread_info_get_tid (info), mono_thread_get_abort_signal ());
150 mono_threads_core_suspend (MonoThreadInfo *info)
152 /*FIXME, check return value*/
153 info->self_suspend = FALSE;
154 pthread_kill (mono_thread_info_get_tid (info), mono_thread_get_abort_signal ());
155 while (MONO_SEM_WAIT (&info->suspend_semaphore) != 0) {
156 /* g_assert (errno == EINTR); */
162 mono_threads_core_resume (MonoThreadInfo *info)
164 MONO_SEM_POST (&info->resume_semaphore);
165 while (MONO_SEM_WAIT (&info->finish_resume_semaphore) != 0) {
166 /* g_assert (errno == EINTR); */
173 mono_threads_platform_register (MonoThreadInfo *info)
175 MONO_SEM_INIT (&info->suspend_semaphore, 0);
176 MONO_SEM_INIT (&info->resume_semaphore, 0);
177 MONO_SEM_INIT (&info->finish_resume_semaphore, 0);
181 mono_threads_platform_free (MonoThreadInfo *info)
183 MONO_SEM_DESTROY (&info->suspend_semaphore);
184 MONO_SEM_DESTROY (&info->resume_semaphore);
185 MONO_SEM_DESTROY (&info->finish_resume_semaphore);
188 #endif /*!defined (__MACH__)*/