Re: [Gc] glibc 2.19 lock elision bug
Ivan Maidanski <ivmai-JGs/[email protected]> Sat, 19 Jul 2014 16:48:39 +0400
| Newsgroups | gmane.comp.programming.garbage-collection.boehmgc |
|---|---|
| Message-ID | <[email protected]> |
Hi Paul, Thank you for the patch. I reviewed it and applied several changes - see https://github.com/ivmai/bdwgc/commit/757af8aa17ed107ff2915f93967087835c0100dc : * fix version check: major >= 2 && minor >= 19 -> major > 2 || major == 2 && minor >= 19 * fix scope of workaround application - only Linux/x64 with Glibc (instead of Linux on all CPUs) * avoid potential recursion (in case strdup/free redirected to GC_strdup/free) * avoid extra configure checks (currently all major targets could be compiled even without running configure&make) * code refactoring: ** move version parsing to a separate function ** use mutex static initializer if workaround is not needed ** call ABORT on pthread function call error Please test new code. But still I don't know whether the proposed solution is good enough to be in master. The questions are: * is there a link pointing to a lock elision bug implementation in Glibc? If not, it is better to register such * this workaround simply disables lock elision (causing potentially degradation of performance). which pthread primitive causes malfunction? if trylock then we could avoid it. Regards, Ivan Fri, 27 Jun 2014 12:13:31 +1000 from Paul Bone <[email protected]>: >On Wed, Jun 25, 2014 at 11:34:57AM +1000, Paul Bone wrote: >> Hi. >> >> I wrote earlier about a bug I was trying to find regarding lock elision in >> glibc 2.19 that affects Boehm GC. I beleive that this affects all >> applications that use Boehm GC, not just Mercury, as mono applications have >> also been crashing since I upgraded glibc. I would like some feedback and >> help with the following change: >> >> The git branch containing this change can be found here: >> https://github.com/PaulBone/bdwgc/tree/fix_tsx_bug >> > >The patch I sent had a bug. This one fixes it and also enables the >workaround for versions greater than 2.19 > > >From 3c22928504e6a0d306d39a60686e963bcd04ede4 Mon Sep 17 00:00:00 2001 >From: Paul Bone < [email protected] > >Date: Wed, 25 Jun 2014 11:17:50 +1000 >Subject: [PATCH] Workaround Linux NTPL lock elision bug. > >glibc 2.19 on Linux x86-64 platforms includes support for lock elision, >by using Intel's TSX support when it is available. Without modifying an >application this converts suitable critical sections that use mutex into >transactional memory critical sections. See http://lwn.net/Articles/534758/ >If a problem occurs that means that transactional memory can't be used, such >as a system call or buffer overflow, the pthreads implementation will catch >this error and retry the critical section using a normal mutex. > >I noticed that since upgrading glibc that programs using Boehm GC crash, one >of these crashes was an assertion that the owner field of a mutex was >invalid. The assertion was generated by the pthreads implementation. >I believe that there is a bug in glibc that when a mutex cannot be used >safely for transactions that some series of events causes it's owner field >to be set incorrectly (or cleared when it shouldn't be). > >I've found that I can work around this problem by having Boehm GC use an >error checking mutex, which I believe doesn't use lock elision and in my >testing doesn't crash. > >XXX: This work-around mostly works except for linking the feature detection >in configure.ac to the conditional compilation in pthread_support.c as there >isn't an obvious way to make it work for automake and Makefile.direct. >Could I have some help updating the build system please? > >include/private/pthread_support.h: >pthread_support.c: > Define GC_setup_mark_lock() This procedure creates the lock specifying a > pthread_mutexattr_t structure. This is used to disable lock elision on > Linux with glibc 2.19 or greater. > >configure.ac: > If we're using Linux then check for the gnu extensions required to > identify the version of glibc at runtime. > >misc.c: > Call GC_setup_mark_lock() when initialising the collector. >--- > configure.ac | 13 ++++++++++ > include/private/pthread_support.h | 2 ++ > misc.c | 3 +++ > pthread_support.c | 53 +++++++++++++++++++++++++++++++++++++++ > 4 files changed, 71 insertions(+) > >diff --git a/configure.ac b/configure.ac >index 7667949..6853e97 100644 >--- a/configure.ac >+++ b/configure.ac >@@ -646,6 +646,19 @@ case "$host" in > *) AC_MSG_RESULT(no) ;; > esac > >+dnl Check for specific glibc functions and definitions that we need to for >+dnl the glibc 2.19 workaround. >+HAVE_LIBC_VERSION_H=no >+HAVE_GNU_GET_LIBC_VERSION=no >+case "${host}" in >+ *-linux*) >+ AC_CHECK_HEADER([gnu/libc-version.h], HAVE_LIBC_VERSION_H=yes) >+ AC_CHECK_FUNC([gnu_get_libc_version], HAVE_GNU_GET_LIBC_VERSION=yes) >+ ;; >+esac >+AC_SUBST(HAVE_LIBC_VERSION_H) >+AC_SUBST(HAVE_GNU_GET_LIBC_VERSION) >+ > dnl Include defines that have become de facto standard. > dnl ALL_INTERIOR_POINTERS and NO_EXECUTE_PERMISSION can be overridden > dnl in the startup code. >diff --git a/include/private/pthread_support.h b/include/private/pthread_support.h >index 525a9aa..017f194 100644 >--- a/include/private/pthread_support.h >+++ b/include/private/pthread_support.h >@@ -148,6 +148,8 @@ GC_INNER_PTHRSTART GC_thread GC_start_rtn_prepare_thread( > struct GC_stack_base *sb, void *arg); > GC_INNER_PTHRSTART void GC_thread_exit_proc(void *); > >+GC_INNER void GC_setup_mark_lock(void); >+ > #endif /* GC_PTHREADS && !GC_WIN32_THREADS */ > > #endif /* GC_PTHREAD_SUPPORT_H */ >diff --git a/misc.c b/misc.c >index df434a1..dccf5f3 100644 >--- a/misc.c >+++ b/misc.c >@@ -875,6 +875,9 @@ GC_API void GC_CALL GC_init(void) > /* else */ InitializeCriticalSection (&GC_allocate_ml); > } > # endif /* GC_WIN32_THREADS */ >+# if (defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS)) >+ GC_setup_mark_lock(); >+# endif /* GC_PTHREADS */ > # if (defined(MSWIN32) || defined(MSWINCE)) && defined(THREADS) > InitializeCriticalSection(&GC_write_cs); > # endif >diff --git a/pthread_support.c b/pthread_support.c >index c00b93d..56fc94b 100644 >--- a/pthread_support.c >+++ b/pthread_support.c >@@ -95,6 +95,10 @@ > typedef unsigned int sem_t; > #endif /* GC_DGUX386_THREADS */ > >+#ifdef HAVE_LIBC_VERSION_H >+# include <gnu/libc-version.h> >+#endif >+ > /* Undefine macros used to redirect pthread primitives. */ > # undef pthread_create > # ifndef GC_NO_PTHREAD_SIGMASK >@@ -1973,12 +1977,61 @@ GC_INNER void GC_lock(void) > /* defined. */ > static pthread_mutex_t mark_mutex = > {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, {0, 0}}; >+#elif defined(HAVE_GNU_GET_LIBC_VERSION) && defined(HAVE_LIBC_VERSION_H) >+ static pthread_mutex_t mark_mutex; > #else > static pthread_mutex_t mark_mutex = PTHREAD_MUTEX_INITIALIZER; > #endif > > static pthread_cond_t builder_cv = PTHREAD_COND_INITIALIZER; > >+GC_INNER void GC_setup_mark_lock(void) >+{ >+#if defined(HAVE_GNU_GET_LIBC_VERSION) && defined(HAVE_LIBC_VERSION_H) >+ pthread_mutexattr_t attr; >+ char *version_str = NULL; >+ char *strtok_save; >+ char *version_part; >+ char *version_str; >+ >+ if (0 != pthread_mutexattr_init(&attr)) { >+ goto error; >+ } >+ >+ /* >+ ** Check for version 2.19 or greater. >+ */ >+ version_str = strdup(gnu_get_libc_version()); >+ version_part = strtok_r(version_str, ".", &strtok_save); >+ if ((NULL != version_part) && (2 <= atoi(version_part))) { >+ version_part = strtok_r(NULL, ".", &strtok_save); >+ if ((NULL != version_part) && (19 <= atoi(version_part))) { >+ /* >+ * Disable lock elision on this version of glibc. >+ */ >+ if (0 != pthread_mutexattr_settype(&attr, >+ PTHREAD_MUTEX_ERRORCHECK)) >+ { >+ goto error; >+ } >+ } >+ } >+ >+ if (0 != pthread_mutex_init(&mark_mutex, &attr)) { >+ goto error; >+ } >+ pthread_mutexattr_destroy(&attr); >+ if (NULL != version_str) { >+ free(version_str); >+ } >+ return; >+ >+error: >+ perror("Error setting up marker mutex"); >+ exit(1); >+#endif /* HAVE_GNU_GET_LIBC_VERSION && HAVE_LIBC_VERSION_H */ >+} >+ > GC_INNER void GC_acquire_mark_lock(void) > { > GC_ASSERT(GC_mark_lock_holder != NUMERIC_THREAD_ID(pthread_self())); >-- >2.0.0 > > >-- >Paul Bone >_______________________________________________ >bdwgc mailing list >[email protected] >https://lists.opendylan.org/mailman/listinfo/bdwgc _______________________________________________ bdwgc mailing list [email protected] https://lists.opendylan.org/mailman/listinfo/bdwgc