diff options
author | ivmai <ivmai> | 2011-01-24 21:43:30 +0000 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2011-07-26 21:06:56 +0400 |
commit | bb4edc16faef98e2be3966eb1f6c9cec45c4ffeb (patch) | |
tree | 49666259893a4bc311454edc2c9d3ed8729bd457 /mach_dep.c | |
parent | ce3582069e602d1e6d1d1b17a2336484150fdef5 (diff) | |
download | bdwgc-bb4edc16faef98e2be3966eb1f6c9cec45c4ffeb.tar.gz |
2011-01-22 Ivan Maidanski <ivmai@mail.ru> (mostly Jean-Claude Beaudoin)
* darwin_stop_world.c (GC_FindTopOfStack): Prefix and suffix
"volatile" keyword with double underscore.
* mach_dep.c (GETCONTEXT_FPU_EXCMASK_BUG): Recognize new macro and
include fenv.h if defined (unless NO_GETCONTEXT or HAVE_PUSH_REGS).
* mach_dep.c (GC_with_callee_saves_pushed): Restore FPU exception
mask corrupted by getcontext if GETCONTEXT_FPU_EXCMASK_BUG.
* include/private/gcconfig.h (GETCONTEXT_FPU_EXCMASK_BUG): Define
for Linux/amd64 (since its GLibc getcontext currently has the bug).
Diffstat (limited to 'mach_dep.c')
-rw-r--r-- | mach_dep.c | 40 |
1 files changed, 38 insertions, 2 deletions
@@ -185,8 +185,11 @@ asm static void PushMacRegisters() # include <signal.h> # ifndef NO_GETCONTEXT # include <ucontext.h> +# ifdef GETCONTEXT_FPU_EXCMASK_BUG +# include <fenv.h> +# endif # endif -#endif +#endif /* !HAVE_PUSH_REGS */ /* Ensure that either registers are pushed, or callee-save registers */ /* are somewhere on the stack, and then call fn(arg, ctxt). */ @@ -204,8 +207,41 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), /* ARM and MIPS Linux often doesn't support a real */ /* getcontext(). */ ucontext_t ctxt; +# ifdef GETCONTEXT_FPU_EXCMASK_BUG + /* Workaround a bug (clearing the FPU exception mask) in */ + /* getcontext on Linux/x86_64. */ +# ifdef X86_64 + /* We inline fegetexcept and feenableexcept here just not to */ + /* force the client application to use -lm linker option. */ + unsigned short except_mask; + __asm__ __volatile__ ("fstcw %0" : "=m" (*&except_mask)); + except_mask &= FE_ALL_EXCEPT; +# else + int except_mask = fegetexcept(); +# endif +# endif if (getcontext(&ctxt) < 0) - ABORT ("Getcontext failed: Use another register retrieval method?"); + ABORT ("getcontext failed: Use another register retrieval method?"); +# ifdef GETCONTEXT_FPU_EXCMASK_BUG +# ifdef X86_64 + { + unsigned short new_exc; + unsigned int new_exc_sse; + /* Get the current control word of the x87 FPU. */ + __asm__ __volatile__ ("fstcw %0" : "=m" (*&new_exc)); + new_exc &= except_mask; + __asm__ __volatile__ ("fldcw %0" : : "m" (*&new_exc)); + /* And now the same for the SSE MXCSR register. */ + __asm__ __volatile__ ("stmxcsr %0" : "=m" (*&new_exc_sse)); + /* The SSE exception masks are shifted by 7 bits. */ + new_exc_sse &= except_mask << 7; + __asm__ __volatile__ ("ldmxcsr %0" : : "m" (*&new_exc_sse)); + } +# else /* !X86_64 */ + if (feenableexcept(except_mask) < 0) + ABORT("feenableexcept failed"); +# endif +# endif context = &ctxt; # if defined(SPARC) || defined(IA64) /* On a register window machine, we need to save register */ |