TSX lock elision for glibc v12
Torvald Riegel
triegel@redhat.com
Fri Jun 21 17:17:00 GMT 2013
On Fri, 2013-06-21 at 11:37 -0400, Rich Felker wrote:
> On Fri, Jun 21, 2013 at 05:00:29PM +0200, Torvald Riegel wrote:
> > Or should we just not try to support explicit initialization of DEFAULT
> > mutexes *via settype()* and just make them NORMAL mutexes by default?
> > This way, we wouldn't need to introduce a new public
> > PTHREAD_MUTEX_DEFAULT value, and could still disambiguate DEFAULT from
> > NORMAL when the initialization happens via static initializers or
> > default mutex attributes (ie, NULL parameter).
>
> I'm fine with this. I don't think there's any sane reason to call
> pthread_mutexattr_settype when making default-type mutexes, and I
> doubt any real-world apps do it. If they do, it's their fault for
> being slow; they're performing unnecessary, bloated operations in any
> case and should be fixed.
Ok.
Attached is what I am currently testing. This doesn't touch any of the
public mutex types, but disambiguates NORMAL from DEFAULT (modulo the
above). All the mutex functions can then handle
PTHREAD_MUTEX_NORMAL_INT_NP and PTHREAD_MUTEX_DEFAULT_INT_NP
differently. This should be sufficient as a base to enable elision for
the "90%", and we don't require further bits in the type. IOW, it's
stage 1) in my three-stage proposal for how to commit those things we
can actually agree on now.
I hope to get back to this later today.
-------------- next part --------------
commit 2f9407bb8108af3a27894e2d3eb915c00b9018fb
Author: Torvald Riegel <triegel@redhat.com>
Date: Fri Jun 21 16:38:17 2013 +0200
new mutex types
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index 7883fdf..7003417 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -60,7 +60,12 @@
/* Internal mutex type value. */
enum
{
- PTHREAD_MUTEX_KIND_MASK_NP = 3,
+ PTHREAD_MUTEX_KIND_MASK_NP = 7,
+ /* New internal alias for PTHREAD_MUTEX_DEFAULT-like mutexes. This is the
+ value that the default initializer uses. */
+ PTHREAD_MUTEX_DEFAULT_INT_NP = 0,
+ /* New internal type used for PTHREAD_MUTEX_NORMAL-like mutexes. */
+ PTHREAD_MUTEX_NORMAL_INT_NP = 4,
PTHREAD_MUTEX_ROBUST_NORMAL_NP = 16,
PTHREAD_MUTEX_ROBUST_RECURSIVE_NP
= PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_RECURSIVE_NP,
diff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c
index 174d900..788726b 100644
--- a/nptl/pthread_mutex_init.c
+++ b/nptl/pthread_mutex_init.c
@@ -26,8 +26,8 @@
static const struct pthread_mutexattr default_mutexattr =
{
- /* Default is a normal mutex, not shared between processes. */
- .mutexkind = PTHREAD_MUTEX_NORMAL
+ /* Default is a DEFAULT mutex, not shared between processes. */
+ .mutexkind = PTHREAD_MUTEX_DEFAULT_INT_NP
};
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
index fbedfd7..de18044 100644
--- a/nptl/pthread_mutex_lock.c
+++ b/nptl/pthread_mutex_lock.c
@@ -56,14 +56,16 @@ __pthread_mutex_lock (mutex)
pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
- if (__builtin_expect (type, PTHREAD_MUTEX_TIMED_NP)
- == PTHREAD_MUTEX_TIMED_NP)
+ if (__builtin_expect (type, PTHREAD_MUTEX_DEFAULT_INT_NP)
+ == PTHREAD_MUTEX_DEFAULT_INT_NP)
{
simple:
/* Normal mutex. */
LLL_MUTEX_LOCK (mutex);
assert (mutex->__data.__owner == 0);
}
+ else if (__builtin_expect (type == PTHREAD_MUTEX_NORMAL_INT_NP, 1))
+ goto simple;
else if (__builtin_expect (type == PTHREAD_MUTEX_RECURSIVE_NP, 1))
{
/* Recursive mutex. */
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
index 3a36424..f2c1dab 100644
--- a/nptl/pthread_mutex_timedlock.c
+++ b/nptl/pthread_mutex_timedlock.c
@@ -41,7 +41,7 @@ pthread_mutex_timedlock (mutex, abstime)
abstime must not be checked for a valid value. */
switch (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex),
- PTHREAD_MUTEX_TIMED_NP))
+ PTHREAD_MUTEX_DEFAULT_INT_NP))
{
/* Recursive mutex. */
case PTHREAD_MUTEX_RECURSIVE_NP:
@@ -77,7 +77,8 @@ pthread_mutex_timedlock (mutex, abstime)
/* FALLTHROUGH */
- case PTHREAD_MUTEX_TIMED_NP:
+ case PTHREAD_MUTEX_DEFAULT_INT_NP:
+ case PTHREAD_MUTEX_NORMAL_INT_NP:
simple:
/* Normal mutex. */
result = lll_timedlock (mutex->__data.__lock, abstime,
diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
index 8f5279d..8e1fcb6 100644
--- a/nptl/pthread_mutex_trylock.c
+++ b/nptl/pthread_mutex_trylock.c
@@ -31,7 +31,7 @@ __pthread_mutex_trylock (mutex)
pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
switch (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex),
- PTHREAD_MUTEX_TIMED_NP))
+ PTHREAD_MUTEX_DEFAULT_INT_NP))
{
/* Recursive mutex. */
case PTHREAD_MUTEX_RECURSIVE_NP:
@@ -58,7 +58,8 @@ __pthread_mutex_trylock (mutex)
break;
case PTHREAD_MUTEX_ERRORCHECK_NP:
- case PTHREAD_MUTEX_TIMED_NP:
+ case PTHREAD_MUTEX_DEFAULT_INT_NP:
+ case PTHREAD_MUTEX_NORMAL_INT_NP:
case PTHREAD_MUTEX_ADAPTIVE_NP:
/* Normal mutex. */
if (lll_trylock (mutex->__data.__lock) != 0)
diff --git a/nptl/pthread_mutex_unlock.c b/nptl/pthread_mutex_unlock.c
index c0249f7..5772af6 100644
--- a/nptl/pthread_mutex_unlock.c
+++ b/nptl/pthread_mutex_unlock.c
@@ -38,8 +38,8 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
if (__builtin_expect (type & ~PTHREAD_MUTEX_KIND_MASK_NP, 0))
return __pthread_mutex_unlock_full (mutex, decr);
- if (__builtin_expect (type, PTHREAD_MUTEX_TIMED_NP)
- == PTHREAD_MUTEX_TIMED_NP)
+ if (__builtin_expect (type, PTHREAD_MUTEX_DEFAULT_INT_NP)
+ == PTHREAD_MUTEX_DEFAULT_INT_NP)
{
/* Always reset the owner field. */
normal:
@@ -55,6 +55,8 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
return 0;
}
+ else if (__builtin_expect (type == PTHREAD_MUTEX_NORMAL_INT_NP, 1))
+ goto normal;
else if (__builtin_expect (type == PTHREAD_MUTEX_RECURSIVE_NP, 1))
{
/* Recursive mutex. */
diff --git a/nptl/pthread_mutexattr_gettype.c b/nptl/pthread_mutexattr_gettype.c
index 9008a49..d5ab2f2 100644
--- a/nptl/pthread_mutexattr_gettype.c
+++ b/nptl/pthread_mutexattr_gettype.c
@@ -29,6 +29,9 @@ pthread_mutexattr_gettype (attr, kind)
iattr = (const struct pthread_mutexattr *) attr;
*kind = iattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
+ /* See pthread_mutex_settype. */
+ if (*kind == PTHREAD_MUTEX_NORMAL_INT_NP)
+ *kind = PTHREAD_MUTEX_TIMED_NP;
return 0;
}
diff --git a/nptl/pthread_mutexattr_init.c b/nptl/pthread_mutexattr_init.c
index b08eeab..c193a44 100644
--- a/nptl/pthread_mutexattr_init.c
+++ b/nptl/pthread_mutexattr_init.c
@@ -30,7 +30,8 @@ __pthread_mutexattr_init (attr)
/* We use bit 31 to signal whether the mutex is going to be
process-shared or not. By default it is zero, i.e., the mutex is
not process-shared. */
- ((struct pthread_mutexattr *) attr)->mutexkind = PTHREAD_MUTEX_NORMAL;
+ ((struct pthread_mutexattr *) attr)->mutexkind
+ = PTHREAD_MUTEX_DEFAULT_INT_NP;
return 0;
}
diff --git a/nptl/pthread_mutexattr_settype.c b/nptl/pthread_mutexattr_settype.c
index 7b476e9..37fc2d3 100644
--- a/nptl/pthread_mutexattr_settype.c
+++ b/nptl/pthread_mutexattr_settype.c
@@ -30,6 +30,19 @@ __pthread_mutexattr_settype (attr, kind)
if (kind < PTHREAD_MUTEX_NORMAL || kind > PTHREAD_MUTEX_ADAPTIVE_NP)
return EINVAL;
+ /* Translate any kinds with semantics equivalent to PTHREAD_MUTEX_NORMAL to
+ the internal mutex kind for this. This allows us to disambiguate those
+ and PTHREAD_MUTEX_DEFAULT kinds specified in PTHREAD_MUTEX_INITIALIZER
+ without having to change the ABI. (This works because there is no
+ initializer for PTHREAD_MUTEX_NORMAL.) Note that this applies to
+ PTHREAD_MUTEX_TIMED_NP and PTHREAD_MUTEX_FAST_NP too because they use
+ the same value as PTHREAD_MUTEX_NORMAL.
+ XXX Trying to set PTHREAD_MUTEX_DEFAULT here will still result in a
+ mutex with PTHREAD_MUTEX_NORMAL semantics; this is still correct
+ behavior but may affect performance. */
+ if (kind == PTHREAD_MUTEX_TIMED_NP)
+ kind = PTHREAD_MUTEX_NORMAL_INT_NP;
+
iattr = (struct pthread_mutexattr *) attr;
iattr->mutexkind = (iattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_BITS) | kind;
More information about the Libc-alpha
mailing list