1.0.25.47: OOAO restoring fp control word
authorGabor Melis <mega@hotpop.com>
Mon, 16 Feb 2009 22:20:16 +0000 (22:20 +0000)
committerGabor Melis <mega@hotpop.com>
Mon, 16 Feb 2009 22:20:16 +0000 (22:20 +0000)
Do it in all signal handlers, no matter what, on platforms that
require it.

12 files changed:
src/runtime/alpha-arch.c
src/runtime/interrupt.c
src/runtime/mips-arch.c
src/runtime/ppc-arch.c
src/runtime/sparc-arch.c
src/runtime/x86-64-arch.c
src/runtime/x86-64-linux-os.c
src/runtime/x86-64-linux-os.h
src/runtime/x86-arch.c
src/runtime/x86-linux-os.c
src/runtime/x86-linux-os.h
version.lisp-expr

index 77fbbc1..2f1c559 100644 (file)
@@ -319,9 +319,6 @@ static void
 sigtrap_handler(int signal, siginfo_t *siginfo, os_context_t *context)
 {
     unsigned int code;
-#ifdef LISP_FEATURE_LINUX
-    os_restore_fp_control(context);
-#endif
 
     /* this is different from how CMUCL does it.  CMUCL used "call_pal
      * PAL_gentrap", which doesn't do anything on Linux (unless NL0
index f651742..921f3b7 100644 (file)
 #include "genesis/simple-fun.h"
 #include "genesis/cons.h"
 
+/* 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. */
+#if defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
+#define RESTORE_FP_CONTROL_WORD(context,void_context)           \
+    os_context_t *context = arch_os_get_context(&void_context); \
+    os_restore_fp_control(context);
+#else
+#define RESTORE_FP_CONTROL_WORD(context,void_context)           \
+    os_context_t *context = arch_os_get_context(&void_context);
+#endif
+
 /* These are to be used in signal handlers. Currently all handlers are
  * called from one of:
  *
  * low_level_maybe_now_maybe_later
  * low_level_unblock_me_trampoline
  */
-#define SAVE_ERRNO()                                            \
+#define SAVE_ERRNO(context,void_context)                        \
     {                                                           \
         int _saved_errno = errno;                               \
+        RESTORE_FP_CONTROL_WORD(context,void_context);          \
         {
 
 #define RESTORE_ERRNO                                           \
@@ -854,13 +867,6 @@ interrupt_handle_now(int signal, siginfo_t *info, os_context_t *context)
         check_interrupts_enabled_or_lose(context);
 #endif
 
-#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
-    /* 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];
 
     if (ARE_SAME_HANDLER(handler.c, SIG_IGN)) {
@@ -1044,15 +1050,10 @@ store_signal_data_for_later (struct interrupt_data *data, void *handler,
 static void
 maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context)
 {
-    SAVE_ERRNO();
-    os_context_t *context = arch_os_get_context(&void_context);
+    SAVE_ERRNO(context,void_context);
     struct thread *thread = arch_os_get_current_thread();
     struct interrupt_data *data = thread->interrupt_data;
 
-#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
-    os_restore_fp_control(context);
-#endif
-
     if(!maybe_defer_handler(interrupt_handle_now,data,signal,info,context))
         interrupt_handle_now(signal, info, context);
     RESTORE_ERRNO;
@@ -1072,15 +1073,10 @@ low_level_interrupt_handle_now(int signal, siginfo_t *info,
 static void
 low_level_maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context)
 {
-    SAVE_ERRNO();
-    os_context_t *context = arch_os_get_context(&void_context);
+    SAVE_ERRNO(context,void_context);
     struct thread *thread = arch_os_get_current_thread();
     struct interrupt_data *data = thread->interrupt_data;
 
-#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
-    os_restore_fp_control(context);
-#endif
-
     if(!maybe_defer_handler(low_level_interrupt_handle_now,data,
                             signal,info,context))
         low_level_interrupt_handle_now(signal, info, context);
@@ -1153,10 +1149,7 @@ sig_stop_for_gc_handler(int signal, siginfo_t *info, void *void_context)
 void
 interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context)
 {
-    SAVE_ERRNO();
-    os_context_t *context = arch_os_get_context(&void_context);
-#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
-    os_restore_fp_control(context);
+    SAVE_ERRNO(context,void_context);
 #ifndef LISP_FEATURE_WIN32
     if ((signal == SIGILL) || (signal == SIGBUS)
 #ifndef LISP_FEATURE_LINUX
@@ -1165,7 +1158,6 @@ interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context)
         )
         corruption_warning_and_maybe_lose("Signal %d recieved", signal);
 #endif
-#endif
     interrupt_handle_now(signal, info, context);
     RESTORE_ERRNO;
 }
@@ -1195,7 +1187,7 @@ arrange_return_to_lisp_function(os_context_t *context, lispobj function)
     /* Build a stack frame showing `interrupted' so that the
      * user's backtrace makes (as much) sense (as usual) */
 
-    /* FIXME: what about restoring fp state? */
+    /* fp state is saved and restored by call_into_lisp */
     /* FIXME: errno is not restored, but since current uses of this
      * function only call Lisp code that signals an error, it's not
      * much of a problem. In other words, running out of the control
@@ -1495,8 +1487,7 @@ see_if_sigaction_nodefer_works(void)
 static void
 unblock_me_trampoline(int signal, siginfo_t *info, void *void_context)
 {
-    SAVE_ERRNO();
-    os_context_t *context = arch_os_get_context(&void_context);
+    SAVE_ERRNO(context,void_context);
     sigset_t unblock;
 
     sigemptyset(&unblock);
@@ -1509,7 +1500,7 @@ unblock_me_trampoline(int signal, siginfo_t *info, void *void_context)
 static void
 low_level_unblock_me_trampoline(int signal, siginfo_t *info, void *void_context)
 {
-    SAVE_ERRNO();
+    SAVE_ERRNO(context,void_context);
     sigset_t unblock;
 
     sigemptyset(&unblock);
@@ -1522,7 +1513,7 @@ low_level_unblock_me_trampoline(int signal, siginfo_t *info, void *void_context)
 static void
 low_level_handle_now_handler(int signal, siginfo_t *info, void *void_context)
 {
-    SAVE_ERRNO();
+    SAVE_ERRNO(context,void_context);
     (*interrupt_low_level_handlers[signal])(signal, info, void_context);
     RESTORE_ERRNO;
 }
index b33b118..48045a9 100644 (file)
@@ -400,9 +400,6 @@ sigtrap_handler(int signal, siginfo_t *info, void *void_context)
 {
     os_context_t *context = arch_os_get_context(&void_context);
     unsigned int code = (os_context_insn(context) >> 6) & 0xfffff;
-#ifdef LISP_FEATURE_LINUX
-    os_restore_fp_control(context);
-#endif
     /* FIXME: This magic number is pseudo-atomic-trap from parms.lisp.
      * Genesis should provide the proper #define, but it specialcases
      * pseudo-atomic-trap to work around some oddity on SPARC.
@@ -425,9 +422,6 @@ sigfpe_handler(int signal, siginfo_t *info, void *void_context)
     unsigned int op, rs, rt, rd, funct, dest = 32;
     int immed;
     int result;
-#ifdef LISP_FEATURE_LINUX
-    os_restore_fp_control(context);
-#endif
 
     op = (bad_inst >> 26) & 0x3f;
     rs = (bad_inst >> 21) & 0x1f;
index 5e6b885..297fbf0 100644 (file)
@@ -428,9 +428,6 @@ sigtrap_handler(int signal, siginfo_t *siginfo, void *void_context)
     unsigned int code;
     os_context_t *context = void_context;
 
-#ifdef LISP_FEATURE_LINUX
-    os_restore_fp_control(context);
-#endif
     code=*((u32 *)(*os_context_pc_addr(context)));
     if (code == ((3 << 26) | (0x18 << 21) | (reg_NL3 << 16))) {
         arch_clear_pseudo_atomic_interrupted(context);
index f32c06d..79d1809 100644 (file)
@@ -254,10 +254,6 @@ arch_handle_single_step_trap(os_context_t *context, int trap)
 static void sigill_handler(int signal, siginfo_t *siginfo, void *void_context)
 {
     os_context_t *context = arch_os_get_context(&void_context);
-#ifdef LISP_FEATURE_LINUX
-    /* FIXME: Check that this is necessary -- CSR, 2002-07-15 */
-    os_restore_fp_control(context);
-#endif
 
     if ((siginfo->si_code) == ILL_ILLOPC
 #ifdef LISP_FEATURE_LINUX
@@ -301,9 +297,6 @@ static void sigemt_handler(int signal, siginfo_t *siginfo, void *void_context)
     boolean subtract, immed;
     int rd, rs1, op1, rs2, op2, result;
     os_context_t *context = arch_os_get_context(&void_context);
-#ifdef LISP_FEATURE_LINUX
-    os_restore_fp_control(context);
-#endif
 
     badinst = *(unsigned int *)os_context_pc_addr(context);
     if ((badinst >> 30) != 2 || ((badinst >> 20) & 0x1f) != 0x11) {
index d075ce6..2a625d8 100644 (file)
@@ -263,16 +263,6 @@ sigtrap_handler(int signal, siginfo_t *info, void *void_context)
     current_control_stack_pointer =
         (lispobj *)*os_context_sp_addr(context);
 
-    /* FIXME: CMUCL puts the float control restoration code here.
-       Thus, it seems to me that single-stepping won't restore the
-       float control.  Since SBCL currently doesn't support
-       single-stepping (as far as I can tell) this is somewhat moot,
-       but it might be worth either moving this code up or deleting
-       the single-stepping code entirely.  -- CSR, 2002-07-15 */
-#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
-    os_restore_fp_control(context);
-#endif
-
     /* On entry %eip points just after the INT3 byte and aims at the
      * 'kind' value (eg trap_Cerror). For error-trap and Cerror-trap a
      * number of bytes will follow, the first is the length of the byte
index 12d4266..d3d2c30 100644 (file)
@@ -151,11 +151,13 @@ os_context_sigmask_addr(os_context_t *context)
 void
 os_restore_fp_control(os_context_t *context)
 {
-    /* reset exception flags and restore control flags on SSE2 FPU */
-    unsigned int temp = (context->uc_mcontext.fpregs->mxcsr) & ~0x3F;
-    asm ("ldmxcsr %0" : : "m" (temp));
-    /* same for x87 FPU. */
-    asm ("fldcw %0" : : "m" (context->uc_mcontext.fpregs->cwd));
+    if (context->uc_mcontext.fpregs) {
+        /* reset exception flags and restore control flags on SSE2 FPU */
+        unsigned int temp = (context->uc_mcontext.fpregs->mxcsr) & ~0x3F;
+        asm ("ldmxcsr %0" : : "m" (temp));
+        /* same for x87 FPU. */
+        asm ("fldcw %0" : : "m" (context->uc_mcontext.fpregs->cwd));
+    }
 }
 
 void
index 48e3e25..60c6122 100644 (file)
@@ -10,6 +10,7 @@ static inline os_context_t *arch_os_get_context(void **void_context)
 }
 
 unsigned long os_context_fp_control(os_context_t *context);
+#define RESTORE_FP_CONTROL_FROM_CONTEXT
 void os_restore_fp_control(os_context_t *context);
 
 #endif /* _X86_64_LINUX_OS_H */
index 3ef4bec..6babc96 100644 (file)
@@ -274,16 +274,6 @@ sigtrap_handler(int signal, siginfo_t *info, void *void_context)
     current_control_stack_pointer =
         (lispobj *)*os_context_sp_addr(context);
 
-    /* FIXME: CMUCL puts the float control restoration code here.
-       Thus, it seems to me that single-stepping won't restore the
-       float control.  Since SBCL currently doesn't support
-       single-stepping (as far as I can tell) this is somewhat moot,
-       but it might be worth either moving this code up or deleting
-       the single-stepping code entirely.  -- CSR, 2002-07-15 */
-#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
-    os_restore_fp_control(context);
-#endif
-
 #ifdef LISP_FEATURE_SUNOS
     /* For some reason the breakpoints that :ENCAPSULATE NIL tracing sets up
      * cause a trace trap (i.e. processor single-stepping trap) on the following
index c15665d..ddbe154 100644 (file)
@@ -208,7 +208,8 @@ os_context_sigmask_addr(os_context_t *context)
 void
 os_restore_fp_control(os_context_t *context)
 {
-    asm ("fldcw %0" : : "m" (context->uc_mcontext.fpregs->cw));
+    if (context->uc_mcontext.fpregs)
+        asm ("fldcw %0" : : "m" (context->uc_mcontext.fpregs->cw));
 }
 
 void
index 6e688c6..f2a39f9 100644 (file)
@@ -10,6 +10,7 @@ static inline os_context_t *arch_os_get_context(void **void_context)
 }
 
 unsigned long os_context_fp_control(os_context_t *context);
+#define RESTORE_FP_CONTROL_FROM_CONTEXT
 void os_restore_fp_control(os_context_t *context);
 
 #endif /* _X86_LINUX_OS_H */
index c1e27f0..72d53b0 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.46"
+"1.0.25.47"