]> granicus.if.org Git - gc/commitdiff
2011-01-22 Ivan Maidanski <ivmai@mail.ru> (mostly Jean-Claude Beaudoin)
authorivmai <ivmai>
Mon, 24 Jan 2011 21:43:30 +0000 (21:43 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:56 +0000 (21:06 +0400)
* 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).

ChangeLog
darwin_stop_world.c
include/private/gcconfig.h
mach_dep.c

index da3b65ac07e3999d4f753aaa04d1a6d02d516366..2c8dc557fcddbb152636c921ad07c73fdbe75b8d 100644 (file)
--- 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
index 6af691847f59d873b004897856be7c74cedec582..db462295dc478150531686729e76cfaa854f5c61 100644 (file)
@@ -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 {
index cbfe735c27473ac2868d41dde24e532c479568b0..c75b7cee0145bf066d5acf7120c052d4a2fd323d 100644 (file)
 #       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
 #           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"
index 0829c8caebc4c34402aef677b36c418020b722a4..0753d504243620359f62f54ac4fb0eb3ffa66846 100644 (file)
@@ -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       */