+gpointer
+mono_threads_core_prepare_interrupt (HANDLE thread_handle)
+{
+ return wapi_prepare_interrupt_thread (thread_handle);
+}
+
+void
+mono_threads_core_finish_interrupt (gpointer wait_handle)
+{
+ wapi_finish_interrupt_thread (wait_handle);
+}
+
+void
+mono_threads_core_self_interrupt (void)
+{
+ wapi_self_interrupt ();
+}
+
+void
+mono_threads_core_clear_interruption (void)
+{
+ wapi_clear_interruption ();
+}
+
+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));
+#ifdef USE_TKILL_ON_ANDROID
+ int result, 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;
+#else
+ return pthread_kill (mono_thread_info_get_tid (info), signum);
+#endif
+}
+
+MonoNativeThreadId
+mono_native_thread_id_get (void)
+{
+ return pthread_self ();
+}
+
+gboolean
+mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2)
+{
+ return pthread_equal (id1, id2);
+}
+
+/*
+ * mono_native_thread_create:
+ *
+ * Low level thread creation function without any GC wrappers.
+ */
+gboolean
+mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg)
+{
+ return pthread_create (tid, NULL, func, arg) == 0;
+}
+
+void
+mono_threads_core_set_name (MonoNativeThreadId tid, const char *name)
+{
+#if defined (HAVE_PTHREAD_SETNAME_NP) && !defined (__MACH__)
+ if (!name) {
+ pthread_setname_np (tid, "");
+ } else {
+ char n [16];
+
+ strncpy (n, name, 16);
+ n [15] = '\0';
+ pthread_setname_np (tid, n);
+ }
+#endif
+}
+
+
+#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 */
+}
+