+static boolean
+maybe_resignal_to_lisp_thread(int signal, os_context_t *context)
+{
+#ifdef LISP_FEATURE_SB_THREAD
+ if (!pthread_getspecific(lisp_thread)) {
+ if (!(sigismember(&deferrable_sigset,signal))) {
+ corruption_warning_and_maybe_lose
+ ("Received signal %d in non-lisp thread %lu, resignalling to a lisp thread.",
+ signal,
+ pthread_self());
+ }
+ {
+ sigset_t sigset;
+ sigemptyset(&sigset);
+ add_handled_signals(&sigset);
+ block_signals(&sigset, 0, 0);
+ block_signals(&sigset, os_context_sigmask_addr(context), 0);
+ kill(getpid(), signal);
+ }
+ return 1;
+ } else
+#endif
+ return 0;
+}
+
+/* These are to be used in signal handlers. Currently all handlers are
+ * called from one of:
+ *
+ * interrupt_handle_now_handler
+ * maybe_now_maybe_later
+ * unblock_me_trampoline
+ * low_level_handle_now_handler
+ * low_level_maybe_now_maybe_later
+ * low_level_unblock_me_trampoline
+ *
+ * This gives us a single point of control (or six) over errno, fp
+ * control word, and fixing up signal context on sparc.
+ *
+ * The SPARC/Linux platform doesn't quite do signals the way we want
+ * them done. The third argument in the handler isn't filled in by the
+ * kernel properly, so we fix it up ourselves in the
+ * arch_os_get_context(..) function. -- CSR, 2002-07-23
+ */
+#define SAVE_ERRNO(signal,context,void_context) \
+ { \
+ int _saved_errno = errno; \
+ RESTORE_FP_CONTROL_WORD(context,void_context); \
+ if (!maybe_resignal_to_lisp_thread(signal, context)) \
+ {
+
+#define RESTORE_ERRNO \
+ } \
+ errno = _saved_errno; \
+ }
+
+static void run_deferred_handler(struct interrupt_data *data,
+ os_context_t *context);
+#ifndef LISP_FEATURE_WIN32
+static void store_signal_data_for_later (struct interrupt_data *data,
+ void *handler, int signal,
+ siginfo_t *info,
+ os_context_t *context);
+\f
+
+/* Generic signal related utilities. */
+
+void
+get_current_sigmask(sigset_t *sigset)
+{
+ /* Get the current sigmask, by blocking the empty set. */
+ thread_sigmask(SIG_BLOCK, 0, sigset);
+}
+
+void
+block_signals(sigset_t *what, sigset_t *where, sigset_t *old)
+{
+ if (where) {
+ int i;
+ if (old)
+ sigcopyset(old, where);
+ for(i = 1; i < NSIG; i++) {
+ if (sigismember(what, i))
+ sigaddset(where, i);
+ }
+ } else {
+ thread_sigmask(SIG_BLOCK, what, old);
+ }
+}
+
+void
+unblock_signals(sigset_t *what, sigset_t *where, sigset_t *old)
+{
+ if (where) {
+ int i;
+ if (old)
+ sigcopyset(old, where);
+ for(i = 1; i < NSIG; i++) {
+ if (sigismember(what, i))
+ sigdelset(where, i);
+ }
+ } else {
+ thread_sigmask(SIG_UNBLOCK, what, old);
+ }
+}