diff options
author | Andi Kleen <ak@linux.intel.com> | 2012-12-22 01:03:04 -0800 |
---|---|---|
committer | Andi Kleen <ak@linux.intel.com> | 2013-07-02 08:46:55 -0700 |
commit | e8c659d74e011346785355eeef03b7fb6f533c61 (patch) | |
tree | 7791d2e0769dc19ff7b549be745e4ddc251c3b7a /nptl/pthread_mutex_trylock.c | |
parent | 68cc29355f3334c7ad18f648ff9a6383a0916d23 (diff) | |
download | glibc-e8c659d74e011346785355eeef03b7fb6f533c61.zip glibc-e8c659d74e011346785355eeef03b7fb6f533c61.tar.gz glibc-e8c659d74e011346785355eeef03b7fb6f533c61.tar.bz2 |
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_trylock.c')
-rw-r--r-- | nptl/pthread_mutex_trylock.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c index 8f5279d..600c848 100644 --- a/nptl/pthread_mutex_trylock.c +++ b/nptl/pthread_mutex_trylock.c @@ -22,6 +22,16 @@ #include "pthreadP.h" #include <lowlevellock.h> +#ifndef lll_trylock_elision +#define lll_trylock_elision(a,t) lll_trylock(a) +#endif + +#ifndef DO_ELISION +#define DO_ELISION(m) 0 +#endif + +/* We don't force elision in trylock, because this can lead to inconsistent + lock state if the lock was actually busy. */ int __pthread_mutex_trylock (mutex) @@ -30,10 +40,11 @@ __pthread_mutex_trylock (mutex) int oldval; pid_t id = THREAD_GETMEM (THREAD_SELF, tid); - 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) @@ -57,10 +68,20 @@ __pthread_mutex_trylock (mutex) } break; - case PTHREAD_MUTEX_ERRORCHECK_NP: + case PTHREAD_MUTEX_TIMED_ELISION_NP: + elision: + if (lll_trylock_elision (mutex->__data.__lock, + mutex->__data.__elision) != 0) + break; + /* Don't record the ownership. */ + return 0; + case PTHREAD_MUTEX_TIMED_NP: + if (DO_ELISION (mutex)) + goto elision; + /*FALL THROUGH*/ case PTHREAD_MUTEX_ADAPTIVE_NP: - /* Normal mutex. */ + case PTHREAD_MUTEX_ERRORCHECK_NP: if (lll_trylock (mutex->__data.__lock) != 0) break; @@ -378,4 +399,9 @@ __pthread_mutex_trylock (mutex) return EBUSY; } + +#ifndef __pthread_mutex_trylock +#ifndef pthread_mutex_trylock strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock) +#endif +#endif |