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 ();
87 gboolean ret = mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (¤t->suspend_state, context);
91 MONO_SEM_POST (¤t->suspend_semaphore);
93 while (MONO_SEM_WAIT (¤t->resume_semaphore) != 0) {
94 /*if (EINTR != errno) ABORT("sem_wait failed"); */
97 if (current->async_target) {
98 #if MONO_ARCH_HAS_MONO_CONTEXT
99 MonoContext tmp = current->suspend_state.ctx;
100 mono_threads_get_runtime_callbacks ()->setup_async_callback (&tmp, current->async_target, current->user_data);
101 current->async_target = current->user_data = NULL;
102 mono_monoctx_to_sigctx (&tmp, context);
104 g_error ("The new interruption machinery requires a working mono-context");
108 MONO_SEM_POST (¤t->finish_resume_semaphore);
113 mono_posix_add_signal_handler (int signo, gpointer handler)
115 #if !defined(__native_client__)
116 /*FIXME, move the code from mini to utils and do the right thing!*/
118 struct sigaction previous_sa;
121 sa.sa_sigaction = handler;
122 sigemptyset (&sa.sa_mask);
123 sa.sa_flags = SA_SIGINFO;
124 ret = sigaction (signo, &sa, &previous_sa);
126 g_assert (ret != -1);
131 mono_threads_init_platform (void)
133 #if !defined(__native_client__)
135 FIXME we should use all macros from mini to make this more portable
136 FIXME it would be very sweet if sgen could end up using this too.
138 if (mono_thread_info_new_interrupt_enabled ())
139 mono_posix_add_signal_handler (mono_thread_get_abort_signal (), suspend_signal_handler);
143 /*nothing to be done here since suspend always abort syscalls due using signals*/
145 mono_threads_core_interrupt (MonoThreadInfo *info)
150 mono_threads_pthread_kill (MonoThreadInfo *info, int signum)
152 #if defined (PLATFORM_ANDROID)
153 int result, old_errno = errno;
154 result = tkill (info->native_handle, signum);
161 return pthread_kill (mono_thread_info_get_tid (info), signum);
167 mono_threads_core_suspend (MonoThreadInfo *info)
169 /*FIXME, check return value*/
170 mono_threads_pthread_kill (info, mono_thread_get_abort_signal ());
171 while (MONO_SEM_WAIT (&info->suspend_semaphore) != 0) {
172 /* g_assert (errno == EINTR); */
178 mono_threads_core_resume (MonoThreadInfo *info)
180 MONO_SEM_POST (&info->resume_semaphore);
181 while (MONO_SEM_WAIT (&info->finish_resume_semaphore) != 0) {
182 /* g_assert (errno == EINTR); */
189 mono_threads_platform_register (MonoThreadInfo *info)
191 MONO_SEM_INIT (&info->suspend_semaphore, 0);
193 #if defined (PLATFORM_ANDROID)
194 info->native_handle = (gpointer) gettid ();
199 mono_threads_platform_free (MonoThreadInfo *info)
201 MONO_SEM_DESTROY (&info->suspend_semaphore);
205 mono_native_thread_id_get (void)
207 return pthread_self ();
211 mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2)
213 return pthread_equal (id1, id2);
217 * mono_native_thread_create:
219 * Low level thread creation function without any GC wrappers.
222 mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg)
224 return pthread_create (tid, NULL, func, arg) == 0;
227 #endif /*!defined (__MACH__)*/