summaryrefslogtreecommitdiff
path: root/nptl/pthread_mutex_timedlock.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2012-12-22 01:03:04 -0800
committerAndi Kleen <ak@linux.intel.com>2013-07-02 08:46:55 -0700
commite8c659d74e011346785355eeef03b7fb6f533c61 (patch)
tree7791d2e0769dc19ff7b549be745e4ddc251c3b7a /nptl/pthread_mutex_timedlock.c
parent68cc29355f3334c7ad18f648ff9a6383a0916d23 (diff)
Add elision to pthread_mutex_{try,timed,un}lock
Add elision paths to the basic mutex locks. The normal path has a check for RTM and upgrades the lock to RTM when available. Trylocks cannot automatically upgrade, so they check for elision every time. We use a 4 byte value in the mutex to store the lock elision adaptation state. This is separate from the adaptive spin state and uses a separate field. Condition variables currently do not support elision. Recursive mutexes and condition variables may be supported at some point, but are not in the current implementation. Also "trylock" will not automatically enable elision unless some other lock call has been already called on the lock. This version does not use IFUNC, so it means every lock has one additional check for elision. Benchmarking showed the overhead to be negligible.
Diffstat (limited to 'nptl/pthread_mutex_timedlock.c')
-rw-r--r--nptl/pthread_mutex_timedlock.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
index 3a36424afa..689cefa2de 100644
--- a/nptl/pthread_mutex_timedlock.c
+++ b/nptl/pthread_mutex_timedlock.c
@@ -25,6 +25,17 @@
#include <stap-probe.h>
+#ifndef lll_timedlock_elision
+#define lll_timedlock_elision(a,dummy,b,c) lll_timedlock(a, b, c)
+#endif
+
+#ifndef lll_trylock_elision
+#define lll_trylock_elision(a,t) lll_trylock(a)
+#endif
+
+#ifndef FORCE_ELISION
+#define FORCE_ELISION(m, s)
+#endif
int
pthread_mutex_timedlock (mutex, abstime)
@@ -40,10 +51,11 @@ pthread_mutex_timedlock (mutex, abstime)
/* We must not check ABSTIME here. If the thread does not block
abstime must not be checked for a valid value. */
- switch (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex),
+ switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex),
PTHREAD_MUTEX_TIMED_NP))
{
/* Recursive mutex. */
+ case PTHREAD_MUTEX_RECURSIVE_NP|PTHREAD_MUTEX_ELISION_NP:
case PTHREAD_MUTEX_RECURSIVE_NP:
/* Check whether we already hold the mutex. */
if (mutex->__data.__owner == id)
@@ -78,12 +90,22 @@ pthread_mutex_timedlock (mutex, abstime)
/* FALLTHROUGH */
case PTHREAD_MUTEX_TIMED_NP:
+ FORCE_ELISION (mutex, goto elision);
simple:
/* Normal mutex. */
result = lll_timedlock (mutex->__data.__lock, abstime,
PTHREAD_MUTEX_PSHARED (mutex));
break;
+ case PTHREAD_MUTEX_TIMED_ELISION_NP:
+ elision: __attribute__((unused))
+ /* Don't record ownership */
+ return lll_timedlock_elision (mutex->__data.__lock,
+ mutex->__data.__spins,
+ abstime,
+ PTHREAD_MUTEX_PSHARED (mutex));
+
+
case PTHREAD_MUTEX_ADAPTIVE_NP:
if (! __is_smp)
goto simple;