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