From a62e6fc5808e8f4739adb842ec55958acfbdb338 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 11 Aug 2016 11:56:44 +0300 Subject: Workaround missing getcontext() in Docker osrf/ubuntu_32bit * mach_dep.c [NO_GETCONTEXT] (GC_with_callee_saves_pushed): Call WARN instead of ABORT if getcontext() failed; do not set context variable if getcontext() failed; fallback to other register retrieval methods (__builtin_unwind_init or setjmp) if context variable is NULL. * mach_dep.c (GC_with_callee_saves_pushed): Reformat code. --- mach_dep.c | 69 ++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 29 deletions(-) (limited to 'mach_dep.c') diff --git a/mach_dep.c b/mach_dep.c index 0515a531..fbf6c43d 100644 --- a/mach_dep.c +++ b/mach_dep.c @@ -220,15 +220,16 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), volatile ptr_t arg) { - volatile int dummy; - void * context = 0; - -# if defined(HAVE_PUSH_REGS) - GC_push_regs(); -# elif defined(UNIX_LIKE) && !defined(NO_GETCONTEXT) - /* Older versions of Darwin seem to lack getcontext(). */ - /* ARM and MIPS Linux often doesn't support a real */ - /* getcontext(). */ + volatile int dummy; + void * context = 0; + +# if defined(HAVE_PUSH_REGS) + GC_push_regs(); +# else +# if defined(UNIX_LIKE) && !defined(NO_GETCONTEXT) + /* Older versions of Darwin seem to lack getcontext(). */ + /* 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 */ @@ -237,13 +238,20 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), /* We manipulate FPU control word here just not to force the */ /* client application to use -lm linker option. */ unsigned short old_fcw; + __asm__ __volatile__ ("fstcw %0" : "=m" (*&old_fcw)); # else int except_mask = fegetexcept(); # endif # endif - if (getcontext(&ctxt) < 0) - ABORT ("getcontext failed: Use another register retrieval method?"); + + 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; + } # ifdef GETCONTEXT_FPU_EXCMASK_BUG # ifdef X86_64 __asm__ __volatile__ ("fldcw %0" : : "m" (*&old_fcw)); @@ -259,21 +267,22 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), if (feenableexcept(except_mask) < 0) ABORT("feenableexcept failed"); # endif -# endif - context = &ctxt; +# endif /* GETCONTEXT_FPU_EXCMASK_BUG */ # if defined(SPARC) || defined(IA64) /* On a register window machine, we need to save register */ /* contents on the stack for this to work. This may already be */ /* subsumed by the getcontext() call. */ GC_save_regs_ret_val = GC_save_regs_in_stack(); -# endif /* register windows. */ -# elif defined(HAVE_BUILTIN_UNWIND_INIT) - /* This was suggested by Richard Henderson as the way to */ - /* force callee-save registers and register windows onto */ - /* the stack. */ - __builtin_unwind_init(); -# else /* !HAVE_BUILTIN_UNWIND_INIT && !UNIX_LIKE */ - /* && !HAVE_PUSH_REGS */ +# endif + if (NULL == context) /* getcontext failed */ +# endif /* !NO_GETCONTEXT */ + { +# if defined(HAVE_BUILTIN_UNWIND_INIT) + /* This was suggested by Richard Henderson as the way to */ + /* force callee-save registers and register windows onto */ + /* the stack. */ + __builtin_unwind_init(); +# else /* Generic code */ /* The idea is due to Parag Patel at HP. */ /* We're not sure whether he would like */ @@ -297,14 +306,16 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), /* SUSV3, setjmp() may or may not save signal mask. */ /* _setjmp won't, but is less portable. */ # endif -# endif /* !HAVE_PUSH_REGS ... */ - /* FIXME: context here is sometimes just zero. At the moment the */ - /* callees don't really need it. */ - fn(arg, context); - /* Strongly discourage the compiler from treating the above */ - /* as a tail-call, since that would pop the register */ - /* contents before we get a chance to look at them. */ - GC_noop1((word)(&dummy)); +# endif /* !HAVE_BUILTIN_UNWIND_INIT */ + } +# endif /* !HAVE_PUSH_REGS */ + /* FIXME: context here is sometimes just zero. At the moment the */ + /* callees don't really need it. */ + fn(arg, context); + /* Strongly discourage the compiler from treating the above */ + /* as a tail-call, since that would pop the register */ + /* contents before we get a chance to look at them. */ + GC_noop1((word)(&dummy)); } #if defined(ASM_CLEAR_CODE) -- cgit v1.2.1