From: Ivan Maidanski Date: Thu, 26 Apr 2018 07:54:52 +0000 (+0300) Subject: Avoid multiple 'getcontext failed' warnings if getcontext is broken X-Git-Tag: v7.6.8~95 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fec76d59af8e767071d6adedc4990f5ddc1c31c1;p=gc Avoid multiple 'getcontext failed' warnings if getcontext is broken (back-port of commits b594132, 2bfaff7 from 'master') 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. --- diff --git a/mach_dep.c b/mach_dep.c index 5f64d4dc..14b4c9db 100644 --- a/mach_dep.c +++ b/mach_dep.c @@ -235,6 +235,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 */ @@ -253,12 +254,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 0ae5d3af..840e3d89 100644 --- a/misc.c +++ b/misc.c @@ -826,6 +826,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 */ @@ -1292,6 +1297,11 @@ GC_API void GC_CALL GC_init(void) GC_gcollect_inner(); # 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