1.0.4.4: simplify JOIN-THREAD interface
[sbcl.git] / src / runtime / interrupt.c
index 357a5b2..eb1e834 100644 (file)
@@ -123,9 +123,9 @@ static sigset_t blockable_sigset;
 #endif
 
 void
-check_blockables_blocked_or_lose()
+check_blockables_blocked_or_lose(void)
 {
-#ifndef LISP_FEATURE_WIN32
+#if !defined(LISP_FEATURE_WIN32)
     /* Get the current sigmask, by blocking the empty set. */
     sigset_t empty,current;
     int i;
@@ -138,6 +138,41 @@ check_blockables_blocked_or_lose()
 #endif
 }
 
+void
+check_gc_signals_unblocked_or_lose(void)
+{
+#ifdef LISP_FEATURE_SB_THREAD
+# if !defined(LISP_FEATURE_WIN32)
+    /* Get the current sigmask, by blocking the empty set. */
+    sigset_t empty,current;
+    sigemptyset(&empty);
+    thread_sigmask(SIG_BLOCK, &empty, &current);
+    if (sigismember(&current, SIG_STOP_FOR_GC))
+        lose("SIG_STOP_FOR_GC blocked in thread %p at a bad place\n",
+             arch_os_get_current_thread());
+#  if defined(SIG_RESUME_FROM_GC)
+    if (sigismember(&current, SIG_RESUME_FROM_GC))
+        lose("SIG_RESUME_FROM_GC blocked in thread %p at a bad place\n",
+             arch_os_get_current_thread());
+#  endif
+# endif
+#endif
+}
+
+void
+unblock_gc_signals(void)
+{
+#ifdef LISP_FEATURE_SB_THREAD
+    sigset_t new;
+    sigemptyset(&new);
+#if defined(SIG_RESUME_FROM_GC)
+    sigaddset(&new,SIG_RESUME_FROM_GC);
+#endif
+    sigaddset(&new,SIG_STOP_FOR_GC);
+    thread_sigmask(SIG_UNBLOCK,&new,0);
+#endif
+}
+
 inline static void
 check_interrupts_enabled_or_lose(os_context_t *context)
 {
@@ -186,6 +221,14 @@ block_blockable_signals(void)
 #endif
 }
 
+void
+block_deferrable_signals(void)
+{
+#ifndef LISP_FEATURE_WIN32
+    thread_sigmask(SIG_BLOCK, &deferrable_sigset, 0);
+#endif
+}
+
 \f
 /*
  * utility routines used by various signal handlers
@@ -576,7 +619,6 @@ run_deferred_handler(struct interrupt_data *data, void *v_context) {
      * pending handler before calling it. Trust the handler to finish
      * with the siginfo before enabling interrupts. */
     void (*pending_handler) (int, siginfo_t*, void*)=data->pending_handler;
-    os_context_t *context = arch_os_get_context(&v_context);
 
     data->pending_handler=0;
     (*pending_handler)(data->pending_signal,&(data->pending_info), v_context);
@@ -740,7 +782,7 @@ sig_stop_for_gc_handler(int signal, siginfo_t *info, void *void_context)
     struct thread *thread=arch_os_get_current_thread();
     sigset_t ss;
 
-   if ((arch_pseudo_atomic_atomic(context) ||
+    if ((arch_pseudo_atomic_atomic(context) ||
          SymbolValue(GC_INHIBIT,thread) != NIL)) {
         SetSymbolValue(STOP_FOR_GC_PENDING,T,thread);
         if (SymbolValue(GC_INHIBIT,thread) == NIL)
@@ -814,7 +856,7 @@ gc_trigger_hit(int signal, siginfo_t *info, os_context_t *context)
     else{
         void *badaddr=arch_get_bad_addr(signal,info,context);
         return (badaddr >= (void *)current_auto_gc_trigger &&
-                badaddr <((void *)current_dynamic_space + DYNAMIC_SPACE_SIZE));
+                badaddr <((void *)current_dynamic_space + dynamic_space_size));
     }
 }
 #endif
@@ -930,6 +972,7 @@ arrange_return_to_lisp_function(os_context_t *context, lispobj function)
 
 #elif defined(LISP_FEATURE_X86_64)
     u64 *sp=(u64 *)*os_context_register_addr(context,reg_RSP);
+
     /* return address for call_into_lisp: */
     *(sp-18) = (u64)post_signal_tramp;
 
@@ -1139,22 +1182,14 @@ interrupt_maybe_gc_int(int signal, siginfo_t *info, void *void_context)
      * outer context.
      */
 #ifndef LISP_FEATURE_WIN32
-    if(SymbolValue(INTERRUPTS_ENABLED,thread)!=NIL)
+    if(SymbolValue(INTERRUPTS_ENABLED,thread)!=NIL) {
         thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
-#ifdef LISP_FEATURE_SB_THREAD
-    else {
-        sigset_t new;
-        sigemptyset(&new);
-#if defined(SIG_RESUME_FROM_GC)
-        sigaddset(&new,SIG_RESUME_FROM_GC);
-#endif
-        sigaddset(&new,SIG_STOP_FOR_GC);
-        thread_sigmask(SIG_UNBLOCK,&new,0);
+        check_gc_signals_unblocked_or_lose();
     }
-#endif
+    else
+        unblock_gc_signals();
 #endif
     funcall0(SymbolFunction(SUB_GC));
-
     undo_fake_foreign_function_call(context);
     return 1;
 }
@@ -1189,7 +1224,7 @@ sigaction_nodefer_test_handler(int signal, siginfo_t *info, void *void_context)
     sigset_t empty, current;
     int i;
     sigemptyset(&empty);
-    sigprocmask(SIG_BLOCK, &empty, &current);
+    thread_sigmask(SIG_BLOCK, &empty, &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
@@ -1220,7 +1255,7 @@ see_if_sigaction_nodefer_works()
     {
         sigset_t empty;
         sigemptyset(&empty);
-        sigprocmask(SIG_SETMASK, &empty, 0);
+        thread_sigmask(SIG_SETMASK, &empty, 0);
     }
     kill(getpid(), SA_NODEFER_TEST_KILL_SIGNAL);
     while (sigaction_nodefer_works == -1);
@@ -1376,3 +1411,24 @@ interrupt_init()
     SHOW("returning from interrupt_init()");
 #endif
 }
+
+#ifndef LISP_FEATURE_WIN32
+int
+siginfo_code(siginfo_t *info)
+{
+    return info->si_code;
+}
+os_vm_address_t current_memory_fault_address;
+
+void
+lisp_memory_fault_error(os_context_t *context, os_vm_address_t addr)
+{
+   /* FIXME: This is lossy: if we get another memory fault (eg. from
+    * another thread) before lisp has read this, we the information.
+    * However, since this is mostly informative, we'll live with that for
+    * now -- some address is better then no address in this case.
+    */
+    current_memory_fault_address = addr;
+    arrange_return_to_lisp_function(context, SymbolFunction(MEMORY_FAULT_ERROR));
+}
+#endif