[coop] Move syscall abort mechanism to dedicated files
authorLudovic Henry <ludovic@xamarin.com>
Tue, 15 Sep 2015 12:39:27 +0000 (13:39 +0100)
committerLudovic Henry <ludovic@xamarin.com>
Thu, 24 Sep 2015 10:17:12 +0000 (11:17 +0100)
13 files changed:
mono/utils/Makefile.am
mono/utils/mono-threads-coop.c
mono/utils/mono-threads-mach-abort-syscall.c [new file with mode: 0644]
mono/utils/mono-threads-mach.c
mono/utils/mono-threads-posix-abort-syscall.c [new file with mode: 0644]
mono/utils/mono-threads-posix-signals.c [new file with mode: 0644]
mono/utils/mono-threads-posix-signals.h [new file with mode: 0644]
mono/utils/mono-threads-posix.c
mono/utils/mono-threads-windows-abort-syscall.c [new file with mode: 0644]
mono/utils/mono-threads-windows.c
mono/utils/mono-threads.c
mono/utils/mono-threads.h
msvc/libmonoutils.vcxproj

index e1b1034327e1db36902cac3fce48c32a566a99b7..c1f632eba51d9f35abd65bfd617a98d4da706004 100644 (file)
@@ -101,6 +101,8 @@ monoutils_sources = \
        mono-threads.c  \
        mono-threads-state-machine.c    \
        mono-threads-posix.c    \
+       mono-threads-posix-signals.c    \
+       mono-threads-posix-signals.h    \
        mono-threads-mach.c     \
        mono-threads-mach-helper.c      \
        mono-threads-windows.c  \
@@ -112,6 +114,9 @@ monoutils_sources = \
        mono-threads-api.h      \
        mono-threads-coop.c     \
        mono-threads-coop.h     \
+       mono-threads-mach-abort-syscall.c       \
+       mono-threads-posix-abort-syscall.c      \
+       mono-threads-windows-abort-syscall.c    \
        mono-tls.h      \
        mono-tls.c      \
        linux_magic.h   \
index 4c9826aa767dd4ce4c61080dfc785706744cf40f..3817a925fab7d992e905cbb9287b480612dcc372 100644 (file)
@@ -194,12 +194,6 @@ mono_threads_finish_try_blocking (void* cookie)
        mono_threads_finish_blocking (cookie);
 }
 
-void
-mono_threads_core_abort_syscall (MonoThreadInfo *info)
-{
-       g_error ("FIXME");
-}
-
 gboolean
 mono_threads_core_begin_async_resume (MonoThreadInfo *info)
 {
@@ -222,22 +216,6 @@ mono_threads_core_check_suspend_result (MonoThreadInfo *info)
        return TRUE;
 }
 
-gboolean
-mono_threads_core_needs_abort_syscall (void)
-{
-       /*
-       Small digression.
-       Syscall abort can't be handled by the suspend machinery even though it's kind of implemented
-       in a similar way (with, like, signals).
-
-       So, having it here is wrong, it should be on mono-threads-(mach|posix|windows).
-       Ideally we would slice this in (coop|preemp) and target. Then have this file set:
-       mono-threads-mach, mono-threads-mach-preempt and mono-threads-mach-coop.
-       More files, less ifdef hell.
-       */
-       return FALSE;
-}
-
 void
 mono_threads_init_platform (void)
 {
diff --git a/mono/utils/mono-threads-mach-abort-syscall.c b/mono/utils/mono-threads-mach-abort-syscall.c
new file mode 100644 (file)
index 0000000..58153c4
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * mono-threads-mach-abort-syscall.c: Low-level syscall aborting
+ *
+ * Author:
+ *     Ludovic Henry (ludovic@xamarin.com)
+ *
+ * (C) 2015 Xamarin, Inc
+ */
+
+#include "config.h"
+#include <glib.h>
+
+#if defined (__MACH__)
+#define _DARWIN_C_SOURCE 1
+#endif
+
+#include <mono/utils/mono-threads.h>
+
+#if defined(USE_MACH_SYSCALL_ABORT)
+
+void
+mono_threads_init_abort_syscall (void)
+{
+}
+
+void
+mono_threads_core_abort_syscall (MonoThreadInfo *info)
+{
+       kern_return_t ret;
+
+       ret = thread_suspend (info->native_handle);
+       if (ret != KERN_SUCCESS)
+               return;
+
+       ret = thread_abort_safely (info->native_handle);
+
+       /*
+        * 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);
+
+       g_assert (thread_resume (info->native_handle) == KERN_SUCCESS);
+}
+
+gboolean
+mono_threads_core_needs_abort_syscall (void)
+{
+       return TRUE;
+}
+
+#endif
index fbb78b498fa7d252b59e3b236bfa6772676d9a35..1a0bcd8242179a05d4dbc3e4ee697d56876fcd7b 100644 (file)
@@ -31,37 +31,6 @@ mono_threads_init_platform (void)
        mono_threads_init_dead_letter ();
 }
 
-void
-mono_threads_core_abort_syscall (MonoThreadInfo *info)
-{
-       kern_return_t ret;
-
-       ret = thread_suspend (info->native_handle);
-       if (ret != KERN_SUCCESS)
-               return;
-
-       ret = thread_abort_safely (info->native_handle);
-
-       /*
-        * 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);
-
-       g_assert (thread_resume (info->native_handle) == KERN_SUCCESS);
-}
-
-gboolean
-mono_threads_core_needs_abort_syscall (void)
-{
-       return TRUE;
-}
-
 gboolean
 mono_threads_core_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel)
 {
diff --git a/mono/utils/mono-threads-posix-abort-syscall.c b/mono/utils/mono-threads-posix-abort-syscall.c
new file mode 100644 (file)
index 0000000..4935bd1
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * mono-threads-posix-abort-syscall.c: Low-level syscall aborting
+ *
+ * Author:
+ *     Ludovic Henry (ludovic@xamarin.com)
+ *
+ * (C) 2015 Xamarin, Inc
+ */
+
+#include "config.h"
+#include <glib.h>
+
+#if defined (__MACH__)
+#define _DARWIN_C_SOURCE 1
+#endif
+
+#include "mono-threads.h"
+#include "mono-threads-posix-signals.h"
+
+#if defined(USE_POSIX_SYSCALL_ABORT)
+
+void
+mono_threads_init_abort_syscall (void)
+{
+       mono_threads_posix_init_signals (MONO_THREADS_POSIX_INIT_SIGNALS_ABORT);
+}
+
+void
+mono_threads_core_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_posix_get_abort_signal ()))
+               mono_threads_add_to_pending_operation_set (info);
+}
+
+gboolean
+mono_threads_core_needs_abort_syscall (void)
+{
+       return TRUE;
+}
+
+#endif
diff --git a/mono/utils/mono-threads-posix-signals.c b/mono/utils/mono-threads-posix-signals.c
new file mode 100644 (file)
index 0000000..1dfdd38
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * mono-threads-posix-signals.c: Shared facility for Posix signals support
+ *
+ * Author:
+ *     Ludovic Henry (ludovic@gmail.com)
+ *
+ * (C) 2015 Xamarin, Inc
+ */
+
+#include <config.h>
+#include <glib.h>
+
+#include "mono-threads.h"
+
+#if defined(USE_POSIX_BACKEND) || defined(USE_POSIX_SYSCALL_ABORT)
+
+#include <errno.h>
+#include <signal.h>
+
+#include "mono-semaphore.h"
+#include "mono-threads-posix-signals.h"
+
+#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#define DEFAULT_SUSPEND_SIGNAL SIGXFSZ
+#else
+#define DEFAULT_SUSPEND_SIGNAL SIGPWR
+#endif
+#define DEFAULT_RESTART_SIGNAL SIGXCPU
+
+static int suspend_signal_num;
+static int restart_signal_num;
+static int abort_signal_num;
+
+static sigset_t suspend_signal_mask;
+static sigset_t suspend_ack_signal_mask;
+
+static int
+signal_search_alternative (int min_signal)
+{
+#if !defined (SIGRTMIN)
+       g_error ("signal search only works with RTMIN");
+#else
+       int i;
+       /* we try to avoid SIGRTMIN and any one that might have been set already, see bug #75387 */
+       for (i = MAX (min_signal, SIGRTMIN) + 1; i < SIGRTMAX; ++i) {
+               struct sigaction sinfo;
+               sigaction (i, NULL, &sinfo);
+               if (sinfo.sa_handler == SIG_DFL && (void*)sinfo.sa_sigaction == (void*)SIG_DFL) {
+                       return i;
+               }
+       }
+       g_error ("Could not find an available signal");
+#endif
+}
+
+static void
+signal_add_handler (int signo, gpointer handler, int flags)
+{
+#if !defined(__native_client__)
+       /*FIXME, move the code from mini to utils and do the right thing!*/
+       struct sigaction sa;
+       struct sigaction previous_sa;
+       int ret;
+
+       sa.sa_sigaction = handler;
+       sigfillset (&sa.sa_mask);
+
+       sa.sa_flags = SA_SIGINFO | flags;
+       ret = sigaction (signo, &sa, &previous_sa);
+
+       g_assert (ret != -1);
+#endif
+}
+
+static int
+suspend_signal_get (void)
+{
+#if defined(PLATFORM_ANDROID)
+       return SIGUNUSED;
+#elif !defined (SIGRTMIN)
+#ifdef SIGUSR1
+       return SIGUSR1;
+#else
+       return -1;
+#endif /* SIGUSR1 */
+#else
+       static int suspend_signum = -1;
+       if (suspend_signum == -1)
+               suspend_signum = signal_search_alternative (-1);
+       return suspend_signum;
+#endif /* SIGRTMIN */
+}
+
+static int
+restart_signal_get (void)
+{
+#if defined(PLATFORM_ANDROID)
+       return SIGTTOU;
+#elif !defined (SIGRTMIN)
+#ifdef SIGUSR2
+       return SIGUSR2;
+#else
+       return -1;
+#endif /* SIGUSR1 */
+#else
+       static int resume_signum = -1;
+       if (resume_signum == -1)
+               resume_signum = signal_search_alternative (suspend_signal_get () + 1);
+       return resume_signum;
+#endif /* SIGRTMIN */
+}
+
+
+static int
+abort_signal_get (void)
+{
+#if defined(PLATFORM_ANDROID)
+       return SIGTTIN;
+#elif !defined (SIGRTMIN)
+#ifdef SIGTTIN
+       return SIGTTIN;
+#else
+       return -1;
+#endif /* SIGRTMIN */
+#else
+       static int abort_signum = -1;
+       if (abort_signum == -1)
+               abort_signum = signal_search_alternative (restart_signal_get () + 1);
+       return abort_signum;
+#endif /* SIGRTMIN */
+}
+
+static void
+restart_signal_handler (int _dummy, siginfo_t *_info, void *context)
+{
+#if defined(__native_client__)
+       g_assert_not_reached ();
+#else
+       MonoThreadInfo *info;
+       int old_errno = errno;
+
+       info = mono_thread_info_current ();
+       info->signal = restart_signal_num;
+       errno = old_errno;
+#endif
+}
+
+static void
+suspend_signal_handler (int _dummy, siginfo_t *info, void *context)
+{
+#if defined(__native_client__)
+       g_assert_not_reached ();
+#else
+       int old_errno = errno;
+       int hp_save_index = mono_hazard_pointer_save_for_signal_handler ();
+
+
+       MonoThreadInfo *current = mono_thread_info_current ();
+       gboolean ret;
+
+       THREADS_SUSPEND_DEBUG ("SIGNAL HANDLER FOR %p [%p]\n", current, (void*)current->native_handle);
+       if (current->syscall_break_signal) {
+               current->syscall_break_signal = FALSE;
+               THREADS_SUSPEND_DEBUG ("\tsyscall break for %p\n", current);
+               mono_threads_notify_initiator_of_abort (current);
+               goto done;
+       }
+
+       /* Have we raced with self suspend? */
+       if (!mono_threads_transition_finish_async_suspend (current)) {
+               current->suspend_can_continue = TRUE;
+               THREADS_SUSPEND_DEBUG ("\tlost race with self suspend %p\n", current);
+               goto done;
+       }
+
+       ret = mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (&current->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX], context);
+
+       /* thread_state_init_from_sigctx return FALSE if the current thread is detaching and suspend can't continue. */
+       current->suspend_can_continue = ret;
+
+
+       /*
+       Block the restart signal.
+       We need to block the restart signal while posting to the suspend_ack semaphore or we race to sigsuspend,
+       which might miss the signal and get stuck.
+       */
+       pthread_sigmask (SIG_BLOCK, &suspend_ack_signal_mask, NULL);
+
+       /* We're done suspending */
+       mono_threads_notify_initiator_of_suspend (current);
+
+       /* This thread is doomed, all we can do is give up and let the suspender recover. */
+       if (!ret) {
+               THREADS_SUSPEND_DEBUG ("\tThread is dying, failed to capture state %p\n", current);
+               mono_threads_transition_async_suspend_compensation (current);
+               /* Unblock the restart signal. */
+               pthread_sigmask (SIG_UNBLOCK, &suspend_ack_signal_mask, NULL);
+
+               goto done;
+       }
+
+       do {
+               current->signal = 0;
+               sigsuspend (&suspend_signal_mask);
+       } while (current->signal != restart_signal_num);
+
+       /* Unblock the restart signal. */
+       pthread_sigmask (SIG_UNBLOCK, &suspend_ack_signal_mask, NULL);
+
+       if (current->async_target) {
+#if MONO_ARCH_HAS_MONO_CONTEXT
+               MonoContext tmp = current->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX].ctx;
+               mono_threads_get_runtime_callbacks ()->setup_async_callback (&tmp, current->async_target, current->user_data);
+               current->async_target = current->user_data = NULL;
+               mono_monoctx_to_sigctx (&tmp, context);
+#else
+               g_error ("The new interruption machinery requires a working mono-context");
+#endif
+       }
+
+       /* We're done resuming */
+       mono_threads_notify_initiator_of_resume (current);
+
+done:
+       mono_hazard_pointer_restore_for_signal_handler (hp_save_index);
+       errno = old_errno;
+#endif
+}
+
+static void
+abort_signal_handler (int _dummy, siginfo_t *info, void *context)
+{
+#if defined(__native_client__)
+       g_assert_not_reached ();
+#else
+       suspend_signal_handler (_dummy, info, context);
+#endif
+}
+
+void
+mono_threads_posix_init_signals (MonoThreadPosixInitSignals signals)
+{
+       sigset_t signal_set;
+
+       g_assert ((signals == MONO_THREADS_POSIX_INIT_SIGNALS_SUSPEND_RESTART) ^ (signals == MONO_THREADS_POSIX_INIT_SIGNALS_ABORT));
+
+       sigemptyset (&signal_set);
+
+       switch (signals) {
+       case MONO_THREADS_POSIX_INIT_SIGNALS_SUSPEND_RESTART: {
+               if (mono_thread_info_unified_management_enabled ()) {
+                       suspend_signal_num = DEFAULT_SUSPEND_SIGNAL;
+                       restart_signal_num = DEFAULT_RESTART_SIGNAL;
+               } else {
+                       suspend_signal_num = suspend_signal_get ();
+                       restart_signal_num = restart_signal_get ();
+               }
+
+               sigfillset (&suspend_signal_mask);
+               sigdelset (&suspend_signal_mask, restart_signal_num);
+
+               sigemptyset (&suspend_ack_signal_mask);
+               sigaddset (&suspend_ack_signal_mask, restart_signal_num);
+
+               signal_add_handler (suspend_signal_num, suspend_signal_handler, SA_RESTART);
+               signal_add_handler (restart_signal_num, restart_signal_handler, SA_RESTART);
+
+               sigaddset (&signal_set, suspend_signal_num);
+               sigaddset (&signal_set, restart_signal_num);
+
+               break;
+       }
+       case MONO_THREADS_POSIX_INIT_SIGNALS_ABORT: {
+               abort_signal_num = abort_signal_get ();
+
+               signal_add_handler (abort_signal_num, abort_signal_handler, 0);
+
+               sigaddset (&signal_set, abort_signal_num);
+
+               break;
+       }
+       default: g_assert_not_reached ();
+       }
+
+       /* ensure all the new signals are unblocked */
+       sigprocmask (SIG_UNBLOCK, &signal_set, NULL);
+}
+
+gint
+mono_threads_posix_get_suspend_signal (void)
+{
+       return suspend_signal_num;
+}
+
+gint
+mono_threads_posix_get_restart_signal (void)
+{
+       return restart_signal_num;
+}
+
+gint
+mono_threads_posix_get_abort_signal (void)
+{
+       return abort_signal_num;
+}
+
+#endif /* defined(USE_POSIX_BACKEND) || defined(USE_POSIX_SYSCALL_ABORT) */
diff --git a/mono/utils/mono-threads-posix-signals.h b/mono/utils/mono-threads-posix-signals.h
new file mode 100644 (file)
index 0000000..2bdcf8e
--- /dev/null
@@ -0,0 +1,31 @@
+
+#ifndef __MONO_THREADS_POSIX_SIGNALS_H__
+#define __MONO_THREADS_POSIX_SIGNALS_H__
+
+#include <config.h>
+#include <glib.h>
+
+#include "mono-threads.h"
+
+#if defined(USE_POSIX_BACKEND) || defined(USE_POSIX_SYSCALL_ABORT)
+
+typedef enum {
+       MONO_THREADS_POSIX_INIT_SIGNALS_SUSPEND_RESTART,
+       MONO_THREADS_POSIX_INIT_SIGNALS_ABORT,
+} MonoThreadPosixInitSignals;
+
+void
+mono_threads_posix_init_signals (MonoThreadPosixInitSignals signals);
+
+gint
+mono_threads_posix_get_suspend_signal (void);
+
+gint
+mono_threads_posix_get_restart_signal (void);
+
+gint
+mono_threads_posix_get_abort_signal (void);
+
+#endif /* defined(USE_POSIX_BACKEND) || defined(USE_POSIX_SYSCALL_ABORT) */
+
+#endif /* __MONO_THREADS_POSIX_SIGNALS_H__ */
\ No newline at end of file
index 3e2790024a80fa4ba75f7df33426d51ad7a7f12b..ccbd7606b3d35e1694b0158fe28bb4c454e402c1 100644 (file)
 #define _DARWIN_C_SOURCE 1
 #endif
 
-#include <mono/utils/mono-compiler.h>
-#include <mono/utils/mono-semaphore.h>
 #include <mono/utils/mono-threads.h>
-#include <mono/utils/mono-tls.h>
-#include <mono/utils/mono-mmap.h>
-#include <mono/metadata/threads-types.h>
+#include <mono/utils/mono-threads-posix-signals.h>
 #include <mono/metadata/gc-internal.h>
-#include <limits.h>
 
 #include <errno.h>
 
@@ -34,8 +29,8 @@ extern int tkill (pid_t tid, int signal);
 #endif
 
 #if defined(_POSIX_VERSION) || defined(__native_client__)
+
 #include <sys/resource.h>
-#include <signal.h>
 
 #if defined(__native_client__)
 void nacl_shutdown_gc_thread(void);
@@ -300,272 +295,14 @@ mono_threads_core_set_name (MonoNativeThreadId tid, const char *name)
 #endif
 }
 
+#endif /* defined(_POSIX_VERSION) || defined(__native_client__) */
 
-#if defined (USE_POSIX_BACKEND) && !defined (USE_COOP_GC)
-
-static int suspend_signal_num;
-static int restart_signal_num;
-static int abort_signal_num;
-static sigset_t suspend_signal_mask;
-static sigset_t suspend_ack_signal_mask;
-
-
-#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#define DEFAULT_SUSPEND_SIGNAL SIGXFSZ
-#else
-#define DEFAULT_SUSPEND_SIGNAL SIGPWR
-#endif
-#define DEFAULT_RESTART_SIGNAL SIGXCPU
-
-static int
-mono_thread_search_alt_signal (int min_signal)
-{
-#if !defined (SIGRTMIN)
-       g_error ("signal search only works with RTMIN");
-#else
-       int i;
-       /* we try to avoid SIGRTMIN and any one that might have been set already, see bug #75387 */
-       for (i = MAX (min_signal, SIGRTMIN) + 1; i < SIGRTMAX; ++i) {
-               struct sigaction sinfo;
-               sigaction (i, NULL, &sinfo);
-               if (sinfo.sa_handler == SIG_DFL && (void*)sinfo.sa_sigaction == (void*)SIG_DFL) {
-                       return i;
-               }
-       }
-       g_error ("Could not find an available signal");
-#endif
-}
-
-static int
-mono_thread_get_alt_suspend_signal (void)
-{
-#if defined(PLATFORM_ANDROID)
-       return SIGUNUSED;
-#elif !defined (SIGRTMIN)
-#ifdef SIGUSR1
-       return SIGUSR1;
-#else
-       return -1;
-#endif /* SIGUSR1 */
-#else
-       static int suspend_signum = -1;
-       if (suspend_signum == -1)
-               suspend_signum = mono_thread_search_alt_signal (-1);
-       return suspend_signum;
-#endif /* SIGRTMIN */
-}
-
-static int
-mono_thread_get_alt_resume_signal (void)
-{
-#if defined(PLATFORM_ANDROID)
-       return SIGTTOU;
-#elif !defined (SIGRTMIN)
-#ifdef SIGUSR2
-       return SIGUSR2;
-#else
-       return -1;
-#endif /* SIGUSR1 */
-#else
-       static int resume_signum = -1;
-       if (resume_signum == -1)
-               resume_signum = mono_thread_search_alt_signal (mono_thread_get_alt_suspend_signal () + 1);
-       return resume_signum;
-#endif /* SIGRTMIN */
-}
-
-
-static int
-mono_threads_get_abort_signal (void)
-{
-#if defined(PLATFORM_ANDROID)
-       return SIGTTIN;
-#elif !defined (SIGRTMIN)
-#ifdef SIGTTIN
-       return SIGTTIN;
-#else
-       return -1;
-#endif /* SIGRTMIN */
-#else
-       static int abort_signum = -1;
-       if (abort_signum == -1)
-               abort_signum = mono_thread_search_alt_signal (mono_thread_get_alt_resume_signal () + 1);
-       return abort_signum;
-#endif /* SIGRTMIN */
-}
-
-
-#if !defined(__native_client__)
-static void
-restart_signal_handler (int _dummy, siginfo_t *_info, void *context)
-{
-       MonoThreadInfo *info;
-       int old_errno = errno;
-
-       info = mono_thread_info_current ();
-       info->signal = restart_signal_num;
-       errno = old_errno;
-}
-
-static void
-suspend_signal_handler (int _dummy, siginfo_t *info, void *context)
-{
-       int old_errno = errno;
-       int hp_save_index = mono_hazard_pointer_save_for_signal_handler ();
-
-
-       MonoThreadInfo *current = mono_thread_info_current ();
-       gboolean ret;
-
-       THREADS_SUSPEND_DEBUG ("SIGNAL HANDLER FOR %p [%p]\n", current, (void*)current->native_handle);
-       if (current->syscall_break_signal) {
-               current->syscall_break_signal = FALSE;
-               THREADS_SUSPEND_DEBUG ("\tsyscall break for %p\n", current);
-               mono_threads_notify_initiator_of_abort (current);
-               goto done;
-       }
-
-       /* Have we raced with self suspend? */
-       if (!mono_threads_transition_finish_async_suspend (current)) {
-               current->suspend_can_continue = TRUE;
-               THREADS_SUSPEND_DEBUG ("\tlost race with self suspend %p\n", current);
-               goto done;
-       }
-
-       ret = mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (&current->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX], context);
-
-       /* thread_state_init_from_sigctx return FALSE if the current thread is detaching and suspend can't continue. */
-       current->suspend_can_continue = ret;
-
-
-       /*
-       Block the restart signal.
-       We need to block the restart signal while posting to the suspend_ack semaphore or we race to sigsuspend,
-       which might miss the signal and get stuck.
-       */
-       pthread_sigmask (SIG_BLOCK, &suspend_ack_signal_mask, NULL);
-
-       /* We're done suspending */
-       mono_threads_notify_initiator_of_suspend (current);
-
-       /* This thread is doomed, all we can do is give up and let the suspender recover. */
-       if (!ret) {
-               THREADS_SUSPEND_DEBUG ("\tThread is dying, failed to capture state %p\n", current);
-               mono_threads_transition_async_suspend_compensation (current);
-               /* Unblock the restart signal. */
-               pthread_sigmask (SIG_UNBLOCK, &suspend_ack_signal_mask, NULL);
-
-               goto done;
-       }
-
-       do {
-               current->signal = 0;
-               sigsuspend (&suspend_signal_mask);
-       } while (current->signal != restart_signal_num);
-
-       /* Unblock the restart signal. */
-       pthread_sigmask (SIG_UNBLOCK, &suspend_ack_signal_mask, NULL);
-
-       if (current->async_target) {
-#if MONO_ARCH_HAS_MONO_CONTEXT
-               MonoContext tmp = current->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX].ctx;
-               mono_threads_get_runtime_callbacks ()->setup_async_callback (&tmp, current->async_target, current->user_data);
-               current->async_target = current->user_data = NULL;
-               mono_monoctx_to_sigctx (&tmp, context);
-#else
-               g_error ("The new interruption machinery requires a working mono-context");
-#endif
-       }
-
-       /* We're done resuming */
-       mono_threads_notify_initiator_of_resume (current);
-
-done:
-       mono_hazard_pointer_restore_for_signal_handler (hp_save_index);
-       errno = old_errno;
-}
-
-static void
-abort_signal_handler (int _dummy, siginfo_t *info, void *context)
-{
-       suspend_signal_handler (_dummy, info, context);
-}
-
-#endif
-
-static void
-mono_posix_add_signal_handler (int signo, gpointer handler, int flags)
-{
-#if !defined(__native_client__)
-       /*FIXME, move the code from mini to utils and do the right thing!*/
-       struct sigaction sa;
-       struct sigaction previous_sa;
-       int ret;
-
-       sa.sa_sigaction = handler;
-       sigfillset (&sa.sa_mask);
-
-       sa.sa_flags = SA_SIGINFO | flags;
-       ret = sigaction (signo, &sa, &previous_sa);
-
-       g_assert (ret != -1);
-#endif
-}
-
-void
-mono_threads_init_platform (void)
-{
-       sigset_t signal_set;
-
-       abort_signal_num = mono_threads_get_abort_signal ();
-       if (mono_thread_info_unified_management_enabled ()) {
-               suspend_signal_num = DEFAULT_SUSPEND_SIGNAL;
-               restart_signal_num = DEFAULT_RESTART_SIGNAL;
-       } else {
-               suspend_signal_num = mono_thread_get_alt_suspend_signal ();
-               restart_signal_num = mono_thread_get_alt_resume_signal ();
-       }
-
-       sigfillset (&suspend_signal_mask);
-       sigdelset (&suspend_signal_mask, restart_signal_num);
-
-       sigemptyset (&suspend_ack_signal_mask);
-       sigaddset (&suspend_ack_signal_mask, restart_signal_num);
-
-       mono_posix_add_signal_handler (suspend_signal_num, suspend_signal_handler, SA_RESTART);
-       mono_posix_add_signal_handler (restart_signal_num, restart_signal_handler, SA_RESTART);
-       mono_posix_add_signal_handler (abort_signal_num, abort_signal_handler, 0);
-
-       /* ensure all the new signals are unblocked */
-       sigemptyset (&signal_set);
-       sigaddset (&signal_set, suspend_signal_num);
-       sigaddset (&signal_set, restart_signal_num);
-       sigaddset (&signal_set, abort_signal_num);
-       sigprocmask (SIG_UNBLOCK, &signal_set, NULL);
-}
-
-void
-mono_threads_core_abort_syscall (MonoThreadInfo *info)
-{
-       /*
-       We signal a thread to break it from the urrent syscall.
-       This signal should not be interpreted as a suspend request.
-       */
-       info->syscall_break_signal = TRUE;
-       if (!mono_threads_pthread_kill (info, abort_signal_num))
-               mono_threads_add_to_pending_operation_set (info);
-}
-
-gboolean
-mono_threads_core_needs_abort_syscall (void)
-{
-       return TRUE;
-}
+#if defined(USE_POSIX_BACKEND)
 
 gboolean
 mono_threads_core_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel)
 {
-       int sig = interrupt_kernel ? abort_signal_num :  suspend_signal_num;
+       int sig = interrupt_kernel ? mono_threads_posix_get_abort_signal () :  mono_threads_posix_get_suspend_signal ();
 
        if (!mono_threads_pthread_kill (info, sig)) {
                mono_threads_add_to_pending_operation_set (info);
@@ -590,7 +327,7 @@ gboolean
 mono_threads_core_begin_async_resume (MonoThreadInfo *info)
 {
        mono_threads_add_to_pending_operation_set (info);
-       return mono_threads_pthread_kill (info, restart_signal_num) == 0;
+       return mono_threads_pthread_kill (info, mono_threads_posix_get_restart_signal ()) == 0;
 }
 
 void
@@ -616,6 +353,10 @@ mono_threads_core_end_global_suspend (void)
 {
 }
 
-#endif /*defined (USE_POSIX_BACKEND)*/
+void
+mono_threads_init_platform (void)
+{
+       mono_threads_posix_init_signals (MONO_THREADS_POSIX_INIT_SIGNALS_SUSPEND_RESTART);
+}
 
-#endif
+#endif /* defined(USE_POSIX_BACKEND) */
diff --git a/mono/utils/mono-threads-windows-abort-syscall.c b/mono/utils/mono-threads-windows-abort-syscall.c
new file mode 100644 (file)
index 0000000..13d0b3d
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * mono-threads-windows-abort-syscall.c: Low-level syscall aborting
+ *
+ * Author:
+ *     Ludovic Henry (ludovic@xamarin.com)
+ *
+ * (C) 2015 Xamarin, Inc
+ */
+
+#include "config.h"
+#include <glib.h>
+
+#include <mono/utils/mono-threads.h>
+
+#if defined(USE_WINDOWS_SYSCALL_ABORT)
+
+#include <limits.h>
+
+void
+mono_threads_init_abort_syscall (void)
+{
+}
+
+static void CALLBACK
+abort_apc (ULONG_PTR param)
+{
+}
+
+void
+mono_threads_core_abort_syscall (MonoThreadInfo *info)
+{
+       DWORD id = mono_thread_info_get_tid (info);
+       HANDLE handle;
+
+       handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id);
+       g_assert (handle);
+
+       QueueUserAPC ((PAPCFUNC)abort_apc, handle, (ULONG_PTR)NULL);
+
+       CloseHandle (handle);
+}
+
+gboolean
+mono_threads_core_needs_abort_syscall (void)
+{
+       return TRUE;
+}
+
+#endif
index 9e59810fb2b1925e5ffc407c037fb6ecc505c907..29703b11f6f8a8aaeb7142eda3cdf817ff38a3b8 100644 (file)
@@ -25,26 +25,6 @@ interrupt_apc (ULONG_PTR param)
 {
 }
 
-void
-mono_threads_core_abort_syscall (MonoThreadInfo *info)
-{
-       DWORD id = mono_thread_info_get_tid (info);
-       HANDLE handle;
-
-       handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id);
-       g_assert (handle);
-
-       QueueUserAPC ((PAPCFUNC)interrupt_apc, handle, (ULONG_PTR)NULL);
-
-       CloseHandle (handle);
-}
-
-gboolean
-mono_threads_core_needs_abort_syscall (void)
-{
-       return TRUE;
-}
-
 gboolean
 mono_threads_core_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel)
 {
index c0bfbec293daabd03924a2664d9cda4d5a230024..e2a7239b45db31c253852d41702c9ec7e8ec6a5b 100644 (file)
@@ -589,6 +589,7 @@ mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size)
        mono_lls_init (&thread_list, NULL);
        mono_thread_smr_init ();
        mono_threads_init_platform ();
+       mono_threads_init_abort_syscall ();
 
 #if defined(__MACH__)
        mono_mach_init (thread_info_key);
index 693b2fdd82198819281ee5e676635dde71ed62f0..d153ca83c4e73635aaaea4cf63e2d080d76a0aed 100644 (file)
@@ -145,8 +145,24 @@ and reduce the number of casts drastically.
 #define MONO_THREADS_PLATFORM_REQUIRES_UNIFIED_SUSPEND 0
 #define USE_WINDOWS_BACKEND
 
+#else
+#error "no backend support for current platform"
+#endif /* defined (USE_COOP_GC) */
+
+#if defined (_POSIX_VERSION) || defined (__native_client__)
+#if defined (__MACH__) && !defined (USE_SIGNALS_ON_MACH)
+#define USE_MACH_SYSCALL_ABORT
+#else
+#define USE_POSIX_SYSCALL_ABORT
 #endif
 
+#elif HOST_WIN32
+#define USE_WINDOWS_SYSCALL_ABORT
+
+#else
+#error "no syscall abort support for current platform"
+#endif /* defined (_POSIX_VERSION) || defined (__native_client__) */
+
 enum {
        STATE_STARTING                          = 0x00,
        STATE_RUNNING                           = 0x01,
@@ -200,13 +216,12 @@ typedef struct {
 
        MonoSemType resume_semaphore;
 
-       /* only needed by the posix backend */ 
-#if defined(USE_POSIX_BACKEND)
+       /* only needed by the posix backend */
+#if defined(USE_POSIX_BACKEND) || defined(USE_POSIX_SYSCALL_ABORT)
        MonoSemType finish_resume_semaphore;
        gboolean syscall_break_signal;
        gboolean suspend_can_continue;
        int signal;
-
 #endif
 
        /*In theory, only the posix backend needs this, but having it on mach/win32 simplifies things a lot.*/
@@ -481,6 +496,8 @@ This is called very early in the runtime, it cannot access any runtime facilitie
 */
 void mono_threads_init_platform (void); //ok
 
+void mono_threads_init_abort_syscall (void);
+
 /*
 This begins async suspend. This function must do the following:
 
index 599febb589a161be9f828dfbfb527cce16fae33b..615183c02df569ba3905671b76a289806644ba04 100644 (file)
     <ClCompile Include="..\mono\utils\mono-stdlib.c" />\r
     <ClCompile Include="..\mono\utils\mono-threads-mach.c" />\r
     <ClCompile Include="..\mono\utils\mono-threads-posix.c" />\r
+    <ClCompile Include="..\mono\utils\mono-threads-posix-signals.c" />\r
     <ClCompile Include="..\mono\utils\mono-threads-windows.c" />\r
     <ClCompile Include="..\mono\utils\mono-threads.c" />\r
+    <ClCompile Include="..\mono\utils\mono-threads-posix-abort-syscall.c" />\r
+    <ClCompile Include="..\mono\utils\mono-threads-mach-abort-syscall.c" />\r
+    <ClCompile Include="..\mono\utils\mono-threads-windows-abort-syscall.c" />\r
     <ClCompile Include="..\mono\utils\mono-time.c" />\r
     <ClCompile Include="..\mono\utils\mono-tls.c" />\r
     <ClCompile Include="..\mono\utils\mono-uri.c" />\r
     <ClInclude Include="..\mono\utils\mono-stdlib.h" />\r
     <ClInclude Include="..\mono\utils\mono-string.h" />\r
     <ClInclude Include="..\mono\utils\mono-threads.h" />\r
+    <ClCompile Include="..\mono\utils\mono-threads-posix-signals.h" />\r
     <ClInclude Include="..\mono\utils\mono-time.h" />\r
     <ClInclude Include="..\mono\utils\mono-tls.h" />\r
     <ClInclude Include="..\mono\utils\mono-uri.h" />\r