From 842d3c24e4a1a6b5ebadb9ee754814174a951029 Mon Sep 17 00:00:00 2001 From: Gabor Melis Date: Mon, 16 Feb 2009 22:20:16 +0000 Subject: [PATCH] 1.0.25.47: OOAO restoring fp control word Do it in all signal handlers, no matter what, on platforms that require it. --- src/runtime/alpha-arch.c | 3 --- src/runtime/interrupt.c | 51 +++++++++++++++++------------------------ src/runtime/mips-arch.c | 6 ----- src/runtime/ppc-arch.c | 3 --- src/runtime/sparc-arch.c | 7 ------ src/runtime/x86-64-arch.c | 10 -------- src/runtime/x86-64-linux-os.c | 12 ++++++---- src/runtime/x86-64-linux-os.h | 1 + src/runtime/x86-arch.c | 10 -------- src/runtime/x86-linux-os.c | 3 ++- src/runtime/x86-linux-os.h | 1 + version.lisp-expr | 2 +- 12 files changed, 33 insertions(+), 76 deletions(-) diff --git a/src/runtime/alpha-arch.c b/src/runtime/alpha-arch.c index 77fbbc1..2f1c559 100644 --- a/src/runtime/alpha-arch.c +++ b/src/runtime/alpha-arch.c @@ -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 diff --git a/src/runtime/interrupt.c b/src/runtime/interrupt.c index f651742..921f3b7 100644 --- a/src/runtime/interrupt.c +++ b/src/runtime/interrupt.c @@ -68,6 +68,18 @@ #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: * @@ -78,9 +90,10 @@ * 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; } diff --git a/src/runtime/mips-arch.c b/src/runtime/mips-arch.c index b33b118..48045a9 100644 --- a/src/runtime/mips-arch.c +++ b/src/runtime/mips-arch.c @@ -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; diff --git a/src/runtime/ppc-arch.c b/src/runtime/ppc-arch.c index 5e6b885..297fbf0 100644 --- a/src/runtime/ppc-arch.c +++ b/src/runtime/ppc-arch.c @@ -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); diff --git a/src/runtime/sparc-arch.c b/src/runtime/sparc-arch.c index f32c06d..79d1809 100644 --- a/src/runtime/sparc-arch.c +++ b/src/runtime/sparc-arch.c @@ -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) { diff --git a/src/runtime/x86-64-arch.c b/src/runtime/x86-64-arch.c index d075ce6..2a625d8 100644 --- a/src/runtime/x86-64-arch.c +++ b/src/runtime/x86-64-arch.c @@ -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 diff --git a/src/runtime/x86-64-linux-os.c b/src/runtime/x86-64-linux-os.c index 12d4266..d3d2c30 100644 --- a/src/runtime/x86-64-linux-os.c +++ b/src/runtime/x86-64-linux-os.c @@ -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 diff --git a/src/runtime/x86-64-linux-os.h b/src/runtime/x86-64-linux-os.h index 48e3e25..60c6122 100644 --- a/src/runtime/x86-64-linux-os.h +++ b/src/runtime/x86-64-linux-os.h @@ -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 */ diff --git a/src/runtime/x86-arch.c b/src/runtime/x86-arch.c index 3ef4bec..6babc96 100644 --- a/src/runtime/x86-arch.c +++ b/src/runtime/x86-arch.c @@ -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 diff --git a/src/runtime/x86-linux-os.c b/src/runtime/x86-linux-os.c index c15665d..ddbe154 100644 --- a/src/runtime/x86-linux-os.c +++ b/src/runtime/x86-linux-os.c @@ -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 diff --git a/src/runtime/x86-linux-os.h b/src/runtime/x86-linux-os.h index 6e688c6..f2a39f9 100644 --- a/src/runtime/x86-linux-os.h +++ b/src/runtime/x86-linux-os.h @@ -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 */ diff --git a/version.lisp-expr b/version.lisp-expr index c1e27f0..72d53b0 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -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" -- 1.7.10.4