0.7.13.5
[sbcl.git] / src / runtime / interrupt.c
index feb2cc9..4027b3d 100644 (file)
 #include "alloc.h"
 #include "dynbind.h"
 #include "interr.h"
+#include "genesis/simple-fun.h"
+#include "genesis/fdefn.h"
+#include "genesis/symbol.h"
+#include "genesis/static-symbols.h"
 
 void sigaddset_blockable(sigset_t *s)
 {
@@ -99,7 +103,7 @@ static int pending_signal = 0;
 static siginfo_t pending_info;
 static sigset_t pending_mask;
 
-static boolean maybe_gc_pending = 0;
+boolean maybe_gc_pending = 0;
 \f
 /*
  * utility routines used by various signal handlers
@@ -342,6 +346,15 @@ interrupt_handle_pending(os_context_t *context)
  * the two main signal handlers:
  *   interrupt_handle_now(..)
  *   maybe_now_maybe_later(..)
+ *
+ * to which we have added interrupt_handle_now_handler(..).  Why?
+ * Well, mostly because 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; however, we only
+ * want to do this when we first hit the handler, and not when
+ * interrupt_handle_now(..) is being called from some other handler
+ * (when the fixup will already have been done). -- CSR, 2002-07-23
  */
 
 void
@@ -354,9 +367,9 @@ interrupt_handle_now(int signal, siginfo_t *info, void *void_context)
     union interrupt_handler handler;
 
 #ifdef LISP_FEATURE_LINUX
-    /* Under Linux, we appear to have to restore the fpu control word
-       from the context, as after the signal is delivered we appear to
-       have a null fpu control word. */
+    /* Under Linux on some architectures, we appear to have to restore
+       the FPU control word from the context, as after the signal is
+       delivered we appear to have a null FPU control word. */
     os_restore_fp_control(context);
 #endif 
     handler = interrupt_handlers[signal];
@@ -434,15 +447,8 @@ interrupt_handle_now(int signal, siginfo_t *info, void *void_context)
 static void
 maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context)
 {
-    os_context_t *context = (os_context_t*)void_context;
+    os_context_t *context = arch_os_get_context(&void_context);
 
-    /* FIXME: See Debian cmucl 2.4.17, and mail from DTC on the CMU CL
-     * mailing list 23 Oct 1999, for changes in FPU handling at
-     * interrupt time which should be ported into SBCL. Also see the
-     * analogous logic at the head of interrupt_handle_now for
-     * more related FIXME stuff. 
-     */
-    
 #ifdef LISP_FEATURE_LINUX
     os_restore_fp_control(context);
 #endif 
@@ -488,11 +494,20 @@ maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context)
     }
 }
 \f
+
+void
+interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context)
+{
+    os_context_t *context = arch_os_get_context(&void_context);
+    interrupt_handle_now(signal, info, context);
+}
+
 /*
  * stuff to detect and handle hitting the GC trigger
  */
 
-#ifndef GENCGC /* since GENCGC has its own way to record trigger */
+#ifndef LISP_FEATURE_GENCGC 
+/* since GENCGC has its own way to record trigger */
 static boolean
 gc_trigger_hit(int signal, siginfo_t *info, os_context_t *context)
 {
@@ -512,41 +527,57 @@ boolean handle_control_stack_guard_triggered(os_context_t *context,void *addr)
 {
     /* note the os_context hackery here.  When the signal handler returns, 
      * it won't go back to what it was doing ... */
-    if(addr>=CONTROL_STACK_GUARD_PAGE && 
-       addr<(CONTROL_STACK_GUARD_PAGE+os_vm_page_size)) {
-       void *function;
+    if(addr>=(void *)CONTROL_STACK_GUARD_PAGE && 
+       addr<(void *)(CONTROL_STACK_GUARD_PAGE+os_vm_page_size)) {
+       void *fun;
+       void *code;
+       
        /* we hit the end of the control stack.  disable protection
         * temporarily so the error handler has some headroom */
        protect_control_stack_guard_page(0);
        
-       function=
-           &(((struct simple_fun *)
-              native_pointer(SymbolFunction(CONTROL_STACK_EXHAUSTED_ERROR)))
-             ->code);
+       fun = (void *)
+           native_pointer((lispobj) SymbolFunction(CONTROL_STACK_EXHAUSTED_ERROR));
+       code = &(((struct simple_fun *) fun)->code);
 
        /* Build a stack frame showing `interrupted' so that the
         * user's backtrace makes (as much) sense (as usual) */
        build_fake_control_stack_frames(context);
        /* signal handler will "return" to this error-causing function */
-       *os_context_pc_addr(context)= function;
-#ifndef LISP_FEATURE_X86
+       *os_context_pc_addr(context) = code;
+#ifdef LISP_FEATURE_X86
+       *os_context_register_addr(context,reg_ECX) = 0; 
+#else
        /* this much of the calling convention is common to all
           non-x86 ports */
-       *os_context_register_addr(context,reg_NARGS)=0; 
-       *os_context_register_addr(context,reg_LIP)= function;
-       *os_context_register_addr(context,reg_CFP)= 
+       *os_context_register_addr(context,reg_NARGS) = 0; 
+       *os_context_register_addr(context,reg_LIP) = code;
+       *os_context_register_addr(context,reg_CFP) = 
            current_control_frame_pointer;
+#endif
 #ifdef ARCH_HAS_NPC_REGISTER
-       *os_context_register_addr(context,reg_LIP)=
-           4+*os_context_pc_addr(context);
+       *os_context_npc_addr(context) =
+           4 + *os_context_pc_addr(context);
 #endif
+#ifdef LISP_FEATURE_SPARC
+       /* Bletch.  This is a feature of the SPARC calling convention,
+          which sadly I'm not going to go into in large detail here,
+          as I don't know it well enough.  Suffice to say that if the
+          line 
+
+          (INST MOVE CODE-TN FUNCTION) 
+
+          in compiler/sparc/call.lisp is changed, then this bit can
+          probably go away.  -- CSR, 2002-07-24 */
+       *os_context_register_addr(context,reg_CODE) = 
+           fun + FUN_POINTER_LOWTAG;
 #endif
        return 1;
     }
     else return 0;
 }
 
-#ifndef __i386__
+#ifndef LISP_FEATURE_X86
 /* This function gets called from the SIGSEGV (for e.g. Linux or
  * OpenBSD) or SIGBUS (for e.g. FreeBSD) handler. Here we check
  * whether the signal was due to treading on the mprotect()ed zone -
@@ -557,11 +588,13 @@ interrupt_maybe_gc(int signal, siginfo_t *info, void *void_context)
     os_context_t *context=(os_context_t *) void_context;
 
     if (!foreign_function_call_active
-#ifndef GENCGC /* since GENCGC has its own way to record trigger */
+#ifndef LISP_FEATURE_GENCGC 
+       /* nb: GENCGC on non-x86?  I really don't think so.  This
+        * happens every time */
        && gc_trigger_hit(signal, info, context)
 #endif
        ) {
-#ifndef GENCGC /* since GENCGC has its own way to record trigger */
+#ifndef LISP_FEATURE_GENCGC 
        clear_auto_gc_trigger();
 #endif
 
@@ -720,7 +753,7 @@ install_handler(int signal, void handler(int, siginfo_t*, void*))
        } else if (sigismember(&new, signal)) {
            sa.sa_sigaction = maybe_now_maybe_later;
        } else {
-           sa.sa_sigaction = interrupt_handle_now;
+           sa.sa_sigaction = interrupt_handle_now_handler;
        }
 
        sigemptyset(&sa.sa_mask);