@@ -147,9 +147,6 @@
/* Define if __stack_chk_guard canary should be randomized at program startup. */
#undef ENABLE_STACKGUARD_RANDOMIZE
-/* Define if lock elision should be enabled by default. */
-#undef ENABLE_LOCK_ELISION
-
/* Package description. */
#undef PKGVERSION
@@ -677,7 +677,6 @@ enable_werror
all_warnings
force_install
bindnow
-enable_lock_elision
hardcoded_path_in_tests
enable_timezone_tools
use_default_link
@@ -766,7 +765,6 @@ enable_profile
enable_timezone_tools
enable_hardcoded_path_in_tests
enable_stackguard_randomization
-enable_lock_elision
enable_add_ons
enable_hidden_plt
enable_bind_now
@@ -1427,8 +1425,6 @@ Optional Features:
--enable-stackguard-randomization
initialize __stack_chk_guard canary with a random
number at program start
- --enable-lock-elision=yes/no
- Enable lock elision for pthread mutexes by default
--enable-add-ons[=DIRS...]
configure and build add-ons in DIR1,DIR2,... search
for add-ons if no parameter given
@@ -3395,19 +3391,6 @@ if test "$enable_stackguard_randomize" = yes; then
fi
-# Check whether --enable-lock-elision was given.
-if test "${enable_lock_elision+set}" = set; then :
- enableval=$enable_lock_elision; enable_lock_elision=$enableval
-else
- enable_lock_elision=no
-fi
-
-
-if test "$enable_lock_elision" = yes ; then
- $as_echo "#define ENABLE_LOCK_ELISION 1" >>confdefs.h
-
-fi
-
# Check whether --enable-add-ons was given.
if test "${enable_add_ons+set}" = set; then :
enableval=$enable_add_ons;
@@ -199,16 +199,6 @@ if test "$enable_stackguard_randomize" = yes; then
AC_DEFINE(ENABLE_STACKGUARD_RANDOMIZE)
fi
-AC_ARG_ENABLE([lock-elision],
- AC_HELP_STRING([--enable-lock-elision[=yes/no]],
- [Enable lock elision for pthread mutexes by default]),
- [enable_lock_elision=$enableval],
- [enable_lock_elision=no])
-AC_SUBST(enable_lock_elision)
-if test "$enable_lock_elision" = yes ; then
- AC_DEFINE(ENABLE_LOCK_ELISION)
-fi
-
dnl Generic infrastructure for drop-in additions to libc.
AC_ARG_ENABLE([add-ons],
AC_HELP_STRING([--enable-add-ons@<:@=DIRS...@:>@],
@@ -18,8 +18,8 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#ifndef _TUNABLES_H_
-#define _TUNABLES_H_
+#ifndef _DL_TUNABLES_H_
+#define _DL_TUNABLES_H_
#if !HAVE_TUNABLES
static inline void
@@ -77,4 +77,12 @@ glibc {
security_level: SXID_IGNORE
}
}
+ elision {
+ enable {
+ type: INT_32
+ minval: 0
+ maxval: 1
+ security_level: SXID_IGNORE
+ }
+ }
}
@@ -704,6 +704,10 @@ $(objpfx)tst-oddstacklimit.out: $(objpfx)tst-oddstacklimit $(objpfx)tst-basic1
$(evaluate-test)
endif
+# Disable elision for tst-mutex8 so it can verify error case for
+# destroying a mutex.
+tst-mutex8-ENV = GLIBC_TUNABLES=glibc.elision.enable=0
+
# The tests here better do not run in parallel
ifneq ($(filter %tests,$(MAKECMDGOALS)),)
.NOTPARALLEL:
@@ -127,9 +127,8 @@ check_type (const char *mas, pthread_mutexattr_t *ma)
return 1;
}
- /* Elided mutexes don't fail destroy. If elision is not explicitly disabled
- we don't know, so can also not check this. */
-#ifndef ENABLE_LOCK_ELISION
+ /* Elided mutexes don't fail destroy, but this test is run with
+ elision disabled so we can test them. */
e = pthread_mutex_destroy (m);
if (e == 0)
{
@@ -142,7 +141,6 @@ check_type (const char *mas, pthread_mutexattr_t *ma)
mas);
return 1;
}
-#endif
if (pthread_mutex_unlock (m) != 0)
{
@@ -157,7 +155,6 @@ check_type (const char *mas, pthread_mutexattr_t *ma)
}
/* Elided mutexes don't fail destroy. */
-#ifndef ENABLE_LOCK_ELISION
e = pthread_mutex_destroy (m);
if (e == 0)
{
@@ -171,7 +168,6 @@ mutex_destroy of self-trylocked mutex did not return EBUSY %s\n",
mas);
return 1;
}
-#endif
if (pthread_mutex_unlock (m) != 0)
{
@@ -207,7 +203,6 @@ mutex_destroy of self-trylocked mutex did not return EBUSY %s\n",
}
/* Elided mutexes don't fail destroy. */
-#ifndef ENABLE_LOCK_ELISION
e = pthread_mutex_destroy (m);
if (e == 0)
{
@@ -220,7 +215,6 @@ mutex_destroy of self-trylocked mutex did not return EBUSY %s\n",
mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", mas);
return 1;
}
-#endif
done = true;
if (pthread_cond_signal (&c) != 0)
@@ -280,7 +274,6 @@ mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", mas);
}
/* Elided mutexes don't fail destroy. */
-#ifndef ENABLE_LOCK_ELISION
e = pthread_mutex_destroy (m);
if (e == 0)
{
@@ -295,7 +288,6 @@ mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", mas);
mas);
return 1;
}
-#endif
if (pthread_cancel (th) != 0)
{
@@ -122,9 +122,9 @@ END {
}
print "/* AUTOGENERATED by gen-tunables.awk. */"
- print "#ifndef _TUNABLES_H_"
+ print "#ifndef _DL_TUNABLES_H_"
print "# error \"Do not include this file directly.\""
- print "# error \"Include tunables.h instead.\""
+ print "# error \"Include dl-tunables.h instead.\""
print "#endif"
# Now, the enum names
@@ -19,7 +19,6 @@
#ifndef ELIDE_PPC_H
# define ELIDE_PPC_H
-#ifdef ENABLE_LOCK_ELISION
# include <htm.h>
# include <elision-conf.h>
@@ -114,12 +113,4 @@ __elide_unlock (int is_lock_free)
# define ELIDE_UNLOCK(is_lock_free) \
__elide_unlock (is_lock_free)
-# else
-
-# define ELIDE_LOCK(adapt_count, is_lock_free) 0
-# define ELIDE_TRYLOCK(adapt_count, is_lock_free, write) 0
-# define ELIDE_UNLOCK(is_lock_free) 0
-
-#endif /* ENABLE_LOCK_ELISION */
-
#endif
@@ -88,7 +88,7 @@ GOT_LABEL: ; \
cfi_endproc; \
ASM_SIZE_DIRECTIVE(name)
-#if ! IS_IN(rtld) && defined (ENABLE_LOCK_ELISION)
+#if ! IS_IN(rtld)
# define ABORT_TRANSACTION \
cmpwi 2,0; \
beq 1f; \
@@ -272,7 +272,7 @@ LT_LABELSUFFIX(name,_name_end): ; \
TRACEBACK_MASK(name,mask) \
END_2(name)
-#if !IS_IN(rtld) && defined (ENABLE_LOCK_ELISION)
+#if !IS_IN(rtld)
# define ABORT_TRANSACTION \
cmpdi 13,0; \
beq 1f; \
@@ -21,10 +21,8 @@
*/
#define _SYSDEPS_SYSDEP_H 1
#include <bits/hwcap.h>
-#ifdef ENABLE_LOCK_ELISION
#include <tls.h>
#include <htm.h>
-#endif
#define PPC_FEATURE_970 (PPC_FEATURE_POWER4 + PPC_FEATURE_HAS_ALTIVEC)
@@ -176,7 +174,7 @@
we abort transaction just before syscalls.
[1] Documentation/powerpc/transactional_memory.txt [Syscalls] */
-#if !IS_IN(rtld) && defined (ENABLE_LOCK_ELISION)
+#if !IS_IN(rtld)
# define ABORT_TRANSACTION \
({ \
if (THREAD_GET_TM_CAPABLE ()) \
@@ -89,37 +89,25 @@ typedef union
binary compatibility with static initializers. */
int __kind;
#if __WORDSIZE == 64
-# ifdef ENABLE_LOCK_ELISION
short __spins;
short __elision;
/* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER. */
-# define __PTHREAD_SPINS 0, 0
-# else
- int __spins;
- /* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER. */
-# define __PTHREAD_SPINS 0
-# endif
+# define __PTHREAD_SPINS 0, 0
__pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV 1
#else
unsigned int __nusers;
__extension__ union
{
-# ifdef ENABLE_LOCK_ELISION
struct
{
short __espins;
short __elision;
} _d;
-# define __spins _d.__espins
-# define __elision _d.__elision
- /* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER. */
-# define __PTHREAD_SPINS { 0, 0 }
-# else
- int __spins;
- /* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER. */
-# define __PTHREAD_SPINS 0
-# endif
+# define __spins _d.__espins
+# define __elision _d.__elision
+ /* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER. */
+# define __PTHREAD_SPINS { 0, 0 }
__pthread_slist_t __list;
};
#endif
@@ -21,6 +21,7 @@
#include <elision-conf.h>
#include <unistd.h>
#include <dl-procinfo.h>
+#include <elf/dl-tunables.h>
/* Reasonable initial tuning values, may be revised in the future.
This is a conservative initial value. */
@@ -54,18 +55,47 @@ int __pthread_force_elision attribute_hidden;
/* Initialize elision. */
+static inline void
+do_set_elision_enable (bool elision_enable)
+{
+ /* If elision is not enabled, or we are in a secure mode,
+ make sure elision is never used... */
+ if (!elision_enable || __libc_enable_secure)
+ {
+ __pthread_force_elision = 0;
+ return;
+ }
+
+ /* ... otherwise enable elision based on hardare availability. */
+ __pthread_force_elision = (GLRO (dl_hwcap2)
+ & PPC_FEATURE2_HAS_HTM) ? 1 : 0;
+}
+
+#if HAVE_TUNABLES
+/* The elision->enable tunable is either 0 or 1 to indicate that
+ elision should be disabled or enabled respectively. Availability at
+ the hardware level will still dictate if the feature is used. */
+void
+DL_TUNABLE_CALLBACK (set_elision_enable) (tunable_val_t *elision_enable)
+{
+ int32_t elision_enable = (int32_t) valp->numval;
+ do_set_elision_enable (elision_enable ? true : false);
+}
+#endif
+
static void
elision_init (int argc __attribute__ ((unused)),
char **argv __attribute__ ((unused)),
char **environ)
{
-#ifdef ENABLE_LOCK_ELISION
- int elision_available = (GLRO (dl_hwcap2) & PPC_FEATURE2_HAS_HTM) ? 1 : 0;
- __pthread_force_elision = __libc_enable_secure ? 0 : elision_available;
+#if HAVE_TUNABLES
+ /* Elision depends on tunables to enable and tune elision at runtime. */
+# define TUNABLE_NAMESPACE elision
+ TUNABLE_SET_VAL_WITH_CALLBACK (enable, NULL, set_elision_enable);
+#else
+ /* Disable elision when built without tunables. */
+ do_set_elision_enable (false);
#endif
- if (!__pthread_force_elision)
- /* Disable elision on rwlocks. */
- __elision_aconf.try_tbegin = 0;
}
#ifdef SHARED
@@ -16,7 +16,6 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#ifdef ENABLE_LOCK_ELISION
/* Automatically enable elision for existing user lock kinds. */
#define FORCE_ELISION(m, s) \
if (__pthread_force_elision \
@@ -25,4 +24,3 @@
mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \
s; \
}
-#endif
@@ -21,6 +21,7 @@
#include <elision-conf.h>
#include <unistd.h>
#include <dl-procinfo.h>
+#include <elf/dl-tunables.h>
/* Reasonable initial tuning values, may be revised in the future.
This is a conservative initial value. */
@@ -55,16 +56,46 @@ int __pthread_force_elision attribute_hidden = 0;
/* Initialize elison. */
+static inline void
+do_set_elision_enable (bool elision_enable)
+{
+ /* If elision is not enabled, or we are in a secure mode,
+ make sure elision is never used... */
+ if (!elision_enable || __libc_enable_secure)
+ {
+ __pthread_force_elision = 0;
+ return;
+ }
+
+ /* ... otherwise enable elision based on hardare availability. */
+ __pthread_force_elision = (GLRO (dl_hwcap) & HWCAP_S390_TE) ? 1 : 0;
+}
+
+#if HAVE_TUNABLES
+/* The elision->enable tunable is either 0 or 1 to indicate that
+ elision should be disabled or enabled respectively. Availability at
+ the hardware level will still dictate if the feature is used. */
+void
+DL_TUNABLE_CALLBACK (set_elision_enable) (tunable_val_t *elision_enable)
+{
+ int32_t elision_enable = (int32_t) valp->numval;
+ do_set_elision_enable (elision_enable ? true : false);
+}
+#endif
+
static void
elision_init (int argc __attribute__ ((unused)),
char **argv __attribute__ ((unused)),
char **environ)
{
- /* Set when the CPU and the kernel supports transactional execution.
- When false elision is never attempted. */
- int elision_available = (GLRO (dl_hwcap) & HWCAP_S390_TE) ? 1 : 0;
-
- __pthread_force_elision = __libc_enable_secure ? 0 : elision_available;
+#if HAVE_TUNABLES
+ /* Elision depends on tunables to enable and tune elision at runtime. */
+# define TUNABLE_NAMESPACE elision
+ TUNABLE_SET_VAL_WITH_CALLBACK (enable, NULL, set_elision_enable);
+#else
+ /* Disable elision when built without tunables. */
+ do_set_elision_enable (false);
+#endif
}
#ifdef SHARED
@@ -15,7 +15,6 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#ifdef ENABLE_LOCK_ELISION
#ifndef _ELISION_CONF_H
#define _ELISION_CONF_H 1
@@ -41,4 +40,3 @@ extern int __pthread_force_elision attribute_hidden;
#define HAVE_ELISION 1
#endif
-#endif
@@ -16,7 +16,6 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#ifdef ENABLE_LOCK_ELISION
/* Automatically enable elision for existing user lock kinds. */
#define FORCE_ELISION(m, s) \
if (__pthread_force_elision \
@@ -25,4 +24,3 @@
mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \
s; \
}
-#endif
@@ -22,7 +22,6 @@
#include <sysdeps/nptl/lowlevellock.h>
/* Transactional lock elision definitions. */
-# ifdef ENABLE_LOCK_ELISION
extern int __lll_timedlock_elision
(int *futex, short *adapt_count, const struct timespec *timeout, int private)
attribute_hidden;
@@ -45,6 +44,5 @@ extern int __lll_trylock_elision(int *futex, short *adapt_count)
__lll_unlock_elision (&(futex), &(adapt_count), private)
# define lll_trylock_elision(futex, adapt_count) \
__lll_trylock_elision(&(futex), &(adapt_count))
-# endif /* ENABLE_LOCK_ELISION */
#endif /* lowlevellock.h */
@@ -21,6 +21,7 @@
#include <init-arch.h>
#include <elision-conf.h>
#include <unistd.h>
+#include <elf/dl-tunables.h>
/* Reasonable initial tuning values, may be revised in the future.
This is a conservative initial value. */
@@ -52,17 +53,46 @@ int __pthread_force_elision attribute_hidden;
/* Initialize elison. */
+static inline void
+do_set_elision_enable (bool elision_enable)
+{
+ /* If elision is not enabled, or we are in a secure mode,
+ make sure elision is never used... */
+ if (!elision_enable || __libc_enable_secure)
+ {
+ __pthread_force_elision = 0;
+ return;
+ }
+
+ /* ... otherwise enable elision based on hardare availability. */
+ __pthread_force_elision = HAS_CPU_FEATURE (RTM);
+}
+
+#if HAVE_TUNABLES
+/* The elision->enable tunable is either 0 or 1 to indicate that
+ elision should be disabled or enabled respectively. Availability at
+ the hardware level will still dictate if the feature is used. */
+void
+DL_TUNABLE_CALLBACK (set_elision_enable) (tunable_val_t *valp)
+{
+ int32_t elision_enable = (int32_t) valp->numval;
+ do_set_elision_enable (elision_enable ? true : false);
+}
+#endif
+
static void
elision_init (int argc __attribute__ ((unused)),
char **argv __attribute__ ((unused)),
char **environ)
{
- int elision_available = HAS_CPU_FEATURE (RTM);
-#ifdef ENABLE_LOCK_ELISION
- __pthread_force_elision = __libc_enable_secure ? 0 : elision_available;
+#if HAVE_TUNABLES
+ /* Elision depends on tunables to enable and tune elision at runtime. */
+# define TUNABLE_NAMESPACE elision
+ TUNABLE_SET_VAL_WITH_CALLBACK (enable, NULL, set_elision_enable);
+#else
+ /* Disable elision when built without tunables. */
+ do_set_elision_enable (false);
#endif
- if (!elision_available)
- __elision_aconf.retry_try_xbegin = 0; /* Disable elision on rwlocks */
}
#ifdef SHARED