summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorivmai <ivmai>2011-01-24 21:43:30 +0000
committerIvan Maidanski <ivmai@mail.ru>2011-07-26 21:06:56 +0400
commitbb4edc16faef98e2be3966eb1f6c9cec45c4ffeb (patch)
tree49666259893a4bc311454edc2c9d3ed8729bd457
parentce3582069e602d1e6d1d1b17a2336484150fdef5 (diff)
downloadbdwgc-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).
-rw-r--r--ChangeLog11
-rw-r--r--darwin_stop_world.c4
-rw-r--r--include/private/gcconfig.h8
-rw-r--r--mach_dep.c40
4 files changed, 58 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index da3b65ac..2c8dc557 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+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).
+
2011-01-17 Ivan Maidanski <ivmai@mail.ru>
* allchblk.c (GC_use_entire_heap): Change type to int (as declared
diff --git a/darwin_stop_world.c b/darwin_stop_world.c
index 6af69184..db462295 100644
--- a/darwin_stop_world.c
+++ b/darwin_stop_world.c
@@ -56,9 +56,9 @@ GC_INNER ptr_t GC_FindTopOfStack(unsigned long stack_start)
if (stack_start == 0) {
# ifdef POWERPC
# if CPP_WORDSZ == 32
- __asm__ volatile("lwz %0,0(r1)" : "=r" (frame));
+ __asm__ __volatile__ ("lwz %0,0(r1)" : "=r" (frame));
# else
- __asm__ volatile("ld %0,0(r1)" : "=r" (frame));
+ __asm__ __volatile__ ("ld %0,0(r1)" : "=r" (frame));
# endif
# endif
} else {
diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h
index cbfe735c..c75b7cee 100644
--- a/include/private/gcconfig.h
+++ b/include/private/gcconfig.h
@@ -707,7 +707,7 @@
# ifdef __ELF__
# define DYNAMIC_LOADING
# include <features.h>
-# if defined(__GLIBC__)&& __GLIBC__>=2
+# if defined(__GLIBC__) && __GLIBC__ >= 2
# define SEARCH_FOR_DATA_START
# else /* !GLIBC2 */
# ifdef PLATFORM_ANDROID
@@ -2063,6 +2063,12 @@
# define PREFETCH(x) __builtin_prefetch((x), 0, 0)
# define PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1)
# endif
+# if defined(__GLIBC__)
+ /* At present, there's a bug in GLibc getcontext() on */
+ /* Linux/x64 (it clears FPU exception mask). We define this */
+ /* macro to workaround it. */
+# define GETCONTEXT_FPU_EXCMASK_BUG
+# endif
# endif
# ifdef DARWIN
# define OS_TYPE "DARWIN"
diff --git a/mach_dep.c b/mach_dep.c
index 0829c8ca..0753d504 100644
--- a/mach_dep.c
+++ b/mach_dep.c
@@ -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 */