X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Futils%2Fmono-threads-mach.c;h=fdf18bb1891eeb47c08ec7e6176341912fe57b03;hb=8784e2e1cbbd88b4872536d3a8077702dc547216;hp=6f2ddfa78af52357be210b50a2a43c3a73526b52;hpb=4e4013721304d8da777f3137a9857e387c7cf548;p=mono.git diff --git a/mono/utils/mono-threads-mach.c b/mono/utils/mono-threads-mach.c index 6f2ddfa78af..fdf18bb1891 100644 --- a/mono/utils/mono-threads-mach.c +++ b/mono/utils/mono-threads-mach.c @@ -23,9 +23,10 @@ #include #include #include +#include void -mono_threads_init_platform (void) +mono_threads_suspend_init (void) { mono_threads_init_dead_letter (); } @@ -33,75 +34,91 @@ mono_threads_init_platform (void) #if defined(HOST_WATCHOS) || defined(HOST_TVOS) gboolean -mono_threads_core_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) +mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) { g_assert_not_reached (); } gboolean -mono_threads_core_check_suspend_result (MonoThreadInfo *info) +mono_threads_suspend_check_suspend_result (MonoThreadInfo *info) { g_assert_not_reached (); } gboolean -mono_threads_core_begin_async_resume (MonoThreadInfo *info) +mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) { g_assert_not_reached (); } +void +mono_threads_suspend_abort_syscall (MonoThreadInfo *info) +{ + g_assert_not_reached (); +} + +gboolean +mono_threads_suspend_needs_abort_syscall (void) +{ + return FALSE; +} + #else /* defined(HOST_WATCHOS) || defined(HOST_TVOS) */ gboolean -mono_threads_core_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) +mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) { kern_return_t ret; - gboolean res; g_assert (info); - ret = thread_suspend (info->native_handle); - THREADS_SUSPEND_DEBUG ("SUSPEND %p -> %d\n", (void*)info->native_handle, ret); + + do { + ret = thread_suspend (info->native_handle); + } while (ret == KERN_ABORTED); + + THREADS_SUSPEND_DEBUG ("SUSPEND %p -> %d\n", (gpointer)(gsize)info->native_handle, ret); if (ret != KERN_SUCCESS) return FALSE; /* We're in the middle of a self-suspend, resume and register */ if (!mono_threads_transition_finish_async_suspend (info)) { mono_threads_add_to_pending_operation_set (info); - g_assert (thread_resume (info->native_handle) == KERN_SUCCESS); - THREADS_SUSPEND_DEBUG ("FAILSAFE RESUME/1 %p -> %d\n", (void*)info->native_handle, 0); + do { + ret = thread_resume (info->native_handle); + } while (ret == KERN_ABORTED); + g_assert (ret == KERN_SUCCESS); + THREADS_SUSPEND_DEBUG ("FAILSAFE RESUME/1 %p -> %d\n", (gpointer)(gsize)info->native_handle, 0); //XXX interrupt_kernel doesn't make sense in this case as the target is not in a syscall return TRUE; } - res = mono_threads_get_runtime_callbacks ()-> + info->suspend_can_continue = mono_threads_get_runtime_callbacks ()-> thread_state_init_from_handle (&info->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX], info); - THREADS_SUSPEND_DEBUG ("thread state %p -> %d\n", (void*)info->native_handle, res); - if (res) { + THREADS_SUSPEND_DEBUG ("thread state %p -> %d\n", (gpointer)(gsize)info->native_handle, ret); + if (info->suspend_can_continue) { if (interrupt_kernel) thread_abort (info->native_handle); } else { - mono_threads_transition_async_suspend_compensation (info); - g_assert (thread_resume (info->native_handle) == KERN_SUCCESS); - THREADS_SUSPEND_DEBUG ("FAILSAFE RESUME/2 %p -> %d\n", (void*)info->native_handle, 0); + THREADS_SUSPEND_DEBUG ("FAILSAFE RESUME/2 %p -> %d\n", (gpointer)(gsize)info->native_handle, 0); } - return res; + return TRUE; } gboolean -mono_threads_core_check_suspend_result (MonoThreadInfo *info) +mono_threads_suspend_check_suspend_result (MonoThreadInfo *info) { - return TRUE; + return info->suspend_can_continue; } gboolean -mono_threads_core_begin_async_resume (MonoThreadInfo *info) +mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) { kern_return_t ret; if (info->async_target) { MonoContext tmp = info->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX].ctx; - mach_msg_type_number_t num_state; - thread_state_t state; + mach_msg_type_number_t num_state, num_fpstate; + thread_state_t state, fpstate; ucontext_t uctx; mcontext_t mctx; @@ -110,33 +127,82 @@ mono_threads_core_begin_async_resume (MonoThreadInfo *info) info->async_target = (void (*)(void *)) info->user_data; state = (thread_state_t) alloca (mono_mach_arch_get_thread_state_size ()); + fpstate = (thread_state_t) alloca (mono_mach_arch_get_thread_fpstate_size ()); mctx = (mcontext_t) alloca (mono_mach_arch_get_mcontext_size ()); - ret = mono_mach_arch_get_thread_state (info->native_handle, state, &num_state); + do { + ret = mono_mach_arch_get_thread_states (info->native_handle, state, &num_state, fpstate, &num_fpstate); + } while (ret == KERN_ABORTED); + if (ret != KERN_SUCCESS) return FALSE; - mono_mach_arch_thread_state_to_mcontext (state, mctx); + mono_mach_arch_thread_states_to_mcontext (state, fpstate, mctx); uctx.uc_mcontext = mctx; mono_monoctx_to_sigctx (&tmp, &uctx); - mono_mach_arch_mcontext_to_thread_state (mctx, state); + mono_mach_arch_mcontext_to_thread_states (mctx, state, fpstate); + + do { + ret = mono_mach_arch_set_thread_states (info->native_handle, state, num_state, fpstate, num_fpstate); + } while (ret == KERN_ABORTED); - ret = mono_mach_arch_set_thread_state (info->native_handle, state, num_state); if (ret != KERN_SUCCESS) return FALSE; } - ret = thread_resume (info->native_handle); - THREADS_SUSPEND_DEBUG ("RESUME %p -> %d\n", (void*)info->native_handle, ret); + do { + ret = thread_resume (info->native_handle); + } while (ret == KERN_ABORTED); + THREADS_SUSPEND_DEBUG ("RESUME %p -> %d\n", (gpointer)(gsize)info->native_handle, ret); return ret == KERN_SUCCESS; } +void +mono_threads_suspend_abort_syscall (MonoThreadInfo *info) +{ + kern_return_t ret; + + do { + ret = thread_suspend (info->native_handle); + } while (ret == KERN_ABORTED); + + if (ret != KERN_SUCCESS) + return; + + do { + ret = thread_abort_safely (info->native_handle); + } while (ret == KERN_ABORTED); + + /* + * We are doing thread_abort when thread_abort_safely returns KERN_SUCCESS because + * for some reason accept is not interrupted by thread_abort_safely. + * The risk of aborting non-atomic operations while calling thread_abort should not + * exist because by the time thread_abort_safely returns KERN_SUCCESS the target + * thread should have return from the kernel and should be waiting for thread_resume + * to resume the user code. + */ + if (ret == KERN_SUCCESS) + ret = thread_abort (info->native_handle); + + do { + ret = thread_resume (info->native_handle); + } while (ret == KERN_ABORTED); + + g_assert (ret == KERN_SUCCESS); +} + +gboolean +mono_threads_suspend_needs_abort_syscall (void) +{ + return TRUE; +} + #endif /* defined(HOST_WATCHOS) || defined(HOST_TVOS) */ void -mono_threads_platform_register (MonoThreadInfo *info) +mono_threads_suspend_register (MonoThreadInfo *info) { char thread_name [64]; @@ -149,16 +215,45 @@ mono_threads_platform_register (MonoThreadInfo *info) } void -mono_threads_platform_free (MonoThreadInfo *info) +mono_threads_suspend_free (MonoThreadInfo *info) { mach_port_deallocate (current_task (), info->native_handle); } +void +mono_threads_suspend_init_signals (void) +{ +} + +gint +mono_threads_suspend_search_alternative_signal (void) +{ + g_assert_not_reached (); +} + +gint +mono_threads_suspend_get_suspend_signal (void) +{ + return -1; +} + +gint +mono_threads_suspend_get_restart_signal (void) +{ + return -1; +} + +gint +mono_threads_suspend_get_abort_signal (void) +{ + return -1; +} + #endif /* USE_MACH_BACKEND */ #ifdef __MACH__ void -mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) +mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize) { *staddr = (guint8*)pthread_get_stackaddr_np (pthread_self()); *stsize = pthread_get_stacksize_np (pthread_self());