From cb2be4b6d03412e2e547a8b051e43d5446792b7c Mon Sep 17 00:00:00 2001 From: Nikodemus Siivola Date: Wed, 13 May 2009 18:13:48 +0000 Subject: [PATCH] 1.0.28.46: implement os_restore_fp_control() for OpenBSD x86 Fixes problems with the floating point modes being forgotten. Also fixes one of the float tests by clearing the exception flags first, insuring that the right exception is raised. Patch by Josh Elsasser. --- NEWS | 2 ++ src/runtime/bsd-os.c | 19 +++++++++++++++++++ src/runtime/bsd-os.h | 3 +++ src/runtime/x86-bsd-os.c | 22 ++++++++++++++++++++++ src/runtime/x86-bsd-os.h | 5 +++++ tests/float.pure.lisp | 7 ++++--- version.lisp-expr | 2 +- 7 files changed, 56 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 8760976..f37703e 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,8 @@ * improvement: pretty-printing loop has been implemented properly. (thanks to Tobias Rittweiler) * documentation: CLOS slot typechecing policy has been documented. + * bug fix: better floating point exception handling on x86/OpenBSD. + (thanks to Josh Elsasser) * bug fix: exit status from QUIT when called under --script was lost (reported by Hubert Kauker) * bug fix: MAKE-ARRAY for non-zero :INITIAL-ELEMENT always used the diff --git a/src/runtime/bsd-os.c b/src/runtime/bsd-os.c index 8848492..df486eb 100644 --- a/src/runtime/bsd-os.c +++ b/src/runtime/bsd-os.c @@ -70,7 +70,11 @@ static void freebsd_init(); #include #include #include +#include #include +#ifdef LISP_FEATURE_X86 +#include +#endif static void openbsd_init(); #endif @@ -481,9 +485,16 @@ os_get_runtime_executable_path() #endif #ifdef __OpenBSD__ + +int openbsd_use_fxsave = 0; + void openbsd_init() { +#ifdef LISP_FEATURE_X86 + int mib[2]; + size_t size; +#endif /* * Show a warning if it looks like the memory available after * allocating the spaces won't be at least this much. @@ -495,6 +506,14 @@ openbsd_init() #endif struct rlimit rl; +#ifdef LISP_FEATURE_X86 + /* Save the machdep.osfxsr sysctl for use by os_restore_fp_control() */ + mib[0] = CTL_MACHDEP; + mib[1] = CPU_OSFXSR; + size = sizeof (openbsd_use_fxsave); + sysctl(mib, 2, &openbsd_use_fxsave, &size, NULL, 0); +#endif + /* OpenBSD, like NetBSD, counts mmap()ed space against the * process's data size limit. If the soft limit is lower than the * hard limit then try to yank it up, this lets users in the diff --git a/src/runtime/bsd-os.h b/src/runtime/bsd-os.h index 26e39e3..880c5f7 100644 --- a/src/runtime/bsd-os.h +++ b/src/runtime/bsd-os.h @@ -65,6 +65,9 @@ extern int sig_memory_fault; typedef struct sigcontext os_context_t; #define SIG_MEMORY_FAULT SIGSEGV +#if defined(LISP_FEATURE_X86) +extern int openbsd_use_fxsave; +#endif #elif defined __NetBSD__ diff --git a/src/runtime/x86-bsd-os.c b/src/runtime/x86-bsd-os.c index c44c7db..d071666 100644 --- a/src/runtime/x86-bsd-os.c +++ b/src/runtime/x86-bsd-os.c @@ -19,6 +19,12 @@ #include "machine/npx.h" #endif +#if defined(LISP_FEATURE_OPENBSD) +#include +#include +#include +#endif + /* KLUDGE: There is strong family resemblance in the signal context * stuff in FreeBSD and OpenBSD, but in detail they're different in * almost every line of code. It would be nice to find some way to @@ -237,3 +243,19 @@ os_restore_fp_control(os_context_t *context) #endif } #endif + +#if defined(LISP_FEATURE_OPENBSD) +void +os_restore_fp_control(os_context_t *context) +{ + struct sigframe *frame; + union savefpu *fpu; + + frame = (struct sigframe *)((char*)context - offsetof(struct sigframe, sf_sc)); + fpu = frame->sf_fpstate; + if (openbsd_use_fxsave) + __asm__ __volatile__ ("fldcw %0" : : "m" (fpu->sv_xmm.sv_env.en_cw)); + else + __asm__ __volatile__ ("fldcw %0" : : "m" (fpu->sv_87.sv_env.en_cw)); +} +#endif diff --git a/src/runtime/x86-bsd-os.h b/src/runtime/x86-bsd-os.h index dbd601f..dc9d9f7 100644 --- a/src/runtime/x86-bsd-os.h +++ b/src/runtime/x86-bsd-os.h @@ -35,4 +35,9 @@ void os_restore_tls_segment_register(os_context_t *context); void os_restore_fp_control(os_context_t *context); #endif +#if defined LISP_FEATURE_OPENBSD +#define RESTORE_FP_CONTROL_FROM_CONTEXT +void os_restore_fp_control(os_context_t *context); +#endif + #endif /* _X86_BSD_OS_H */ diff --git a/tests/float.pure.lisp b/tests/float.pure.lisp index e1aabae..bea74a8 100644 --- a/tests/float.pure.lisp +++ b/tests/float.pure.lisp @@ -93,7 +93,7 @@ (assert (= 0.0d0 (scale-float 1.0d0 (1- most-negative-fixnum)))) (with-test (:name (:scale-float-overflow :bug-372) - :fails-on '(or :ppc :darwin (and :x86 :openbsd))) ;; bug 372 + :fails-on '(or :ppc :darwin)) ;; bug 372 (progn (assert (raises-error? (scale-float 1.0 most-positive-fixnum) floating-point-overflow)) @@ -125,12 +125,13 @@ (funcall (compile nil '(lambda () (tan (tan (round 0)))))) (with-test (:name (:addition-overflow :bug-372) - :fails-on '(or :ppc :darwin (and (or :x86 :x86-64) - (or :netbsd :openbsd)))) + :fails-on '(or :ppc :darwin (and :x86 :netbsd))) (assert (typep (nth-value 1 (ignore-errors (sb-sys:without-interrupts + (sb-int:set-floating-point-modes :current-exceptions nil + :accrued-exceptions nil) (loop repeat 2 summing most-positive-double-float) (sleep 2)))) 'floating-point-overflow))) diff --git a/version.lisp-expr b/version.lisp-expr index 67f58a2..e7e08d5 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.28.45" +"1.0.28.46" -- 1.7.10.4