*) 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.
/* 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
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
/* 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)
{
# ifdef NUMERIC_THREAD_ID_UNIQUE