+
+int
+wake_thread(os_thread_t os_thread)
+{
+#ifdef LISP_FEATURE_WIN32
+# define SIGPIPE 1
+#endif
+#if !defined(LISP_FEATURE_SB_THRUPTION) || defined(LISP_FEATURE_WIN32)
+ return kill_safely(os_thread, SIGPIPE);
+#else
+ return wake_thread_posix(os_thread);
+#endif
+}
+
+/* If the thread id given does not belong to a running thread (it has
+ * exited or never even existed) pthread_kill _may_ fail with ESRCH,
+ * but it is also allowed to just segfault, see
+ * <http://udrepper.livejournal.com/16844.html>.
+ *
+ * Relying on thread ids can easily backfire since ids are recycled
+ * (NPTL recycles them extremely fast) so a signal can be sent to
+ * another process if the one it was sent to exited.
+ *
+ * For these reasons, we must make sure that the thread is still alive
+ * when the pthread_kill is called and return if the thread is
+ * exiting.
+ *
+ * Note (DFL, 2011-06-22): At the time of writing, this function is only
+ * used for INTERRUPT-THREAD, hence the wake_thread special-case for
+ * Windows is OK. */
+int
+kill_safely(os_thread_t os_thread, int signal)
+{
+ FSHOW_SIGNAL((stderr,"/kill_safely: %lu, %d\n", os_thread, signal));
+ {
+#ifdef LISP_FEATURE_SB_THREAD
+ sigset_t oldset;
+ struct thread *thread;
+ /* Frequent special case: resignalling to self. The idea is
+ * that leave_region safepoint will acknowledge the signal, so
+ * there is no need to take locks, roll thread to safepoint
+ * etc. */
+ /* Kludge (on safepoint builds): At the moment, this isn't just
+ * an optimization; rather it masks the fact that
+ * gc_stop_the_world() grabs the all_threads mutex without
+ * releasing it, and since we're not using recursive pthread
+ * mutexes, the pthread_mutex_lock() around the all_threads loop
+ * would go wrong. Why are we running interruptions while
+ * stopping the world though? Test case is (:ASYNC-UNWIND
+ * :SPECIALS), especially with s/10/100/ in both loops. */
+ if (os_thread == pthread_self()) {
+ pthread_kill(os_thread, signal);
+ return 0;
+ }
+
+ /* pthread_kill is not async signal safe and we don't want to be
+ * interrupted while holding the lock. */
+ block_deferrable_signals(0, &oldset);
+ pthread_mutex_lock(&all_threads_lock);
+ for (thread = all_threads; thread; thread = thread->next) {
+ if (thread->os_thread == os_thread) {
+ int status = pthread_kill(os_thread, signal);
+ if (status)
+ lose("kill_safely: pthread_kill failed with %d\n", status);
+ break;
+ }
+ }
+ pthread_mutex_unlock(&all_threads_lock);
+ thread_sigmask(SIG_SETMASK,&oldset,0);
+ if (thread)
+ return 0;
+ else
+ return -1;
+#else
+ int status;
+ if (os_thread != 0)
+ lose("kill_safely: who do you want to kill? %d?\n", os_thread);
+ /* Dubious (as in don't know why it works) workaround for the
+ * signal sometimes not being generated on darwin. */
+#ifdef LISP_FEATURE_DARWIN
+ {
+ sigset_t oldset;
+ sigprocmask(SIG_BLOCK, &deferrable_sigset, &oldset);
+ status = raise(signal);
+ sigprocmask(SIG_SETMASK,&oldset,0);
+ }
+#else
+ status = raise(signal);
+#endif
+ if (status == 0) {
+ return 0;
+ } else {
+ lose("cannot raise signal %d, %d %s\n",
+ signal, status, strerror(errno));
+ }
+#endif
+ }
+}