X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Futils%2Fmono-threads-posix.c;h=138cc9e4b6aebd411ea1e0f75b88ce42b1cb5176;hb=746d97a043149d1204e10a3a1944cfe40fa60051;hp=a8a5b53274e95a0041f8ca6cbed2510df8229c40;hpb=4df88aea4b841eed9614455a8b71d4a446a44cc6;p=mono.git diff --git a/mono/utils/mono-threads-posix.c b/mono/utils/mono-threads-posix.c index a8a5b53274e..138cc9e4b6a 100644 --- a/mono/utils/mono-threads-posix.c +++ b/mono/utils/mono-threads-posix.c @@ -1,5 +1,6 @@ -/* - * mono-threads-posix.c: Low-level threading, posix version +/** + * \file + * Low-level threading, posix version * * Author: * Rodrigo Kumpera (kumpera@gmail.com) @@ -15,10 +16,9 @@ #endif #include -#include #include #include -#include +#include #include @@ -30,134 +30,98 @@ extern int tkill (pid_t tid, int signal); #endif -#if defined(_POSIX_VERSION) || defined(__native_client__) +#if defined(_POSIX_VERSION) #include #include -#if defined(__native_client__) -void nacl_shutdown_gc_thread(void); -#endif - -void -mono_threads_platform_register (MonoThreadInfo *info) -{ - gpointer thread_handle; - - thread_handle = mono_w32handle_new (MONO_W32HANDLE_THREAD, NULL); - if (thread_handle == INVALID_HANDLE_VALUE) - g_error ("%s: failed to create handle", __func__); - - g_assert (!info->handle); - info->handle = thread_handle; -} - -int -mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize stack_size, MonoNativeThreadId *out_tid) +gboolean +mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *tid) { pthread_attr_t attr; pthread_t thread; - int policy; - struct sched_param param; gint res; + gsize set_stack_size; res = pthread_attr_init (&attr); - g_assert (!res); + if (res != 0) + g_error ("%s: pthread_attr_init failed, error: \"%s\" (%d)", __func__, g_strerror (res), res); + + if (stack_size) + set_stack_size = *stack_size; + else + set_stack_size = 0; #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE - if (stack_size == 0) { + if (set_stack_size == 0) { #if HAVE_VALGRIND_MEMCHECK_H if (RUNNING_ON_VALGRIND) - stack_size = 1 << 20; + set_stack_size = 1 << 20; else - stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024; + set_stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024; #else - stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024; + set_stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024; #endif } #ifdef PTHREAD_STACK_MIN - if (stack_size < PTHREAD_STACK_MIN) - stack_size = PTHREAD_STACK_MIN; + if (set_stack_size < PTHREAD_STACK_MIN) + set_stack_size = PTHREAD_STACK_MIN; #endif - res = pthread_attr_setstacksize (&attr, stack_size); - g_assert (!res); -#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */ - - memset (¶m, 0, sizeof (param)); - - res = pthread_attr_getschedpolicy (&attr, &policy); + res = pthread_attr_setstacksize (&attr, set_stack_size); if (res != 0) - g_error ("%s: pthread_attr_getschedpolicy failed, error: \"%s\" (%d)", g_strerror (res), res); + g_error ("%s: pthread_attr_setstacksize failed, error: \"%s\" (%d)", __func__, g_strerror (res), res); +#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */ -#ifdef _POSIX_PRIORITY_SCHEDULING - int max, min; + /* Actually start the thread */ + res = mono_gc_pthread_create (&thread, &attr, (gpointer (*)(gpointer)) thread_fn, thread_data); + if (res) { + res = pthread_attr_destroy (&attr); + if (res != 0) + g_error ("%s: pthread_attr_destroy failed, error: \"%s\" (%d)", __func__, g_strerror (res), res); - /* Necessary to get valid priority range */ + return FALSE; + } - min = sched_get_priority_min (policy); - max = sched_get_priority_max (policy); + if (tid) + *tid = thread; - if (max > 0 && min >= 0 && max > min) - param.sched_priority = (max - min) / 2 + min; - else -#endif - { - switch (policy) { - case SCHED_FIFO: - case SCHED_RR: - param.sched_priority = 50; - break; -#ifdef SCHED_BATCH - case SCHED_BATCH: -#endif - case SCHED_OTHER: - param.sched_priority = 0; - break; - default: - g_error ("%s: unknown policy %d", __func__, policy); - } + if (stack_size) { + res = pthread_attr_getstacksize (&attr, stack_size); + if (res != 0) + g_error ("%s: pthread_attr_getstacksize failed, error: \"%s\" (%d)", __func__, g_strerror (res), res); } - res = pthread_attr_setschedparam (&attr, ¶m); + res = pthread_attr_destroy (&attr); if (res != 0) - g_error ("%s: pthread_attr_setschedparam failed, error: \"%s\" (%d)", g_strerror (res), res); - - /* Actually start the thread */ - res = mono_gc_pthread_create (&thread, &attr, (gpointer (*)(gpointer)) thread_fn, thread_data); - if (res) - return -1; + g_error ("%s: pthread_attr_destroy failed, error: \"%s\" (%d)", __func__, g_strerror (res), res); - if (out_tid) - *out_tid = thread; + return TRUE; +} - return 0; +void +mono_threads_platform_init (void) +{ } gboolean -mono_threads_platform_yield (void) +mono_threads_platform_in_critical_region (MonoNativeThreadId tid) { - return sched_yield () == 0; + return FALSE; } -void -mono_threads_platform_exit (int exit_code) +gboolean +mono_threads_platform_yield (void) { -#if defined(__native_client__) - nacl_shutdown_gc_thread(); -#endif - - mono_thread_info_detach (); - - pthread_exit (NULL); + return sched_yield () == 0; } void -mono_threads_platform_unregister (MonoThreadInfo *info) +mono_threads_platform_exit (gsize exit_code) { - mono_threads_platform_set_exited (info); + pthread_exit ((gpointer) exit_code); } int @@ -174,48 +138,33 @@ mono_threads_get_max_stack_size (void) return (int)lim.rlim_max; } -gpointer -mono_threads_platform_duplicate_handle (MonoThreadInfo *info) -{ - g_assert (info->handle); - mono_w32handle_ref (info->handle); - return info->handle; -} - -HANDLE -mono_threads_platform_open_thread_handle (HANDLE handle, MonoNativeThreadId tid) -{ - mono_w32handle_ref (handle); - - return handle; -} - -void -mono_threads_platform_close_thread_handle (HANDLE handle) -{ - mono_w32handle_unref (handle); -} - int mono_threads_pthread_kill (MonoThreadInfo *info, int signum) { THREADS_SUSPEND_DEBUG ("sending signal %d to %p[%p]\n", signum, info, mono_thread_info_get_tid (info)); + + int result; + #ifdef USE_TKILL_ON_ANDROID - int result, old_errno = errno; + int old_errno = errno; + result = tkill (info->native_handle, signum); + if (result < 0) { result = errno; errno = old_errno; } - return result; -#elif defined(__native_client__) - /* Workaround pthread_kill abort() in NaCl glibc. */ - return 0; -#elif !defined(HAVE_PTHREAD_KILL) - g_error ("pthread_kill() is not supported by this platform"); +#elif defined (HAVE_PTHREAD_KILL) + result = pthread_kill (mono_thread_info_get_tid (info), signum); #else - return pthread_kill (mono_thread_info_get_tid (info), signum); + result = -1; + g_error ("pthread_kill () is not supported by this platform"); #endif + + if (result && result != ESRCH) + g_error ("%s: pthread_kill failed with error %d - potential kernel OOM or signal queue overflow", __func__, result); + + return result; } MonoNativeThreadId @@ -257,8 +206,8 @@ mono_native_thread_set_name (MonoNativeThreadId tid, const char *name) } else { char n [63]; - strncpy (n, name, 63); - n [62] = '\0'; + strncpy (n, name, sizeof (n) - 1); + n [sizeof (n) - 1] = '\0'; pthread_setname_np (n); } #elif defined (__NetBSD__) @@ -267,8 +216,8 @@ mono_native_thread_set_name (MonoNativeThreadId tid, const char *name) } else { char n [PTHREAD_MAX_NAMELEN_NP]; - strncpy (n, name, PTHREAD_MAX_NAMELEN_NP); - n [PTHREAD_MAX_NAMELEN_NP - 1] = '\0'; + strncpy (n, name, sizeof (n) - 1); + n [sizeof (n) - 1] = '\0'; pthread_setname_np (tid, "%s", (void*)n); } #elif defined (HAVE_PTHREAD_SETNAME_NP) @@ -277,76 +226,29 @@ mono_native_thread_set_name (MonoNativeThreadId tid, const char *name) } else { char n [16]; - strncpy (n, name, 16); - n [15] = '\0'; + strncpy (n, name, sizeof (n) - 1); + n [sizeof (n) - 1] = '\0'; pthread_setname_np (tid, n); } #endif } -void -mono_threads_platform_set_exited (MonoThreadInfo *info) -{ - int thr_ret; - - g_assert (info->handle); - if (mono_w32handle_issignalled (info->handle)) - g_error ("%s: handle %p thread %p has already exited, it's handle is signalled", __func__, info->handle, mono_thread_info_get_tid (info)); - if (mono_w32handle_get_type (info->handle) == MONO_W32HANDLE_UNUSED) - g_error ("%s: handle %p thread %p has already exited, it's handle type is 'unused'", __func__, info->handle, mono_thread_info_get_tid (info)); - - thr_ret = mono_w32handle_lock_handle (info->handle); - g_assert (thr_ret == 0); - - mono_w32handle_set_signal_state (info->handle, TRUE, TRUE); - - thr_ret = mono_w32handle_unlock_handle (info->handle); - g_assert (thr_ret == 0); - - /* The thread is no longer active, so unref it */ - mono_w32handle_unref (info->handle); - - info->handle = NULL; -} - -static const gchar* thread_typename (void) -{ - return "Thread"; -} - -static gsize thread_typesize (void) -{ - return 0; -} - -static MonoW32HandleOps thread_ops = { - NULL, /* close */ - NULL, /* signal */ - NULL, /* own */ - NULL, /* is_owned */ - NULL, /* special_wait */ - NULL, /* prewait */ - NULL, /* details */ - thread_typename, /* typename */ - thread_typesize, /* typesize */ -}; - -void -mono_threads_platform_init (void) +gboolean +mono_native_thread_join (MonoNativeThreadId tid) { - mono_w32handle_register_ops (MONO_W32HANDLE_THREAD, &thread_ops); + void *res; - mono_w32handle_register_capabilities (MONO_W32HANDLE_THREAD, MONO_W32HANDLE_CAP_WAIT); + return !pthread_join (tid, &res); } -#endif /* defined(_POSIX_VERSION) || defined(__native_client__) */ +#endif /* defined(_POSIX_VERSION) */ #if defined(USE_POSIX_BACKEND) gboolean mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) { - int sig = interrupt_kernel ? mono_threads_posix_get_abort_signal () : mono_threads_posix_get_suspend_signal (); + int sig = interrupt_kernel ? mono_threads_suspend_get_abort_signal () : mono_threads_suspend_get_suspend_signal (); if (!mono_threads_pthread_kill (info, sig)) { mono_threads_add_to_pending_operation_set (info); @@ -370,8 +272,24 @@ This begins async resume. This function must do the following: gboolean mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) { - mono_threads_add_to_pending_operation_set (info); - return mono_threads_pthread_kill (info, mono_threads_posix_get_restart_signal ()) == 0; + int sig = mono_threads_suspend_get_restart_signal (); + + if (!mono_threads_pthread_kill (info, sig)) { + mono_threads_add_to_pending_operation_set (info); + return TRUE; + } + return FALSE; +} + +void +mono_threads_suspend_abort_syscall (MonoThreadInfo *info) +{ + /* We signal a thread to break it from the current syscall. + * This signal should not be interpreted as a suspend request. */ + info->syscall_break_signal = TRUE; + if (mono_threads_pthread_kill (info, mono_threads_suspend_get_abort_signal ()) == 0) { + mono_threads_add_to_pending_operation_set (info); + } } void @@ -390,7 +308,6 @@ mono_threads_suspend_free (MonoThreadInfo *info) void mono_threads_suspend_init (void) { - mono_threads_posix_init_signals (MONO_THREADS_POSIX_INIT_SIGNALS_SUSPEND_RESTART); } #endif /* defined(USE_POSIX_BACKEND) */