1.0.25.35: check that gc signals are unblocked
authorGabor Melis <mega@hotpop.com>
Mon, 16 Feb 2009 21:54:06 +0000 (21:54 +0000)
committerGabor Melis <mega@hotpop.com>
Mon, 16 Feb 2009 21:54:06 +0000 (21:54 +0000)
... when alloc() is called and when calling into Lisp.

doc/internals/signals.texinfo
src/runtime/alloc.c
src/runtime/breakpoint.c
src/runtime/funcall.c
src/runtime/interrupt.c
version.lisp-expr

index 33c0adf..e5cfceb 100644 (file)
@@ -145,6 +145,10 @@ derive the rule: in a @code{WITHOUT-GCING} form (or pseudo atomic for
 that matter) never wait for another thread that's not in
 @code{WITHOUT-GCING}.
 
+Somewhat of a special case, it is enforced by the runtime that
+@code{SIG_STOP_FOR_GC} and @code{SIG_RESUME_FROM_GC} always unblocked
+when we might trigger a gc (i.e. on alloc or calling into Lisp).
+
 @subsection Calling user code
 
 For the reasons above, calling user code, i.e. functions passed in, or
index f42be24..dc4f5f2 100644 (file)
@@ -40,6 +40,12 @@ pa_alloc(int bytes, int page_type_flag)
     lispobj *result;
     struct thread *th = arch_os_get_current_thread();
 
+    /* SIG_STOP_FOR_GC needs to be enabled before we can call lisp:
+     * 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();
+
     /* FIXME: OOAO violation: see arch_pseudo_* */
     set_pseudo_atomic_atomic(th);
     result = general_alloc(bytes, page_type_flag);
index 18f96d8..5dfa9a4 100644 (file)
@@ -130,6 +130,7 @@ void handle_breakpoint(os_context_t *context)
 
     fake_foreign_function_call(context);
 
+    unblock_gc_signals();
     context_sap = alloc_sap(context);
     code = find_code(context);
 
@@ -154,6 +155,7 @@ void *handle_fun_end_breakpoint(os_context_t *context)
 
     fake_foreign_function_call(context);
 
+    unblock_gc_signals();
     context_sap = alloc_sap(context);
     code = find_code(context);
     codeptr = (struct code *)native_pointer(code);
index e364ec2..186435c 100644 (file)
 #include "sbcl.h"
 #include "runtime.h"
 #include "globals.h"
+#include "os.h"
+#include "interrupt.h"
 
 /* This is implemented in assembly language and called from C: */
 extern lispobj call_into_lisp(lispobj fun, lispobj *args, int nargs);
 
+static inline lispobj
+safe_call_into_lisp(lispobj fun, lispobj *args, int nargs)
+{
+    /* SIG_STOP_FOR_GC needs to be enabled before we can call lisp:
+     * 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();
+    return call_into_lisp(fun, args, nargs);
+}
+
 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
 /* These functions are an interface to the Lisp call-in facility.
  * Since this is C we can know nothing about the calling environment.
@@ -38,14 +51,14 @@ funcall0(lispobj function)
     lispobj *args = NULL;
 
     FSHOW((stderr, "/entering funcall0(0x%lx)\n", (long)function));
-    return call_into_lisp(function, args, 0);
+    return safe_call_into_lisp(function, args, 0);
 }
 lispobj
 funcall1(lispobj function, lispobj arg0)
 {
     lispobj args[1];
     args[0] = arg0;
-    return call_into_lisp(function, args, 1);
+    return safe_call_into_lisp(function, args, 1);
 }
 
 lispobj
@@ -54,7 +67,7 @@ funcall2(lispobj function, lispobj arg0, lispobj arg1)
     lispobj args[2];
     args[0] = arg0;
     args[1] = arg1;
-    return call_into_lisp(function, args, 2);
+    return safe_call_into_lisp(function, args, 2);
 }
 
 lispobj
@@ -64,7 +77,7 @@ funcall3(lispobj function, lispobj arg0, lispobj arg1, lispobj arg2)
     args[0] = arg0;
     args[1] = arg1;
     args[2] = arg2;
-    return call_into_lisp(function, args, 3);
+    return safe_call_into_lisp(function, args, 3);
 }
 
 #else
@@ -74,7 +87,7 @@ funcall0(lispobj function)
 {
     lispobj *args = current_control_stack_pointer;
 
-    return call_into_lisp(function, args, 0);
+    return safe_call_into_lisp(function, args, 0);
 }
 
 lispobj
@@ -85,7 +98,7 @@ funcall1(lispobj function, lispobj arg0)
     current_control_stack_pointer += 1;
     args[0] = arg0;
 
-    return call_into_lisp(function, args, 1);
+    return safe_call_into_lisp(function, args, 1);
 }
 
 lispobj
@@ -97,7 +110,7 @@ funcall2(lispobj function, lispobj arg0, lispobj arg1)
     args[0] = arg0;
     args[1] = arg1;
 
-    return call_into_lisp(function, args, 2);
+    return safe_call_into_lisp(function, args, 2);
 }
 
 lispobj
@@ -110,6 +123,6 @@ funcall3(lispobj function, lispobj arg0, lispobj arg1, lispobj arg2)
     args[1] = arg1;
     args[2] = arg2;
 
-    return call_into_lisp(function, args, 3);
+    return safe_call_into_lisp(function, args, 3);
 }
 #endif
index d44e53c..ff62022 100644 (file)
@@ -489,6 +489,7 @@ interrupt_internal_error(os_context_t *context, boolean continuable)
 
     /* Allocate the SAP object while the interrupts are still
      * disabled. */
+    unblock_gc_signals();
     context_sap = alloc_sap(context);
 
 #ifndef LISP_FEATURE_WIN32
@@ -693,21 +694,12 @@ interrupt_handle_now(int signal, siginfo_t *info, os_context_t *context)
          * Yeah, but non-gencgc platforms don't really wrap allocation
          * in PA. MG - 2005-08-29  */
 
-        lispobj info_sap,context_sap = alloc_sap(context);
-        info_sap = alloc_sap(info);
+        lispobj info_sap, context_sap;
         /* Leave deferrable signals blocked, the handler itself will
          * allow signals again when it sees fit. */
-#ifdef LISP_FEATURE_SB_THREAD
-        {
-            sigset_t unblock;
-            sigemptyset(&unblock);
-            sigaddset(&unblock, SIG_STOP_FOR_GC);
-#ifdef SIG_RESUME_FROM_GC
-            sigaddset(&unblock, SIG_RESUME_FROM_GC);
-#endif
-            thread_sigmask(SIG_UNBLOCK, &unblock, 0);
-        }
-#endif
+        unblock_gc_signals();
+        context_sap = alloc_sap(context);
+        info_sap = alloc_sap(info);
 
         FSHOW_SIGNAL((stderr,"/calling Lisp-level handler\n"));
 
@@ -966,6 +958,8 @@ extern void call_into_lisp_tramp(void);
 void
 arrange_return_to_lisp_function(os_context_t *context, lispobj function)
 {
+    check_gc_signals_unblocked_in_sigset_or_lose
+        (os_context_sigmask_addr(context));
 #if !(defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64))
     void * fun=native_pointer(function);
     void *code = &(((struct simple_fun *) fun)->code);
@@ -1460,6 +1454,7 @@ unhandled_trap_error(os_context_t *context)
 {
     lispobj context_sap;
     fake_foreign_function_call(context);
+    unblock_gc_signals();
     context_sap = alloc_sap(context);
 #ifndef LISP_FEATURE_WIN32
     thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
index 9c15bfe..4b69e45 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.25.34"
+"1.0.25.35"