1.0.26.15: interrupt.c refactoring
authorGabor Melis <mega@hotpop.com>
Sun, 22 Mar 2009 21:44:07 +0000 (21:44 +0000)
committerGabor Melis <mega@hotpop.com>
Sun, 22 Mar 2009 21:44:07 +0000 (21:44 +0000)
- check that all or none of the deferrable signals are blocked

- make passing NULL for sigset in the right context mean the current
  sigmask: there is only a single block_signals() function that can
  performs sigset arithmetic or change the current mask.

- print pc and sp on memory faults to ease debugging

19 files changed:
src/code/target-signal.lisp
src/code/target-thread.lisp
src/runtime/alloc.c
src/runtime/backtrace.c
src/runtime/breakpoint.c
src/runtime/cheneygc.c
src/runtime/funcall.c
src/runtime/gc-common.c
src/runtime/interr.c
src/runtime/interrupt.c
src/runtime/interrupt.h
src/runtime/pthread-futex.c
src/runtime/runtime.c
src/runtime/thread.c
src/runtime/x86-64-darwin-os.c
src/runtime/x86-darwin-os.c
tests/threads.impure.lisp
tests/timer.impure.lisp
version.lisp-expr

index 87cf646..b660735 100644 (file)
 ;;; doing things the SBCL way and moving this kind of C-level work
 ;;; down to C wrapper functions.)
 
-(sb!alien:define-alien-routine "unblock_deferrable_signals" sb!alien:void)
-(sb!alien:define-alien-routine "unblock_gc_signals" sb!alien:void)
+(declaim (inline %unblock-deferrable-signals %unblock-gc-signals))
+(sb!alien:define-alien-routine ("unblock_deferrable_signals"
+                                %unblock-deferrable-signals)
+    sb!alien:void
+  (where sb!alien:unsigned-long)
+  (old sb!alien:unsigned-long))
+(sb!alien:define-alien-routine ("unblock_gc_signals" %unblock-gc-signals)
+    sb!alien:void
+  (where sb!alien:unsigned-long)
+  (old sb!alien:unsigned-long))
+
+(defun unblock-deferrable-signals ()
+  (%unblock-deferrable-signals 0 0))
+
+(defun unblock-gc-signals ()
+  (%unblock-gc-signals 0 0))
 
 \f
 ;;;; C routines that actually do all the work of establishing signal handlers
index 2130213..2021cfb 100644 (file)
@@ -120,8 +120,14 @@ in future versions."
   (define-alien-routine ("create_thread" %create-thread)
       unsigned-long (lisp-fun-address unsigned-long))
 
-  (define-alien-routine "block_deferrable_signals"
-      void)
+  (declaim (inline %block-deferrable-signals))
+  (define-alien-routine ("block_deferrable_signals" %block-deferrable-signals)
+      void
+    (where sb!alien:unsigned-long)
+    (old sb!alien:unsigned-long))
+
+  (defun block-deferrable-signals ()
+    (%block-deferrable-signals 0 0))
 
   #!+sb-lutex
   (progn
index 500bfb0..b84df30 100644 (file)
@@ -44,7 +44,7 @@ pa_alloc(int bytes, int page_type_flag)
      * otherwise two threads racing here may deadlock: the other will
      * wait on the GC lock, and the other cannot stop the first
      * one... */
-    check_gc_signals_unblocked_or_lose();
+    check_gc_signals_unblocked_or_lose(0);
 
     /* FIXME: OOAO violation: see arch_pseudo_* */
     set_pseudo_atomic_atomic(th);
@@ -94,7 +94,7 @@ pa_alloc(int bytes, int page_type_flag)
     /* This is not pseudo atomic at all, but is called only from
      * interrupt safe places like interrupt handlers. MG -
      * 2005-08-09 */
-    check_deferrables_blocked_or_lose();
+    check_deferrables_blocked_or_lose(0);
 
     result = dynamic_space_free_pointer;
 
index a36d373..2d7dfca 100644 (file)
@@ -534,7 +534,7 @@ describe_thread_state(void)
     sigset_t mask;
     struct thread *thread = arch_os_get_current_thread();
 #ifndef LISP_FEATURE_WIN32
-    thread_sigmask(SIG_SETMASK, NULL, &mask);
+    get_current_sigmask(&mask);
     printf("Signal mask:\n");
     printf(" SIGALRM = %d\n", sigismember(&mask, SIGALRM));
     printf(" SIGINT = %d\n", sigismember(&mask, SIGINT));
index 5dfa9a4..45639c4 100644 (file)
@@ -130,7 +130,7 @@ void handle_breakpoint(os_context_t *context)
 
     fake_foreign_function_call(context);
 
-    unblock_gc_signals();
+    unblock_gc_signals(0, 0);
     context_sap = alloc_sap(context);
     code = find_code(context);
 
@@ -155,7 +155,7 @@ void *handle_fun_end_breakpoint(os_context_t *context)
 
     fake_foreign_function_call(context);
 
-    unblock_gc_signals();
+    unblock_gc_signals(0, 0);
     context_sap = alloc_sap(context);
     code = find_code(context);
     codeptr = (struct code *)native_pointer(code);
index 78c0ea4..62bd6de 100644 (file)
@@ -132,9 +132,7 @@ collect_garbage(generation_index_t ignore)
 
     /* it's possible that signals are blocked already if this was called
      * from a signal handler (e.g. with the sigsegv gc_trigger stuff) */
-    sigemptyset(&tmp);
-    sigaddset_blockable(&tmp);
-    thread_sigmask(SIG_BLOCK, &tmp, &old);
+    block_blockable_signals(0, &old);
 
     current_static_space_free_pointer =
         (lispobj *) ((unsigned long)
index 186435c..91f5513 100644 (file)
@@ -31,7 +31,7 @@ safe_call_into_lisp(lispobj fun, lispobj *args, int nargs)
      * otherwise two threads racing here may deadlock: the other will
      * wait on the GC lock, and the other cannot stop the first
      * one... */
-    check_gc_signals_unblocked_or_lose();
+    check_gc_signals_unblocked_or_lose(0);
     return call_into_lisp(fun, args, nargs);
 }
 
index 057be12..c358039 100644 (file)
@@ -2433,9 +2433,8 @@ maybe_gc(os_context_t *context)
      * outer context.
      */
 #ifndef LISP_FEATURE_WIN32
-    check_gc_signals_unblocked_in_sigset_or_lose
-        (os_context_sigmask_addr(context));
-    unblock_gc_signals();
+    check_gc_signals_unblocked_or_lose(os_context_sigmask_addr(context));
+    unblock_gc_signals(0, 0);
 #endif
     FSHOW((stderr, "/maybe_gc: calling SUB_GC\n"));
     /* FIXME: Nothing must go wrong during GC else we end up running
@@ -2456,9 +2455,9 @@ maybe_gc(os_context_t *context)
          (SymbolValue(ALLOW_WITH_INTERRUPTS,thread) != NIL))) {
 #ifndef LISP_FEATURE_WIN32
         sigset_t *context_sigmask = os_context_sigmask_addr(context);
-        if (!deferrables_blocked_in_sigset_p(context_sigmask)) {
+        if (!deferrables_blocked_p(context_sigmask)) {
             thread_sigmask(SIG_SETMASK, context_sigmask, 0);
-            check_gc_signals_unblocked_or_lose();
+            check_gc_signals_unblocked_or_lose(0);
 #endif
             FSHOW((stderr, "/maybe_gc: calling POST_GC\n"));
             funcall0(StaticSymbolFunction(POST_GC));
index f7da2d3..3b0a882 100644 (file)
@@ -79,7 +79,7 @@ lose(char *fmt, ...)
     va_list ap;
     /* Block signals to prevent other threads, timers and such from
      * interfering. If only all threads could be stopped somehow. */
-    block_blockable_signals();
+    block_blockable_signals(0, 0);
     fprintf(stderr, "fatal error encountered");
     va_start(ap, fmt);
     print_message(fmt, ap);
@@ -97,7 +97,7 @@ corruption_warning_and_maybe_lose(char *fmt, ...)
     va_list ap;
 #ifndef LISP_FEATURE_WIN32
     sigset_t oldset;
-    thread_sigmask(SIG_BLOCK, &blockable_sigset, &oldset);
+    block_blockable_signals(0, &oldset);
 #endif
     fprintf(stderr, "CORRUPTION WARNING");
     va_start(ap, fmt);
index 305f75f..8c87054 100644 (file)
@@ -116,15 +116,95 @@ static void store_signal_data_for_later (struct interrupt_data *data,
                                          void *handler, int signal,
                                          siginfo_t *info,
                                          os_context_t *context);
+\f
 
-static void
-fill_current_sigmask(sigset_t *sigset)
+/* Generic signal related utilities. */
+
+void
+get_current_sigmask(sigset_t *sigset)
 {
     /* Get the current sigmask, by blocking the empty set. */
-    sigset_t empty;
-    sigemptyset(&empty);
-    thread_sigmask(SIG_BLOCK, &empty, sigset);
+    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);
+    }
+}
+
+static void
+print_sigset(sigset_t *sigset)
+{
+  int i;
+  for(i = 1; i < NSIG; i++) {
+    if (sigismember(sigset, i))
+      fprintf(stderr, "Signal %d masked\n", i);
+  }
+}
+
+/* Return 1 is all signals is sigset2 are masked in sigset, return 0
+ * if all re unmasked else die. Passing NULL for sigset is a shorthand
+ * for the current sigmask. */
+boolean
+all_signals_blocked_p(sigset_t *sigset, sigset_t *sigset2,
+                                const char *name)
+{
+#if !defined(LISP_FEATURE_WIN32)
+    int i;
+    boolean has_blocked = 0, has_unblocked = 0;
+    sigset_t current;
+    if (sigset == 0) {
+        get_current_sigmask(&current);
+        sigset = &current;
+    }
+    for(i = 1; i < NSIG; i++) {
+        if (sigismember(sigset2, i)) {
+            if (sigismember(sigset, i))
+                has_blocked = 1;
+            else
+                has_unblocked = 1;
+        }
+    }
+    if (has_blocked && has_unblocked) {
+        print_sigset(sigset);
+        lose("some %s signals blocked, some unblocked\n", name);
+    }
+    if (has_blocked)
+        return 1;
+    else
+        return 0;
+#endif
 }
+\f
+
+/* Deferrables, blockables, gc signals. */
 
 void
 sigaddset_deferrable(sigset_t *s)
@@ -149,27 +229,6 @@ sigaddset_deferrable(sigset_t *s)
 }
 
 void
-sigdelset_deferrable(sigset_t *s)
-{
-    sigdelset(s, SIGHUP);
-    sigdelset(s, SIGINT);
-    sigdelset(s, SIGQUIT);
-    sigdelset(s, SIGPIPE);
-    sigdelset(s, SIGALRM);
-    sigdelset(s, SIGURG);
-    sigdelset(s, SIGTSTP);
-    sigdelset(s, SIGCHLD);
-    sigdelset(s, SIGIO);
-#ifndef LISP_FEATURE_HPUX
-    sigdelset(s, SIGXCPU);
-    sigdelset(s, SIGXFSZ);
-#endif
-    sigdelset(s, SIGVTALRM);
-    sigdelset(s, SIGPROF);
-    sigdelset(s, SIGWINCH);
-}
-
-void
 sigaddset_blockable(sigset_t *sigset)
 {
     sigaddset_deferrable(sigset);
@@ -184,113 +243,155 @@ sigaddset_gc(sigset_t *sigset)
 #endif
 }
 
-void
-sigdelset_gc(sigset_t *sigset)
-{
-#ifdef LISP_FEATURE_SB_THREAD
-    sigdelset(sigset,SIG_STOP_FOR_GC);
-#endif
-}
-
 /* initialized in interrupt_init */
 sigset_t deferrable_sigset;
 sigset_t blockable_sigset;
 sigset_t gc_sigset;
+
 #endif
 
 boolean
-deferrables_blocked_in_sigset_p(sigset_t *sigset)
+deferrables_blocked_p(sigset_t *sigset)
+{
+    return all_signals_blocked_p(sigset, &deferrable_sigset, "deferrable");
+}
+
+void
+check_deferrables_unblocked_or_lose(sigset_t *sigset)
 {
 #if !defined(LISP_FEATURE_WIN32)
-    int i;
-    for(i = 1; i < NSIG; i++) {
-        if (sigismember(&deferrable_sigset, i) && sigismember(sigset, i))
-            return 1;
-    }
+    if (deferrables_blocked_p(sigset))
+        lose("deferrables blocked\n");
 #endif
-    return 0;
 }
 
 void
-check_deferrables_unblocked_in_sigset_or_lose(sigset_t *sigset)
+check_deferrables_blocked_or_lose(sigset_t *sigset)
 {
 #if !defined(LISP_FEATURE_WIN32)
-    int i;
-    for(i = 1; i < NSIG; i++) {
-        if (sigismember(&deferrable_sigset, i) && sigismember(sigset, i))
-            lose("deferrable signal %d blocked\n",i);
-    }
+    if (!deferrables_blocked_p(sigset))
+        lose("deferrables unblocked\n");
 #endif
 }
 
+boolean
+blockables_blocked_p(sigset_t *sigset)
+{
+    return all_signals_blocked_p(sigset, &blockable_sigset, "blockable");
+}
+
 void
-check_deferrables_blocked_in_sigset_or_lose(sigset_t *sigset)
+check_blockables_unblocked_or_lose(sigset_t *sigset)
 {
 #if !defined(LISP_FEATURE_WIN32)
-    int i;
-    for(i = 1; i < NSIG; i++) {
-        if (sigismember(&deferrable_sigset, i) && !sigismember(sigset, i))
-            lose("deferrable signal %d not blocked\n",i);
-    }
+    if (blockables_blocked_p(sigset))
+        lose("blockables blocked\n");
 #endif
 }
 
 void
-check_deferrables_unblocked_or_lose(void)
+check_blockables_blocked_or_lose(sigset_t *sigset)
 {
 #if !defined(LISP_FEATURE_WIN32)
-    sigset_t current;
-    fill_current_sigmask(&current);
-    check_deferrables_unblocked_in_sigset_or_lose(&current);
+    if (!blockables_blocked_p(sigset))
+        lose("blockables unblocked\n");
 #endif
 }
 
+boolean
+gc_signals_blocked_p(sigset_t *sigset)
+{
+    return all_signals_blocked_p(sigset, &gc_sigset, "gc");
+}
+
 void
-check_deferrables_blocked_or_lose(void)
+check_gc_signals_unblocked_or_lose(sigset_t *sigset)
 {
 #if !defined(LISP_FEATURE_WIN32)
-    sigset_t current;
-    fill_current_sigmask(&current);
-    check_deferrables_blocked_in_sigset_or_lose(&current);
+    if (gc_signals_blocked_p(sigset))
+        lose("gc signals blocked\n");
 #endif
 }
 
 void
-check_blockables_blocked_or_lose(void)
+check_gc_signals_blocked_or_lose(sigset_t *sigset)
 {
 #if !defined(LISP_FEATURE_WIN32)
-    sigset_t current;
-    int i;
-    fill_current_sigmask(&current);
-    for(i = 1; i < NSIG; i++) {
-        if (sigismember(&blockable_sigset, i) && !sigismember(&current, i))
-            lose("blockable signal %d not blocked\n",i);
-    }
+    if (!gc_signals_blocked_p(sigset))
+        lose("gc signals unblocked\n");
 #endif
 }
 
 void
-check_gc_signals_unblocked_in_sigset_or_lose(sigset_t *sigset)
+block_deferrable_signals(sigset_t *where, sigset_t *old)
 {
-#if !defined(LISP_FEATURE_WIN32)
-    int i;
-    for(i = 1; i < NSIG; i++) {
-        if (sigismember(&gc_sigset, i) && sigismember(sigset, i))
-            lose("gc signal %d blocked\n",i);
-    }
+#ifndef LISP_FEATURE_WIN32
+    block_signals(&deferrable_sigset, where, old);
 #endif
 }
 
 void
-check_gc_signals_unblocked_or_lose(void)
+block_blockable_signals(sigset_t *where, sigset_t *old)
 {
-#if !defined(LISP_FEATURE_WIN32)
-    sigset_t current;
-    fill_current_sigmask(&current);
-    check_gc_signals_unblocked_in_sigset_or_lose(&current);
+#ifndef LISP_FEATURE_WIN32
+    block_signals(&blockable_sigset, where, old);
 #endif
 }
 
+void
+block_gc_signals(sigset_t *where, sigset_t *old)
+{
+#ifndef LISP_FEATURE_WIN32
+    block_signals(&gc_sigset, where, old);
+#endif
+}
+
+void
+unblock_deferrable_signals(sigset_t *where, sigset_t *old)
+{
+#ifndef LISP_FEATURE_WIN32
+    if (interrupt_handler_pending_p())
+        lose("unblock_deferrable_signals: losing proposition\n");
+    check_gc_signals_unblocked_or_lose(where);
+    unblock_signals(&deferrable_sigset, where, old);
+#endif
+}
+
+void
+unblock_blockable_signals(sigset_t *where, sigset_t *old)
+{
+#ifndef LISP_FEATURE_WIN32
+    unblock_signals(&blockable_sigset, where, old);
+#endif
+}
+
+void
+unblock_gc_signals(sigset_t *where, sigset_t *old)
+{
+#ifndef LISP_FEATURE_WIN32
+    unblock_signals(&gc_sigset, where, old);
+#endif
+}
+
+void
+unblock_signals_in_context_and_maybe_warn(os_context_t *context)
+{
+#ifndef LISP_FEATURE_WIN32
+    sigset_t *sigset = os_context_sigmask_addr(context);
+    if (all_signals_blocked_p(sigset, &gc_sigset, "gc")) {
+        corruption_warning_and_maybe_lose(
+"Enabling blocked gc signals to allow returning to Lisp without risking\n\
+gc deadlocks. Since GC signals are only blocked in signal handlers when \n\
+they are not safe to interrupt at all, this is a pretty severe occurrence.\n");
+        unblock_gc_signals(sigset, 0);
+    }
+    if (!interrupt_handler_pending_p()) {
+        unblock_deferrable_signals(sigset, 0);
+    }
+#endif
+}
+\f
+
 inline static void
 check_interrupts_enabled_or_lose(os_context_t *context)
 {
@@ -315,7 +416,7 @@ maybe_save_gc_mask_and_block_deferrables(sigset_t *sigset)
     sigset_t oldset;
     /* Obviously, this function is called when signals may not be
      * blocked. Let's make sure we are not interrupted. */
-    thread_sigmask(SIG_BLOCK, &blockable_sigset, &oldset);
+    block_blockable_signals(0, &oldset);
 #ifndef LISP_FEATURE_SB_THREAD
     /* With threads a SIG_STOP_FOR_GC and a normal GC may also want to
      * block. */
@@ -337,7 +438,7 @@ maybe_save_gc_mask_and_block_deferrables(sigset_t *sigset)
              * unblock gc signals. In the end, this is equivalent to
              * blocking the deferrables. */
             sigcopyset(&data->pending_mask, &oldset);
-            unblock_gc_signals();
+            thread_sigmask(SIG_UNBLOCK, &gc_sigset, 0);
             return;
         }
     }
@@ -405,15 +506,15 @@ check_interrupt_context_or_lose(os_context_t *context)
     if ((data->gc_blocked_deferrables) && interrupt_pending)
         lose("gc_blocked_deferrables and interrupt pending\n.");
     if (data->gc_blocked_deferrables)
-        check_deferrables_blocked_in_sigset_or_lose(sigset);
+        check_deferrables_blocked_or_lose(sigset);
     if (interrupt_pending || interrupt_deferred_p ||
         data->gc_blocked_deferrables)
-        check_deferrables_blocked_in_sigset_or_lose(sigset);
+        check_deferrables_blocked_or_lose(sigset);
     else {
-        check_deferrables_unblocked_in_sigset_or_lose(sigset);
+        check_deferrables_unblocked_or_lose(sigset);
         /* If deferrables are unblocked then we are open to signals
          * that run lisp code. */
-        check_gc_signals_unblocked_in_sigset_or_lose(sigset);
+        check_gc_signals_unblocked_or_lose(sigset);
     }
 #endif
 }
@@ -431,76 +532,6 @@ void (*interrupt_low_level_handlers[NSIG]) (int, siginfo_t*, os_context_t*);
 #endif
 union interrupt_handler interrupt_handlers[NSIG];
 
-void
-block_blockable_signals(void)
-{
-#ifndef LISP_FEATURE_WIN32
-    thread_sigmask(SIG_BLOCK, &blockable_sigset, 0);
-#endif
-}
-
-void
-block_deferrable_signals(void)
-{
-#ifndef LISP_FEATURE_WIN32
-    thread_sigmask(SIG_BLOCK, &deferrable_sigset, 0);
-#endif
-}
-
-void
-unblock_deferrable_signals_in_sigset(sigset_t *sigset)
-{
-#ifndef LISP_FEATURE_WIN32
-    if (interrupt_handler_pending_p())
-        lose("unblock_deferrable_signals_in_sigset: losing proposition\n");
-    check_gc_signals_unblocked_in_sigset_or_lose(sigset);
-    sigdelset_deferrable(sigset);
-#endif
-}
-
-void
-unblock_deferrable_signals(void)
-{
-#ifndef LISP_FEATURE_WIN32
-    if (interrupt_handler_pending_p())
-        lose("unblock_deferrable_signals: losing proposition\n");
-    check_gc_signals_unblocked_or_lose();
-    thread_sigmask(SIG_UNBLOCK, &deferrable_sigset, 0);
-#endif
-}
-
-void
-unblock_gc_signals(void)
-{
-#if defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_WIN32)
-    thread_sigmask(SIG_UNBLOCK,&gc_sigset,0);
-#endif
-}
-
-void
-unblock_signals_in_context_and_maybe_warn(os_context_t *context)
-{
-#ifndef LISP_FEATURE_WIN32
-    int i, oops=0;
-    sigset_t *sigset=os_context_sigmask_addr(context);
-    for(i = 1; i < NSIG; i++) {
-        if (sigismember(&gc_sigset, i) && sigismember(sigset, i)) {
-            if (!oops) {
-                fprintf(stderr,
-"Enabling blocked gc signals to allow returning to Lisp without risking\n\
-gc deadlocks. Since GC signals are only blocked in signal handlers when \n\
-they are not safe to interrupt at all, this is a pretty severe occurrence.\n");
-            }
-            oops=1;
-        }
-    }
-    sigdelset_gc(sigset);
-    if (!interrupt_handler_pending_p()) {
-        unblock_deferrable_signals_in_sigset(sigset);
-    }
-#endif
-}
-
 \f
 /*
  * utility routines used by various signal handlers
@@ -568,7 +599,7 @@ fake_foreign_function_call(os_context_t *context)
     struct thread *thread=arch_os_get_current_thread();
 
     /* context_index incrementing must not be interrupted */
-    check_blockables_blocked_or_lose();
+    check_blockables_blocked_or_lose(0);
 
     /* Get current Lisp state from context. */
 #ifdef reg_ALLOC
@@ -624,7 +655,7 @@ undo_fake_foreign_function_call(os_context_t *context)
 {
     struct thread *thread=arch_os_get_current_thread();
     /* Block all blockable signals. */
-    block_blockable_signals();
+    block_blockable_signals(0, 0);
 
 #ifdef FOREIGN_FUNCTION_CALL_FLAG
     foreign_function_call_active = 0;
@@ -665,7 +696,7 @@ interrupt_internal_error(os_context_t *context, boolean continuable)
 
     /* Allocate the SAP object while the interrupts are still
      * disabled. */
-    unblock_gc_signals();
+    unblock_gc_signals(0, 0);
     context_sap = alloc_sap(context);
 
 #ifndef LISP_FEATURE_WIN32
@@ -730,7 +761,7 @@ interrupt_handle_pending(os_context_t *context)
 
     FSHOW_SIGNAL((stderr, "/entering interrupt_handle_pending\n"));
 
-    check_blockables_blocked_or_lose();
+    check_blockables_blocked_or_lose(0);
 
     /* If GC/SIG_STOP_FOR_GC struck during PA and there was no pending
      * handler, then the pending mask was saved and
@@ -810,7 +841,7 @@ interrupt_handle_pending(os_context_t *context)
             lose("Trapping to run pending handler while GC in progress.");
         }
 
-        check_blockables_blocked_or_lose();
+        check_blockables_blocked_or_lose(0);
 
         /* No GC shall be lost. If SUB_GC triggers another GC then
          * that should be handled on the spot. */
@@ -861,7 +892,7 @@ interrupt_handle_now(int signal, siginfo_t *info, os_context_t *context)
 #endif
     union interrupt_handler handler;
 
-    check_blockables_blocked_or_lose();
+    check_blockables_blocked_or_lose(0);
 
 #ifndef LISP_FEATURE_WIN32
     if (sigismember(&deferrable_sigset,signal))
@@ -912,7 +943,7 @@ interrupt_handle_now(int signal, siginfo_t *info, os_context_t *context)
         lispobj info_sap, context_sap;
         /* Leave deferrable signals blocked, the handler itself will
          * allow signals again when it sees fit. */
-        unblock_gc_signals();
+        unblock_gc_signals(0, 0);
         context_sap = alloc_sap(context);
         info_sap = alloc_sap(info);
 
@@ -973,7 +1004,7 @@ maybe_defer_handler(void *handler, struct interrupt_data *data,
 {
     struct thread *thread=arch_os_get_current_thread();
 
-    check_blockables_blocked_or_lose();
+    check_blockables_blocked_or_lose(0);
 
     if (SymbolValue(INTERRUPT_PENDING,thread) != NIL)
         lose("interrupt already pending\n");
@@ -1066,7 +1097,7 @@ low_level_interrupt_handle_now(int signal, siginfo_t *info,
                                os_context_t *context)
 {
     /* No FP control fixage needed, caller has done that. */
-    check_blockables_blocked_or_lose();
+    check_blockables_blocked_or_lose(0);
     check_interrupts_enabled_or_lose(context);
     (*interrupt_low_level_handlers[signal])(signal, info, context);
     /* No Darwin context fixage needed, caller does that. */
@@ -1093,7 +1124,6 @@ void
 sig_stop_for_gc_handler(int signal, siginfo_t *info, os_context_t *context)
 {
     struct thread *thread=arch_os_get_current_thread();
-    sigset_t ss;
 
     /* Test for GC_INHIBIT _first_, else we'd trap on every single
      * pseudo atomic until gc is finally allowed. */
@@ -1117,10 +1147,6 @@ sig_stop_for_gc_handler(int signal, siginfo_t *info, os_context_t *context)
     /* need the context stored so it can have registers scavenged */
     fake_foreign_function_call(context);
 
-    /* Block everything. */
-    sigfillset(&ss);
-    thread_sigmask(SIG_BLOCK,&ss,0);
-
     /* Not pending anymore. */
     SetSymbolValue(GC_PENDING,NIL,thread);
     SetSymbolValue(STOP_FOR_GC_PENDING,NIL,thread);
@@ -1178,7 +1204,7 @@ void
 arrange_return_to_lisp_function(os_context_t *context, lispobj function)
 {
 #ifndef LISP_FEATURE_WIN32
-    check_gc_signals_unblocked_in_sigset_or_lose
+    check_gc_signals_unblocked_or_lose
         (os_context_sigmask_addr(context));
 #endif
 #if !(defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64))
@@ -1482,10 +1508,9 @@ static volatile int sigaction_nodefer_works = -1;
 static void
 sigaction_nodefer_test_handler(int signal, siginfo_t *info, void *void_context)
 {
-    sigset_t empty, current;
+    sigset_t current;
     int i;
-    sigemptyset(&empty);
-    thread_sigmask(SIG_BLOCK, &empty, &current);
+    get_current_sigmask(&current);
     /* There should be exactly two blocked signals: the two we added
      * to sa_mask when setting up the handler.  NetBSD doesn't block
      * the signal we're handling when SA_NODEFER is set; Linux before
@@ -1600,12 +1625,12 @@ install_handler(int signal, void handler(int, siginfo_t*, os_context_t*))
 {
 #ifndef LISP_FEATURE_WIN32
     struct sigaction sa;
-    sigset_t old, new;
+    sigset_t old;
     union interrupt_handler oldhandler;
 
     FSHOW((stderr, "/entering POSIX install_handler(%d, ..)\n", signal));
 
-    thread_sigmask(SIG_BLOCK, &blockable_sigset, &old);
+    block_blockable_signals(0, &old);
 
     FSHOW((stderr, "/interrupt_low_level_handlers[signal]=%x\n",
            (unsigned int)interrupt_low_level_handlers[signal]));
@@ -1696,7 +1721,15 @@ lisp_memory_fault_error(os_context_t *context, os_vm_address_t addr)
     */
     current_memory_fault_address = addr;
     /* To allow debugging memory faults in signal handlers and such. */
-    corruption_warning_and_maybe_lose("Memory fault at %x", addr);
+    corruption_warning_and_maybe_lose("Memory fault at %x (pc=%p, sp=%p)",
+                                      addr,
+                                      *os_context_pc_addr(context),
+#ifdef ARCH_HAS_STACK_POINTER
+                                      *os_context_sp_addr(context)
+#else
+                                      0
+#endif
+                                      );
     unblock_signals_in_context_and_maybe_warn(context);
 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
     arrange_return_to_lisp_function(context,
@@ -1712,7 +1745,7 @@ unhandled_trap_error(os_context_t *context)
 {
     lispobj context_sap;
     fake_foreign_function_call(context);
-    unblock_gc_signals();
+    unblock_gc_signals(0, 0);
     context_sap = alloc_sap(context);
 #ifndef LISP_FEATURE_WIN32
     thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
index 1d9f64f..4f2b097 100644 (file)
 /* FIXME: do not rely on NSIG being a multiple of 8 */
 #define REAL_SIGSET_SIZE_BYTES ((NSIG/8))
 
+static inline void
+sigcopyset(sigset_t *new, sigset_t *old)
+{
+    memcpy(new, old, REAL_SIGSET_SIZE_BYTES);
+}
+
+extern void get_current_sigmask(sigset_t *sigset);
+
 /* Set all deferrable signals into *s. */
 extern void sigaddset_deferrable(sigset_t *s);
 /* Set all blockable signals into *s. */
@@ -37,25 +45,27 @@ extern sigset_t deferrable_sigset;
 extern sigset_t blockable_sigset;
 extern sigset_t gc_sigset;
 
-extern void block_deferrable_signals(void);
-extern void block_blockable_signals(void);
-extern void unblock_deferrable_signals(void);
-extern void unblock_gc_signals(void);
-extern void unblock_signals_in_context_and_maybe_warn(os_context_t *context);
+extern boolean deferrables_blocked_p(sigset_t *sigset);
+extern boolean blockables_blocked_p(sigset_t *sigset);
+extern boolean gc_signals_blocked_p(sigset_t *sigset);
 
-extern boolean deferrables_blocked_in_sigset_p(sigset_t *sigset);
-extern void check_deferrables_blocked_or_lose(void);
-extern void check_blockables_blocked_or_lose(void);
-extern void check_gc_signals_unblocked_or_lose(void);
-extern void check_gc_signals_unblocked_in_sigset_or_lose(sigset_t *sigset);
+extern void check_deferrables_blocked_or_lose(sigset_t *sigset);
+extern void check_blockables_blocked_or_lose(sigset_t *sigset);
+extern void check_gc_signals_blocked_or_lose(sigset_t *sigset);
 
-extern void maybe_save_gc_mask_and_block_deferrables(sigset_t *sigset);
+extern void check_deferrables_unblocked_or_lose(sigset_t *sigset);
+extern void check_blockables_unblocked_or_lose(sigset_t *sigset);
+extern void check_gc_signals_unblocked_or_lose(sigset_t *sigset);
 
-static inline void
-sigcopyset(sigset_t *new, sigset_t *old)
-{
-    memcpy(new, old, REAL_SIGSET_SIZE_BYTES);
-}
+extern void block_deferrable_signals(sigset_t *where, sigset_t *old);
+extern void block_blockable_signals(sigset_t *where, sigset_t *old);
+extern void block_gc_signals(sigset_t *where, sigset_t *old);
+
+extern void unblock_deferrable_signals(sigset_t *where, sigset_t *old);
+extern void unblock_blockable_signals(sigset_t *where, sigset_t *old);
+extern void unblock_gc_signals(sigset_t *where, sigset_t *old);
+
+extern void maybe_save_gc_mask_and_block_deferrables(sigset_t *sigset);
 
 /* maximum signal nesting depth
  *
index a08eb80..cddcda9 100644 (file)
@@ -227,12 +227,9 @@ futex_wait(int *lock_word, int oldval, long sec, unsigned long usec)
 {
     int ret, result;
     struct futex *futex;
-    sigset_t oldset, newset;
+    sigset_t oldset;
     struct timeval tv, *timeout;
 
-    sigemptyset(&newset);
-    sigaddset_deferrable(&newset);
-
 again:
     if (sec < 0)
         timeout = NULL;
@@ -245,7 +242,7 @@ again:
         timeout = &tv;
     }
 
-    pthread_sigmask(SIG_BLOCK, &newset, &oldset);
+    block_deferrable_signals(0, &oldset);
 
     futex = futex_get(lock_word);
 
@@ -311,12 +308,9 @@ futex_wake(int *lock_word, int n)
 {
     int ret;
     struct futex *futex;
-    sigset_t newset, oldset;
-
-    sigemptyset(&newset);
-    sigaddset_deferrable(&newset);
+    sigset_t oldset;
 
-    pthread_sigmask(SIG_BLOCK, &newset, &oldset);
+    block_deferrable_signals(0, &oldset);
 
     futex = futex_get(lock_word);
 
index 03b519f..45f7eec 100644 (file)
@@ -235,7 +235,7 @@ main(int argc, char *argv[], char *envp[])
     const char *sbcl_home = getenv("SBCL_HOME");
 
     interrupt_init();
-    block_blockable_signals();
+    block_blockable_signals(0, 0);
 
     setlocale(LC_ALL, "");
 
index 1da1108..84fb947 100644 (file)
@@ -258,8 +258,8 @@ new_thread_trampoline(struct thread *th)
     int result, lock_ret;
 
     FSHOW((stderr,"/creating thread %lu\n", thread_self()));
-    check_deferrables_blocked_or_lose();
-    check_gc_signals_unblocked_or_lose();
+    check_deferrables_blocked_or_lose(0);
+    check_gc_signals_unblocked_or_lose(0);
     function = th->no_tls_value_marker;
     th->no_tls_value_marker = NO_TLS_VALUE_MARKER_WIDETAG;
     if(arch_os_thread_init(th)==0) {
@@ -284,7 +284,7 @@ new_thread_trampoline(struct thread *th)
     result = funcall0(function);
 
     /* Block GC */
-    block_blockable_signals();
+    block_blockable_signals(0, 0);
     set_thread_state(th, STATE_DEAD);
 
     /* SIG_STOP_FOR_GC is blocked and GC might be waiting for this
@@ -514,7 +514,7 @@ boolean create_os_thread(struct thread *th,os_thread_t *kid_tid)
     /* Blocking deferrable signals is enough, no need to block
      * SIG_STOP_FOR_GC because the child process is not linked onto
      * all_threads until it's ready. */
-    thread_sigmask(SIG_BLOCK, &deferrable_sigset, &oldset);
+    block_deferrable_signals(0, &oldset);
 
 #ifdef LOCK_CREATE_THREAD
     retcode = pthread_mutex_lock(&create_thread_lock);
@@ -701,7 +701,7 @@ kill_safely(os_thread_t os_thread, int signal)
         struct thread *thread;
         /* pthread_kill is not async signal safe and we don't want to be
          * interrupted while holding the lock. */
-        thread_sigmask(SIG_BLOCK, &deferrable_sigset, &oldset);
+        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) {
index 046a125..bc42425 100644 (file)
@@ -233,7 +233,7 @@ void signal_emulation_wrapper(x86_thread_state64_t *thread_state,
 
     build_fake_signal_context(context, thread_state, float_state);
 
-    block_blockable_signals();
+    block_blockable_signals(0, 0);
 
     handler(signal, siginfo, context);
 
index c657565..25f13b1 100644 (file)
@@ -270,7 +270,7 @@ void signal_emulation_wrapper(x86_thread_state32_t *thread_state,
 
     build_fake_signal_context(context, thread_state, float_state);
 
-    block_blockable_signals();
+    block_blockable_signals(0, 0);
 
     handler(signal, siginfo, context);
 
index 9db5021..aeb807e 100644 (file)
     mutex))
 
 (sb-alien:define-alien-routine "check_deferrables_blocked_or_lose"
-    void)
+    void
+  (where sb-alien:unsigned-long))
 (sb-alien:define-alien-routine "check_deferrables_unblocked_or_lose"
-    void)
+    void
+  (where sb-alien:unsigned-long))
 
 (with-test (:name (:interrupt-thread :deferrables-blocked))
   (sb-thread:interrupt-thread sb-thread:*current-thread*
                               (lambda ()
-                                (check-deferrables-blocked-or-lose))))
+                                (check-deferrables-blocked-or-lose 0))))
 
 (with-test (:name (:interrupt-thread :deferrables-unblocked))
   (sb-thread:interrupt-thread sb-thread:*current-thread*
                               (lambda ()
                                 (with-interrupts
-                                  (check-deferrables-unblocked-or-lose)))))
+                                  (check-deferrables-unblocked-or-lose 0)))))
 
 (with-test (:name (:interrupt-thread :nlx))
   (catch 'xxx
     (sb-thread:interrupt-thread sb-thread:*current-thread*
                                 (lambda ()
-                                  (check-deferrables-blocked-or-lose)
+                                  (check-deferrables-blocked-or-lose 0)
                                   (throw 'xxx nil))))
-  (check-deferrables-unblocked-or-lose))
+  (check-deferrables-unblocked-or-lose 0))
 
 #-sb-thread (sb-ext:quit :unix-status 104)
 
@@ -75,9 +77,9 @@
     (sb-thread::get-spinlock spinlock)
     (sb-thread:interrupt-thread thread
                                 (lambda ()
-                                  (check-deferrables-blocked-or-lose)
+                                  (check-deferrables-blocked-or-lose 0)
                                   (sb-thread::get-spinlock spinlock)
-                                  (check-deferrables-unblocked-or-lose)
+                                  (check-deferrables-unblocked-or-lose 0)
                                   (sb-ext:quit)))
     (sleep 1)
     (sb-thread::release-spinlock spinlock)))
index 3f16fa1..2c1247a 100644 (file)
 (use-package :test-util)
 
 (sb-alien:define-alien-routine "check_deferrables_blocked_or_lose"
-    void)
+    void
+  (where sb-alien:unsigned-long))
 (sb-alien:define-alien-routine "check_deferrables_unblocked_or_lose"
-    void)
+    void
+  (where sb-alien:unsigned-long))
 
 (defun make-limited-timer (fn n &rest args)
   (let (timer)
 
 (with-test (:name (:timer :deferrables-blocked))
   (make-and-schedule-and-wait (lambda ()
-                                (check-deferrables-blocked-or-lose))
+                                (check-deferrables-blocked-or-lose 0))
                               (random 0.1))
-  (check-deferrables-unblocked-or-lose))
+  (check-deferrables-unblocked-or-lose 0))
 
 (with-test (:name (:timer :deferrables-unblocked))
   (make-and-schedule-and-wait (lambda ()
                                 (sb-sys:with-interrupts
-                                  (check-deferrables-unblocked-or-lose)))
+                                  (check-deferrables-unblocked-or-lose 0)))
                               (random 0.1))
-  (check-deferrables-unblocked-or-lose))
+  (check-deferrables-unblocked-or-lose 0))
 
 #-win32
 (with-test (:name (:timer :deferrables-unblocked :unwind))
   (catch 'xxx
     (make-and-schedule-and-wait (lambda ()
-                                  (check-deferrables-blocked-or-lose)
+                                  (check-deferrables-blocked-or-lose 0)
                                   (throw 'xxx nil))
                                 (random 0.1))
     (sleep 1))
-  (check-deferrables-unblocked-or-lose))
+  (check-deferrables-unblocked-or-lose 0))
 
 (defmacro raises-timeout-p (&body body)
   `(handler-case (progn (progn ,@body) nil)
index 03710c9..56cd6de 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.26.14"
+"1.0.26.15"