]> granicus.if.org Git - gc/commitdiff
Avoid multiple 'getcontext failed' warnings if getcontext is broken
authorIvan Maidanski <ivmai@mail.ru>
Thu, 26 Apr 2018 07:54:52 +0000 (10:54 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Thu, 26 Apr 2018 07:54:52 +0000 (10:54 +0300)
Issue #133 (bdwgc).

* mach_dep.c [!HAVE_PUSH_REGS && UNIX_LIKE && !NO_GETCONTEXT]
(GC_with_callee_saves_pushed): Define getcontext_works static variable;
do not call getcontext() if getcontext_works < 0; add comment; set
getcontext_works to 1 or -1 (depending whether getcontext is working)
if getcontext_works is zero.
* misc.c [THREADS && UNIX_LIKE && !NO_GETCONTEXT]
(callee_saves_pushed_dummy_fn): New static function (empty).
* misc.c [THREADS && UNIX_LIKE && !NO_GETCONTEXT] (GC_init): Call
GC_with_callee_saves_pushed(callee_saves_pushed_dummy_fn) if GC_dont_gc
or GC_dont_precollect (otherwise it is called by GC_gcollect_inner);
add comment.

mach_dep.c
misc.c

index b65e6dbe0ce2f0c6735784ebcb48617de18f57e9..958489710ffc3a2726e041d137d1d8d7a75732ee 100644 (file)
@@ -237,6 +237,7 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *),
       /* Older versions of Darwin seem to lack getcontext().    */
       /* ARM and MIPS Linux often doesn't support a real        */
       /* getcontext().                                          */
+      static signed char getcontext_works = 0; /* (-1) - broken, 1 - works */
       ucontext_t ctxt;
 #     ifdef GETCONTEXT_FPU_EXCMASK_BUG
         /* Workaround a bug (clearing the FPU exception mask) in        */
@@ -255,12 +256,17 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *),
 #       endif
 #     endif
 
-      if (getcontext(&ctxt) < 0) {
-        WARN("getcontext failed:"
-             " using another register retrieval method...\n", 0);
-        /* E.g., to workaround a bug in Docker ubuntu_32bit.    */
-      } else {
-        context = &ctxt;
+      if (getcontext_works >= 0) {
+        if (getcontext(&ctxt) < 0) {
+          WARN("getcontext failed:"
+               " using another register retrieval method...\n", 0);
+          /* getcontext() is broken, do not try again.          */
+          /* E.g., to workaround a bug in Docker ubuntu_32bit.  */
+        } else {
+          context = &ctxt;
+        }
+        if (EXPECT(0 == getcontext_works, FALSE))
+          getcontext_works = context != NULL 1 : -1;
       }
 #     ifdef GETCONTEXT_FPU_EXCMASK_BUG
 #       ifdef X86_64
diff --git a/misc.c b/misc.c
index 2c4b6cee7c2afd26aba53c0de90d535c972d523e..10d26dfda489309ce18e14d2ebda87f2d743dd61 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -829,6 +829,11 @@ GC_API int GC_CALL GC_is_init_called(void)
   }
 #endif /* MSWIN32 */
 
+#if defined(THREADS) && defined(UNIX_LIKE) && !defined(NO_GETCONTEXT)
+  static void callee_saves_pushed_dummy_fn(ptr_t data GC_ATTR_UNUSED,
+                                           void * context GC_ATTR_UNUSED) {}
+#endif
+
 STATIC word GC_parse_mem_size_arg(const char *str)
 {
   word result = 0; /* bad value */
@@ -1308,6 +1313,11 @@ GC_API void GC_CALL GC_init(void)
 #   if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED)
         UNLOCK();
 #   endif
+#   if defined(THREADS) && defined(UNIX_LIKE) && !defined(NO_GETCONTEXT)
+      /* Ensure getcontext_works is set to avoid potential data race.   */
+      if (GC_dont_gc || GC_dont_precollect)
+        GC_with_callee_saves_pushed(callee_saves_pushed_dummy_fn, NULL);
+#   endif
 #   ifdef STUBBORN_ALLOC
         GC_stubborn_init();
 #   endif