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(PLATFORM_ANDROID)
21 extern int tkill (pid_t tid, int signal);
24 #if defined(_POSIX_VERSION) || defined(__native_client__)
28 void *(*start_routine)(void*);
31 MonoSemType registered;
36 inner_start_thread (void *arg)
38 ThreadStartInfo *start_info = arg;
39 void *t_arg = start_info->arg;
41 void *(*start_func)(void*) = start_info->start_routine;
44 mono_thread_info_attach (&result);
46 post_result = MONO_SEM_POST (&(start_info->registered));
47 g_assert (!post_result);
49 result = start_func (t_arg);
50 g_assert (!mono_domain_get ());
57 mono_threads_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
59 ThreadStartInfo *start_info;
62 start_info = g_malloc0 (sizeof (ThreadStartInfo));
65 MONO_SEM_INIT (&(start_info->registered), 0);
66 start_info->arg = arg;
67 start_info->start_routine = start_routine;
69 result = mono_threads_get_callbacks ()->mono_gc_pthread_create (new_thread, attr, inner_start_thread, start_info);
71 while (MONO_SEM_WAIT (&(start_info->registered)) != 0) {
72 /*if (EINTR != errno) ABORT("sem_wait failed"); */
75 MONO_SEM_DESTROY (&(start_info->registered));
80 #if !defined (__MACH__)
82 #if !defined(__native_client__)
84 suspend_signal_handler (int _dummy, siginfo_t *info, void *context)
86 MonoThreadInfo *current = mono_thread_info_current ();
89 if (current->syscall_break_signal) {
90 current->syscall_break_signal = FALSE;
94 ret = mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (¤t->suspend_state, context);
98 MONO_SEM_POST (¤t->suspend_semaphore);
100 while (MONO_SEM_WAIT (¤t->resume_semaphore) != 0) {
101 /*if (EINTR != errno) ABORT("sem_wait failed"); */
104 if (current->async_target) {
105 #if MONO_ARCH_HAS_MONO_CONTEXT
106 MonoContext tmp = current->suspend_state.ctx;
107 mono_threads_get_runtime_callbacks ()->setup_async_callback (&tmp, current->async_target, current->user_data);
108 current->async_target = current->user_data = NULL;
109 mono_monoctx_to_sigctx (&tmp, context);
111 g_error ("The new interruption machinery requires a working mono-context");
115 MONO_SEM_POST (¤t->finish_resume_semaphore);
120 mono_posix_add_signal_handler (int signo, gpointer handler)
122 #if !defined(__native_client__)
123 /*FIXME, move the code from mini to utils and do the right thing!*/
125 struct sigaction previous_sa;
128 sa.sa_sigaction = handler;
129 sigemptyset (&sa.sa_mask);
130 sa.sa_flags = SA_SIGINFO;
131 ret = sigaction (signo, &sa, &previous_sa);
133 g_assert (ret != -1);
138 mono_threads_init_platform (void)
140 #if !defined(__native_client__)
142 FIXME we should use all macros from mini to make this more portable
143 FIXME it would be very sweet if sgen could end up using this too.
145 if (mono_thread_info_new_interrupt_enabled ())
146 mono_posix_add_signal_handler (mono_thread_get_abort_signal (), suspend_signal_handler);
150 /*nothing to be done here since suspend always abort syscalls due using signals*/
152 mono_threads_core_interrupt (MonoThreadInfo *info)
157 mono_threads_pthread_kill (MonoThreadInfo *info, int signum)
159 #if defined (PLATFORM_ANDROID)
160 int result, old_errno = errno;
161 result = tkill (info->native_handle, signum);
168 return pthread_kill (mono_thread_info_get_tid (info), signum);
174 mono_threads_core_abort_syscall (MonoThreadInfo *info)
177 We signal a thread to break it from the urrent syscall.
178 This signal should not be interpreted as a suspend request.
180 info->syscall_break_signal = TRUE;
181 mono_threads_pthread_kill (info, mono_thread_get_abort_signal ());
185 mono_threads_core_needs_abort_syscall (void)
191 mono_threads_core_suspend (MonoThreadInfo *info)
193 /*FIXME, check return value*/
194 mono_threads_pthread_kill (info, mono_thread_get_abort_signal ());
195 while (MONO_SEM_WAIT (&info->suspend_semaphore) != 0) {
196 /* g_assert (errno == EINTR); */
202 mono_threads_core_resume (MonoThreadInfo *info)
204 MONO_SEM_POST (&info->resume_semaphore);
205 while (MONO_SEM_WAIT (&info->finish_resume_semaphore) != 0) {
206 /* g_assert (errno == EINTR); */
213 mono_threads_platform_register (MonoThreadInfo *info)
215 MONO_SEM_INIT (&info->suspend_semaphore, 0);
217 #if defined (PLATFORM_ANDROID)
218 info->native_handle = (gpointer) gettid ();
223 mono_threads_platform_free (MonoThreadInfo *info)
225 MONO_SEM_DESTROY (&info->suspend_semaphore);
229 mono_native_thread_id_get (void)
231 return pthread_self ();
235 mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2)
237 return pthread_equal (id1, id2);
241 * mono_native_thread_create:
243 * Low level thread creation function without any GC wrappers.
246 mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg)
248 return pthread_create (tid, NULL, func, arg) == 0;
251 #endif /*!defined (__MACH__)*/