/* 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 */
# 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
}
#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 */
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