slackware-current/source/l/gc/noelision.patch
Patrick J Volkerding d31c50870d Slackware 14.2
Thu Jun 30 20:26:57 UTC 2016
Slackware 14.2 x86_64 stable is released!

The long development cycle (the Linux community has lately been living in
"interesting times", as they say) is finally behind us, and we're proud to
announce the release of Slackware 14.2.  The new release brings many updates
and modern tools, has switched from udev to eudev (no systemd), and adds
well over a hundred new packages to the system.  Thanks to the team, the
upstream developers, the dedicated Slackware community, and everyone else
who pitched in to help make this release a reality.

The ISOs are off to be replicated, a 6 CD-ROM 32-bit set and a dual-sided
32-bit/64-bit x86/x86_64 DVD.  Please consider supporting the Slackware
project by picking up a copy from store.slackware.com.  We're taking
pre-orders now, and offer a discount if you sign up for a subscription.

Have fun!  :-)
2018-05-31 23:31:18 +02:00

127 lines
4.5 KiB
Diff

diff --git c/include/private/gc_priv.h w/include/private/gc_priv.h
index 0ad92fc..b877fac 100644
--- c/include/private/gc_priv.h
+++ w/include/private/gc_priv.h
@@ -2368,6 +2368,7 @@ GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str,
/* GC_notify_all_builder() is called when GC_fl_builder_count */
/* reaches 0. */
+ GC_INNER void GC_setup_mark_lock(void);
GC_INNER void GC_acquire_mark_lock(void);
GC_INNER void GC_release_mark_lock(void);
GC_INNER void GC_notify_all_builder(void);
diff --git c/include/private/gcconfig.h w/include/private/gcconfig.h
index c753cc2..b5ed075 100644
--- c/include/private/gcconfig.h
+++ w/include/private/gcconfig.h
@@ -1357,6 +1357,11 @@
# define PREFETCH_FOR_WRITE(x) \
__asm__ __volatile__ ("prefetchw %0" : : "m"(*(char *)(x)))
# endif
+# if defined(__GLIBC__)
+ /* Workaround lock elision implementation for some glibc. */
+# define GLIBC_2_19_TSX_BUG
+# include <gnu/libc-version.h> /* for gnu_get_libc_version() */
+# endif
# endif
# ifdef CYGWIN32
# define OS_TYPE "CYGWIN32"
@@ -2257,6 +2262,11 @@
/* FIXME: This seems to be fixed in GLibc v2.14. */
# define GETCONTEXT_FPU_EXCMASK_BUG
# endif
+# if defined(__GLIBC__)
+ /* Workaround lock elision implementation for some glibc. */
+# define GLIBC_2_19_TSX_BUG
+# include <gnu/libc-version.h> /* for gnu_get_libc_version() */
+# endif
# endif
# ifdef DARWIN
# define OS_TYPE "DARWIN"
diff --git c/include/private/pthread_support.h w/include/private/pthread_support.h
index 525a9aa..017f194 100644
--- c/include/private/pthread_support.h
+++ w/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 c/misc.c w/misc.c
index df434a1..3aca41d 100644
--- c/misc.c
+++ w/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 c/pthread_support.c w/pthread_support.c
index c00b93d..8a7c50b 100644
--- c/pthread_support.c
+++ w/pthread_support.c
@@ -1979,6 +1979,55 @@ GC_INNER void GC_lock(void)
static pthread_cond_t builder_cv = PTHREAD_COND_INITIALIZER;
+#ifdef GLIBC_2_19_TSX_BUG
+ /* Parse string like <major>[.<minor>[<tail>]] and return major value. */
+ static int parse_version(int *pminor, const char *pverstr) {
+ char *endp;
+ unsigned long value = strtoul(pverstr, &endp, 10);
+ int major = (int)value;
+
+ if (major < 0 || (char *)pverstr == endp || (unsigned)major != value) {
+ /* Parse error */
+ return -1;
+ }
+ if (*endp != '.') {
+ /* No minor part. */
+ *pminor = -1;
+ } else {
+ value = strtoul(endp + 1, &endp, 10);
+ *pminor = (int)value;
+ if (*pminor < 0 || (unsigned)(*pminor) != value) {
+ return -1;
+ }
+ }
+ return major;
+ }
+#endif /* GLIBC_2_19_TSX_BUG */
+
+GC_INNER void GC_setup_mark_lock(void)
+{
+# ifdef GLIBC_2_19_TSX_BUG
+ pthread_mutexattr_t mattr;
+ int glibc_minor = -1;
+ int glibc_major = parse_version(&glibc_minor, gnu_get_libc_version());
+
+ if (glibc_major > 2 || (glibc_major == 2 && glibc_minor >= 19)) {
+ /* TODO: disable this workaround for glibc with fixed TSX */
+ /* This disables lock elision to workaround a bug in glibc 2.19+ */
+ if (0 != pthread_mutexattr_init(&mattr)) {
+ ABORT("pthread_mutexattr_init failed");
+ }
+ if (0 != pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_NORMAL)) {
+ ABORT("pthread_mutexattr_settype failed");
+ }
+ if (0 != pthread_mutex_init(&mark_mutex, &mattr)) {
+ ABORT("pthread_mutex_init failed");
+ }
+ pthread_mutexattr_destroy(&mattr);
+ }
+# endif
+}
+
GC_INNER void GC_acquire_mark_lock(void)
{
GC_ASSERT(GC_mark_lock_holder != NUMERIC_THREAD_ID(pthread_self()));