50f89d
commit 403b4feb22dcbc85ace72a361d2a951380372471
50f89d
Author: Stefan Liebler <stli@linux.ibm.com>
50f89d
Date:   Wed Oct 17 12:23:04 2018 +0200
50f89d
50f89d
    Fix race in pthread_mutex_lock while promoting to PTHREAD_MUTEX_ELISION_NP [BZ #23275]
50f89d
    
50f89d
    The race leads either to pthread_mutex_destroy returning EBUSY
50f89d
    or triggering an assertion (See description in bugzilla).
50f89d
    
50f89d
    This patch is fixing the race by ensuring that the elision path is
50f89d
    used in all cases if elision is enabled by the GLIBC_TUNABLES framework.
50f89d
    
50f89d
    The __kind variable in struct __pthread_mutex_s is accessed concurrently.
50f89d
    Therefore we are now using the atomic macros.
50f89d
    
50f89d
    The new testcase tst-mutex10 is triggering the race on s390x and intel.
50f89d
    Presumably also on power, but I don't have access to a power machine
50f89d
    with lock-elision. At least the code for power is the same as on the other
50f89d
    two architectures.
50f89d
    
50f89d
    ChangeLog:
50f89d
    
50f89d
            [BZ #23275]
50f89d
            * nptl/tst-mutex10.c: New File.
50f89d
            * nptl/Makefile (tests): Add tst-mutex10.
50f89d
            (tst-mutex10-ENV): New variable.
50f89d
            * sysdeps/unix/sysv/linux/s390/force-elision.h: (FORCE_ELISION):
50f89d
            Ensure that elision path is used if elision is available.
50f89d
            * sysdeps/unix/sysv/linux/powerpc/force-elision.h (FORCE_ELISION):
50f89d
            Likewise.
50f89d
            * sysdeps/unix/sysv/linux/x86/force-elision.h: (FORCE_ELISION):
50f89d
            Likewise.
50f89d
            * nptl/pthreadP.h (PTHREAD_MUTEX_TYPE, PTHREAD_MUTEX_TYPE_ELISION)
50f89d
            (PTHREAD_MUTEX_PSHARED): Use atomic_load_relaxed.
50f89d
            * nptl/pthread_mutex_consistent.c (pthread_mutex_consistent): Likewise.
50f89d
            * nptl/pthread_mutex_getprioceiling.c (pthread_mutex_getprioceiling):
50f89d
            Likewise.
50f89d
            * nptl/pthread_mutex_lock.c (__pthread_mutex_lock_full)
50f89d
            (__pthread_mutex_cond_lock_adjust): Likewise.
50f89d
            * nptl/pthread_mutex_setprioceiling.c (pthread_mutex_setprioceiling):
50f89d
            Likewise.
50f89d
            * nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock): Likewise.
50f89d
            * nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock): Likewise.
50f89d
            * nptl/pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Likewise.
50f89d
            * sysdeps/nptl/bits/thread-shared-types.h (struct __pthread_mutex_s):
50f89d
            Add comments.
50f89d
            * nptl/pthread_mutex_destroy.c (__pthread_mutex_destroy):
50f89d
            Use atomic_load_relaxed and atomic_store_relaxed.
50f89d
            * nptl/pthread_mutex_init.c (__pthread_mutex_init):
50f89d
            Use atomic_store_relaxed.
50f89d
50f89d
diff --git a/nptl/Makefile b/nptl/Makefile
50f89d
index be8066524cdc57db..49b6faa330c492e0 100644
50f89d
--- a/nptl/Makefile
50f89d
+++ b/nptl/Makefile
50f89d
@@ -241,9 +241,9 @@ LDLIBS-tst-minstack-throw = -lstdc++
50f89d
 
50f89d
 tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
50f89d
 	tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \
50f89d
-	tst-mutex7 tst-mutex9 tst-mutex5a tst-mutex7a tst-mutex7robust \
50f89d
-	tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \
50f89d
-	tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \
50f89d
+	tst-mutex7 tst-mutex9 tst-mutex10 tst-mutex5a tst-mutex7a \
50f89d
+	tst-mutex7robust tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 \
50f89d
+	tst-mutexpi5 tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \
50f89d
 	tst-mutexpi9 \
50f89d
 	tst-spin1 tst-spin2 tst-spin3 tst-spin4 \
50f89d
 	tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
50f89d
@@ -709,6 +709,8 @@ endif
50f89d
 
50f89d
 $(objpfx)tst-compat-forwarder: $(objpfx)tst-compat-forwarder-mod.so
50f89d
 
50f89d
+tst-mutex10-ENV = GLIBC_TUNABLES=glibc.elision.enable=1
50f89d
+
50f89d
 # The tests here better do not run in parallel
50f89d
 ifneq ($(filter %tests,$(MAKECMDGOALS)),)
50f89d
 .NOTPARALLEL:
50f89d
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
50f89d
index 13bdb11133536195..19efe1e35feed5be 100644
50f89d
--- a/nptl/pthreadP.h
50f89d
+++ b/nptl/pthreadP.h
50f89d
@@ -110,19 +110,23 @@ enum
50f89d
 };
50f89d
 #define PTHREAD_MUTEX_PSHARED_BIT 128
50f89d
 
50f89d
+/* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+   in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
 #define PTHREAD_MUTEX_TYPE(m) \
50f89d
-  ((m)->__data.__kind & 127)
50f89d
+  (atomic_load_relaxed (&((m)->__data.__kind)) & 127)
50f89d
 /* Don't include NO_ELISION, as that type is always the same
50f89d
    as the underlying lock type.  */
50f89d
 #define PTHREAD_MUTEX_TYPE_ELISION(m) \
50f89d
-  ((m)->__data.__kind & (127|PTHREAD_MUTEX_ELISION_NP))
50f89d
+  (atomic_load_relaxed (&((m)->__data.__kind))	\
50f89d
+   & (127 | PTHREAD_MUTEX_ELISION_NP))
50f89d
 
50f89d
 #if LLL_PRIVATE == 0 && LLL_SHARED == 128
50f89d
 # define PTHREAD_MUTEX_PSHARED(m) \
50f89d
-  ((m)->__data.__kind & 128)
50f89d
+  (atomic_load_relaxed (&((m)->__data.__kind)) & 128)
50f89d
 #else
50f89d
 # define PTHREAD_MUTEX_PSHARED(m) \
50f89d
-  (((m)->__data.__kind & 128) ? LLL_SHARED : LLL_PRIVATE)
50f89d
+  ((atomic_load_relaxed (&((m)->__data.__kind)) & 128)	\
50f89d
+   ? LLL_SHARED : LLL_PRIVATE)
50f89d
 #endif
50f89d
 
50f89d
 /* The kernel when waking robust mutexes on exit never uses
50f89d
diff --git a/nptl/pthread_mutex_consistent.c b/nptl/pthread_mutex_consistent.c
50f89d
index 85b8e1a6cb027e9b..4fbd875430439e4d 100644
50f89d
--- a/nptl/pthread_mutex_consistent.c
50f89d
+++ b/nptl/pthread_mutex_consistent.c
50f89d
@@ -23,8 +23,11 @@
50f89d
 int
50f89d
 pthread_mutex_consistent (pthread_mutex_t *mutex)
50f89d
 {
50f89d
-  /* Test whether this is a robust mutex with a dead owner.  */
50f89d
-  if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
50f89d
+  /* Test whether this is a robust mutex with a dead owner.
50f89d
+     See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+     in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+  if ((atomic_load_relaxed (&(mutex->__data.__kind))
50f89d
+       & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
50f89d
       || mutex->__data.__owner != PTHREAD_MUTEX_INCONSISTENT)
50f89d
     return EINVAL;
50f89d
 
50f89d
diff --git a/nptl/pthread_mutex_destroy.c b/nptl/pthread_mutex_destroy.c
50f89d
index 5a22611541995778..713ea684962fefc1 100644
50f89d
--- a/nptl/pthread_mutex_destroy.c
50f89d
+++ b/nptl/pthread_mutex_destroy.c
50f89d
@@ -27,12 +27,17 @@ __pthread_mutex_destroy (pthread_mutex_t *mutex)
50f89d
 {
50f89d
   LIBC_PROBE (mutex_destroy, 1, mutex);
50f89d
 
50f89d
-  if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
50f89d
+  /* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+     in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+  if ((atomic_load_relaxed (&(mutex->__data.__kind))
50f89d
+       & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
50f89d
       && mutex->__data.__nusers != 0)
50f89d
     return EBUSY;
50f89d
 
50f89d
-  /* Set to an invalid value.  */
50f89d
-  mutex->__data.__kind = -1;
50f89d
+  /* Set to an invalid value.  Relaxed MO is enough as it is undefined behavior
50f89d
+     if the mutex is used after it has been destroyed.  But you can reinitialize
50f89d
+     it with pthread_mutex_init.  */
50f89d
+  atomic_store_relaxed (&(mutex->__data.__kind), -1);
50f89d
 
50f89d
   return 0;
50f89d
 }
50f89d
diff --git a/nptl/pthread_mutex_getprioceiling.c b/nptl/pthread_mutex_getprioceiling.c
50f89d
index efa37b0d99201f57..ee85949578475f3a 100644
50f89d
--- a/nptl/pthread_mutex_getprioceiling.c
50f89d
+++ b/nptl/pthread_mutex_getprioceiling.c
50f89d
@@ -24,7 +24,9 @@
50f89d
 int
50f89d
 pthread_mutex_getprioceiling (const pthread_mutex_t *mutex, int *prioceiling)
50f89d
 {
50f89d
-  if (__builtin_expect ((mutex->__data.__kind
50f89d
+  /* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+     in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+  if (__builtin_expect ((atomic_load_relaxed (&(mutex->__data.__kind))
50f89d
 			 & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0, 0))
50f89d
     return EINVAL;
50f89d
 
50f89d
diff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c
50f89d
index d8fe4737289c0bd7..5cf290c272e27915 100644
50f89d
--- a/nptl/pthread_mutex_init.c
50f89d
+++ b/nptl/pthread_mutex_init.c
50f89d
@@ -101,7 +101,7 @@ __pthread_mutex_init (pthread_mutex_t *mutex,
50f89d
   memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T);
50f89d
 
50f89d
   /* Copy the values from the attribute.  */
50f89d
-  mutex->__data.__kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
50f89d
+  int mutex_kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
50f89d
 
50f89d
   if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0)
50f89d
     {
50f89d
@@ -111,17 +111,17 @@ __pthread_mutex_init (pthread_mutex_t *mutex,
50f89d
 	return ENOTSUP;
50f89d
 #endif
50f89d
 
50f89d
-      mutex->__data.__kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP;
50f89d
+      mutex_kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP;
50f89d
     }
50f89d
 
50f89d
   switch (imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK)
50f89d
     {
50f89d
     case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
50f89d
-      mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP;
50f89d
+      mutex_kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP;
50f89d
       break;
50f89d
 
50f89d
     case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
50f89d
-      mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP;
50f89d
+      mutex_kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP;
50f89d
 
50f89d
       int ceiling = (imutexattr->mutexkind
50f89d
 		     & PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
50f89d
@@ -145,7 +145,11 @@ __pthread_mutex_init (pthread_mutex_t *mutex,
50f89d
      FUTEX_PRIVATE_FLAG FUTEX_WAKE.  */
50f89d
   if ((imutexattr->mutexkind & (PTHREAD_MUTEXATTR_FLAG_PSHARED
50f89d
 				| PTHREAD_MUTEXATTR_FLAG_ROBUST)) != 0)
50f89d
-    mutex->__data.__kind |= PTHREAD_MUTEX_PSHARED_BIT;
50f89d
+    mutex_kind |= PTHREAD_MUTEX_PSHARED_BIT;
50f89d
+
50f89d
+  /* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+     in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+  atomic_store_relaxed (&(mutex->__data.__kind), mutex_kind);
50f89d
 
50f89d
   /* Default values: mutex not used yet.  */
50f89d
   // mutex->__count = 0;	already done by memset
50f89d
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
50f89d
index 1519c142bd6ec5cc..29cc143e6cbf2421 100644
50f89d
--- a/nptl/pthread_mutex_lock.c
50f89d
+++ b/nptl/pthread_mutex_lock.c
50f89d
@@ -62,6 +62,8 @@ static int __pthread_mutex_lock_full (pthread_mutex_t *mutex)
50f89d
 int
50f89d
 __pthread_mutex_lock (pthread_mutex_t *mutex)
50f89d
 {
50f89d
+  /* See concurrency notes regarding mutex type which is loaded from __kind
50f89d
+     in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
   unsigned int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
50f89d
 
50f89d
   LIBC_PROBE (mutex_entry, 1, mutex);
50f89d
@@ -350,8 +352,14 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
50f89d
     case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
50f89d
     case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
50f89d
       {
50f89d
-	int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
50f89d
-	int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
50f89d
+	int kind, robust;
50f89d
+	{
50f89d
+	  /* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+	     in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+	  int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
50f89d
+	  kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
50f89d
+	  robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
50f89d
+	}
50f89d
 
50f89d
 	if (robust)
50f89d
 	  {
50f89d
@@ -502,7 +510,10 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
50f89d
     case PTHREAD_MUTEX_PP_NORMAL_NP:
50f89d
     case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
50f89d
       {
50f89d
-	int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
50f89d
+	/* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+	   in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+	int kind = atomic_load_relaxed (&(mutex->__data.__kind))
50f89d
+	  & PTHREAD_MUTEX_KIND_MASK_NP;
50f89d
 
50f89d
 	oldval = mutex->__data.__lock;
50f89d
 
50f89d
@@ -607,15 +618,18 @@ hidden_def (__pthread_mutex_lock)
50f89d
 void
50f89d
 __pthread_mutex_cond_lock_adjust (pthread_mutex_t *mutex)
50f89d
 {
50f89d
-  assert ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0);
50f89d
-  assert ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0);
50f89d
-  assert ((mutex->__data.__kind & PTHREAD_MUTEX_PSHARED_BIT) == 0);
50f89d
+  /* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+     in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+  int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
50f89d
+  assert ((mutex_kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0);
50f89d
+  assert ((mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0);
50f89d
+  assert ((mutex_kind & PTHREAD_MUTEX_PSHARED_BIT) == 0);
50f89d
 
50f89d
   /* Record the ownership.  */
50f89d
   pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
50f89d
   mutex->__data.__owner = id;
50f89d
 
50f89d
-  if (mutex->__data.__kind == PTHREAD_MUTEX_PI_RECURSIVE_NP)
50f89d
+  if (mutex_kind == PTHREAD_MUTEX_PI_RECURSIVE_NP)
50f89d
     ++mutex->__data.__count;
50f89d
 }
50f89d
 #endif
50f89d
diff --git a/nptl/pthread_mutex_setprioceiling.c b/nptl/pthread_mutex_setprioceiling.c
50f89d
index 8594874f8588b7a8..8306cabcf4e56174 100644
50f89d
--- a/nptl/pthread_mutex_setprioceiling.c
50f89d
+++ b/nptl/pthread_mutex_setprioceiling.c
50f89d
@@ -27,9 +27,10 @@ int
50f89d
 pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling,
50f89d
 			      int *old_ceiling)
50f89d
 {
50f89d
-  /* The low bits of __kind aren't ever changed after pthread_mutex_init,
50f89d
-     so we don't need a lock yet.  */
50f89d
-  if ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0)
50f89d
+  /* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+     in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+  if ((atomic_load_relaxed (&(mutex->__data.__kind))
50f89d
+       & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0)
50f89d
     return EINVAL;
50f89d
 
50f89d
   /* See __init_sched_fifo_prio.  */
50f89d
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
50f89d
index 28237b0e58cfcaf5..888c12fe28b2ebfd 100644
50f89d
--- a/nptl/pthread_mutex_timedlock.c
50f89d
+++ b/nptl/pthread_mutex_timedlock.c
50f89d
@@ -53,6 +53,8 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
50f89d
   /* We must not check ABSTIME here.  If the thread does not block
50f89d
      abstime must not be checked for a valid value.  */
50f89d
 
50f89d
+  /* See concurrency notes regarding mutex type which is loaded from __kind
50f89d
+     in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
   switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex),
50f89d
 			    PTHREAD_MUTEX_TIMED_NP))
50f89d
     {
50f89d
@@ -338,8 +340,14 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
50f89d
     case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
50f89d
     case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
50f89d
       {
50f89d
-	int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
50f89d
-	int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
50f89d
+	int kind, robust;
50f89d
+	{
50f89d
+	  /* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+	     in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+	  int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
50f89d
+	  kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
50f89d
+	  robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
50f89d
+	}
50f89d
 
50f89d
 	if (robust)
50f89d
 	  {
50f89d
@@ -509,7 +517,10 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
50f89d
     case PTHREAD_MUTEX_PP_NORMAL_NP:
50f89d
     case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
50f89d
       {
50f89d
-	int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
50f89d
+	/* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+	   in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+	int kind = atomic_load_relaxed (&(mutex->__data.__kind))
50f89d
+	  & PTHREAD_MUTEX_KIND_MASK_NP;
50f89d
 
50f89d
 	oldval = mutex->__data.__lock;
50f89d
 
50f89d
diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
50f89d
index 7de61f4f688c1537..fa90c1d1e6f5afc2 100644
50f89d
--- a/nptl/pthread_mutex_trylock.c
50f89d
+++ b/nptl/pthread_mutex_trylock.c
50f89d
@@ -36,6 +36,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
50f89d
   int oldval;
50f89d
   pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
50f89d
 
50f89d
+  /* See concurrency notes regarding mutex type which is loaded from __kind
50f89d
+     in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
   switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex),
50f89d
 			    PTHREAD_MUTEX_TIMED_NP))
50f89d
     {
50f89d
@@ -199,8 +201,14 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
50f89d
     case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
50f89d
     case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
50f89d
       {
50f89d
-	int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
50f89d
-	int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
50f89d
+	int kind, robust;
50f89d
+	{
50f89d
+	  /* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+	     in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+	  int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
50f89d
+	  kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
50f89d
+	  robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
50f89d
+	}
50f89d
 
50f89d
 	if (robust)
50f89d
 	  /* Note: robust PI futexes are signaled by setting bit 0.  */
50f89d
@@ -325,7 +333,10 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
50f89d
     case PTHREAD_MUTEX_PP_NORMAL_NP:
50f89d
     case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
50f89d
       {
50f89d
-	int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
50f89d
+	/* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+	   in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+	int kind = atomic_load_relaxed (&(mutex->__data.__kind))
50f89d
+	  & PTHREAD_MUTEX_KIND_MASK_NP;
50f89d
 
50f89d
 	oldval = mutex->__data.__lock;
50f89d
 
50f89d
diff --git a/nptl/pthread_mutex_unlock.c b/nptl/pthread_mutex_unlock.c
50f89d
index 9ea62943b7c6b159..68d04d53955584e5 100644
50f89d
--- a/nptl/pthread_mutex_unlock.c
50f89d
+++ b/nptl/pthread_mutex_unlock.c
50f89d
@@ -35,6 +35,8 @@ int
50f89d
 attribute_hidden
50f89d
 __pthread_mutex_unlock_usercnt (pthread_mutex_t *mutex, int decr)
50f89d
 {
50f89d
+  /* See concurrency notes regarding mutex type which is loaded from __kind
50f89d
+     in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
   int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
50f89d
   if (__builtin_expect (type &
50f89d
 		~(PTHREAD_MUTEX_KIND_MASK_NP|PTHREAD_MUTEX_ELISION_FLAGS_NP), 0))
50f89d
@@ -222,13 +224,19 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
50f89d
       /* If the previous owner died and the caller did not succeed in
50f89d
 	 making the state consistent, mark the mutex as unrecoverable
50f89d
 	 and make all waiters.  */
50f89d
-      if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0
50f89d
+      /* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+	 in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+      if ((atomic_load_relaxed (&(mutex->__data.__kind))
50f89d
+	   & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0
50f89d
 	  && __builtin_expect (mutex->__data.__owner
50f89d
 			       == PTHREAD_MUTEX_INCONSISTENT, 0))
50f89d
       pi_notrecoverable:
50f89d
        newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
50f89d
 
50f89d
-      if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0)
50f89d
+      /* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+	 in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+      if ((atomic_load_relaxed (&(mutex->__data.__kind))
50f89d
+	   & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0)
50f89d
 	{
50f89d
 	continue_pi_robust:
50f89d
 	  /* Remove mutex from the list.
50f89d
@@ -251,7 +259,10 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
50f89d
       /* Unlock.  Load all necessary mutex data before releasing the mutex
50f89d
 	 to not violate the mutex destruction requirements (see
50f89d
 	 lll_unlock).  */
50f89d
-      int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
50f89d
+      /* See concurrency notes regarding __kind in struct __pthread_mutex_s
50f89d
+	 in sysdeps/nptl/bits/thread-shared-types.h.  */
50f89d
+      int robust = atomic_load_relaxed (&(mutex->__data.__kind))
50f89d
+	& PTHREAD_MUTEX_ROBUST_NORMAL_NP;
50f89d
       private = (robust
50f89d
 		 ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
50f89d
 		 : PTHREAD_MUTEX_PSHARED (mutex));
50f89d
diff --git a/nptl/tst-mutex10.c b/nptl/tst-mutex10.c
50f89d
new file mode 100644
50f89d
index 0000000000000000..e1113ca60a7c8db5
50f89d
--- /dev/null
50f89d
+++ b/nptl/tst-mutex10.c
50f89d
@@ -0,0 +1,109 @@
50f89d
+/* Testing race while enabling lock elision.
50f89d
+   Copyright (C) 2018 Free Software Foundation, Inc.
50f89d
+   This file is part of the GNU C Library.
50f89d
+
50f89d
+   The GNU C Library is free software; you can redistribute it and/or
50f89d
+   modify it under the terms of the GNU Lesser General Public
50f89d
+   License as published by the Free Software Foundation; either
50f89d
+   version 2.1 of the License, or (at your option) any later version.
50f89d
+
50f89d
+   The GNU C Library is distributed in the hope that it will be useful,
50f89d
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
50f89d
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
50f89d
+   Lesser General Public License for more details.
50f89d
+
50f89d
+   You should have received a copy of the GNU Lesser General Public
50f89d
+   License along with the GNU C Library; if not, see
50f89d
+   <http://www.gnu.org/licenses/>.  */
50f89d
+#include <stdio.h>
50f89d
+#include <stdlib.h>
50f89d
+#include <stdint.h>
50f89d
+#include <pthread.h>
50f89d
+#include <unistd.h>
50f89d
+#include <getopt.h>
50f89d
+#include <support/support.h>
50f89d
+#include <support/xthread.h>
50f89d
+
50f89d
+static pthread_barrier_t barrier;
50f89d
+static pthread_mutex_t mutex;
50f89d
+static long long int iteration_count = 1000000;
50f89d
+static unsigned int thread_count = 3;
50f89d
+
50f89d
+static void *
50f89d
+thr_func (void *arg)
50f89d
+{
50f89d
+  long long int i;
50f89d
+  for (i = 0; i < iteration_count; i++)
50f89d
+    {
50f89d
+      if ((uintptr_t) arg == 0)
50f89d
+	{
50f89d
+	  xpthread_mutex_destroy (&mutex);
50f89d
+	  xpthread_mutex_init (&mutex, NULL);
50f89d
+	}
50f89d
+
50f89d
+      xpthread_barrier_wait (&barrier);
50f89d
+
50f89d
+      /* Test if enabling lock elision works if it is enabled concurrently.
50f89d
+	 There was a race in FORCE_ELISION macro which leads to either
50f89d
+	 pthread_mutex_destroy returning EBUSY as the owner was recorded
50f89d
+	 by pthread_mutex_lock - in "normal mutex" code path - but was not
50f89d
+	 resetted in pthread_mutex_unlock - in "elision" code path.
50f89d
+	 Or it leads to the assertion in nptl/pthread_mutex_lock.c:
50f89d
+	 assert (mutex->__data.__owner == 0);
50f89d
+	 Please ensure that the test is run with lock elision:
50f89d
+	 export GLIBC_TUNABLES=glibc.elision.enable=1  */
50f89d
+      xpthread_mutex_lock (&mutex);
50f89d
+      xpthread_mutex_unlock (&mutex);
50f89d
+
50f89d
+      xpthread_barrier_wait (&barrier);
50f89d
+    }
50f89d
+  return NULL;
50f89d
+}
50f89d
+
50f89d
+static int
50f89d
+do_test (void)
50f89d
+{
50f89d
+  unsigned int i;
50f89d
+  printf ("Starting %d threads to run %lld iterations.\n",
50f89d
+	  thread_count, iteration_count);
50f89d
+
50f89d
+  pthread_t *threads = xmalloc (thread_count * sizeof (pthread_t));
50f89d
+  xpthread_barrier_init (&barrier, NULL, thread_count);
50f89d
+  xpthread_mutex_init (&mutex, NULL);
50f89d
+
50f89d
+  for (i = 0; i < thread_count; i++)
50f89d
+    threads[i] = xpthread_create (NULL, thr_func, (void *) (uintptr_t) i);
50f89d
+
50f89d
+  for (i = 0; i < thread_count; i++)
50f89d
+    xpthread_join (threads[i]);
50f89d
+
50f89d
+  xpthread_barrier_destroy (&barrier);
50f89d
+  free (threads);
50f89d
+
50f89d
+  return EXIT_SUCCESS;
50f89d
+}
50f89d
+
50f89d
+#define OPT_ITERATIONS	10000
50f89d
+#define OPT_THREADS	10001
50f89d
+#define CMDLINE_OPTIONS						\
50f89d
+  { "iterations", required_argument, NULL, OPT_ITERATIONS },	\
50f89d
+  { "threads", required_argument, NULL, OPT_THREADS },
50f89d
+static void
50f89d
+cmdline_process (int c)
50f89d
+{
50f89d
+  long long int arg = strtoll (optarg, NULL, 0);
50f89d
+  switch (c)
50f89d
+    {
50f89d
+    case OPT_ITERATIONS:
50f89d
+      if (arg > 0)
50f89d
+	iteration_count = arg;
50f89d
+      break;
50f89d
+    case OPT_THREADS:
50f89d
+      if (arg > 0 && arg < 100)
50f89d
+	thread_count = arg;
50f89d
+      break;
50f89d
+    }
50f89d
+}
50f89d
+#define CMDLINE_PROCESS cmdline_process
50f89d
+#define TIMEOUT 50
50f89d
+#include <support/test-driver.c>
50f89d
diff --git a/sysdeps/nptl/bits/thread-shared-types.h b/sysdeps/nptl/bits/thread-shared-types.h
50f89d
index 1e2092a05d5610f7..05c94e7a710c0eb9 100644
50f89d
--- a/sysdeps/nptl/bits/thread-shared-types.h
50f89d
+++ b/sysdeps/nptl/bits/thread-shared-types.h
50f89d
@@ -124,7 +124,27 @@ struct __pthread_mutex_s
50f89d
   unsigned int __nusers;
50f89d
 #endif
50f89d
   /* KIND must stay at this position in the structure to maintain
50f89d
-     binary compatibility with static initializers.  */
50f89d
+     binary compatibility with static initializers.
50f89d
+
50f89d
+     Concurrency notes:
50f89d
+     The __kind of a mutex is initialized either by the static
50f89d
+     PTHREAD_MUTEX_INITIALIZER or by a call to pthread_mutex_init.
50f89d
+
50f89d
+     After a mutex has been initialized, the __kind of a mutex is usually not
50f89d
+     changed.  BUT it can be set to -1 in pthread_mutex_destroy or elision can
50f89d
+     be enabled.  This is done concurrently in the pthread_mutex_*lock functions
50f89d
+     by using the macro FORCE_ELISION. This macro is only defined for
50f89d
+     architectures which supports lock elision.
50f89d
+
50f89d
+     For elision, there are the flags PTHREAD_MUTEX_ELISION_NP and
50f89d
+     PTHREAD_MUTEX_NO_ELISION_NP which can be set in addition to the already set
50f89d
+     type of a mutex.
50f89d
+     Before a mutex is initialized, only PTHREAD_MUTEX_NO_ELISION_NP can be set
50f89d
+     with pthread_mutexattr_settype.
50f89d
+     After a mutex has been initialized, the functions pthread_mutex_*lock can
50f89d
+     enable elision - if the mutex-type and the machine supports it - by setting
50f89d
+     the flag PTHREAD_MUTEX_ELISION_NP. This is done concurrently. Afterwards
50f89d
+     the lock / unlock functions are using specific elision code-paths.  */
50f89d
   int __kind;
50f89d
   __PTHREAD_COMPAT_PADDING_MID
50f89d
 #if __PTHREAD_MUTEX_NUSERS_AFTER_KIND
50f89d
diff --git a/sysdeps/unix/sysv/linux/powerpc/force-elision.h b/sysdeps/unix/sysv/linux/powerpc/force-elision.h
50f89d
index fe5d6ceade2bad36..d8f5a4b1c7713bd4 100644
50f89d
--- a/sysdeps/unix/sysv/linux/powerpc/force-elision.h
50f89d
+++ b/sysdeps/unix/sysv/linux/powerpc/force-elision.h
50f89d
@@ -18,9 +18,45 @@
50f89d
 
50f89d
 /* Automatically enable elision for existing user lock kinds.  */
50f89d
 #define FORCE_ELISION(m, s)						\
50f89d
-  if (__pthread_force_elision						\
50f89d
-      && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0)	\
50f89d
+  if (__pthread_force_elision)						\
50f89d
     {									\
50f89d
-      mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP;			\
50f89d
-      s;								\
50f89d
+      /* See concurrency notes regarding __kind in			\
50f89d
+	 struct __pthread_mutex_s in					\
50f89d
+	 sysdeps/nptl/bits/thread-shared-types.h.			\
50f89d
+									\
50f89d
+	 There are the following cases for the kind of a mutex		\
50f89d
+	 (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags	\
50f89d
+	 PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where	\
50f89d
+	 only one of both flags can be set):				\
50f89d
+	 - both flags are not set:					\
50f89d
+	 This is the first lock operation for this mutex.  Enable	\
50f89d
+	 elision as it is not enabled so far.				\
50f89d
+	 Note: It can happen that multiple threads are calling e.g.	\
50f89d
+	 pthread_mutex_lock at the same time as the first lock		\
50f89d
+	 operation for this mutex.  Then elision is enabled for this	\
50f89d
+	 mutex by multiple threads.  Storing with relaxed MO is enough	\
50f89d
+	 as all threads will store the same new value for the kind of	\
50f89d
+	 the mutex.  But we have to ensure that we always use the	\
50f89d
+	 elision path regardless if this thread has enabled elision or	\
50f89d
+	 another one.							\
50f89d
+									\
50f89d
+	 - PTHREAD_MUTEX_ELISION_NP flag is set:			\
50f89d
+	 Elision was already enabled for this mutex by a previous lock	\
50f89d
+	 operation.  See case above.  Just use the elision path.	\
50f89d
+									\
50f89d
+	 - PTHREAD_MUTEX_NO_ELISION_NP flag is set:			\
50f89d
+	 Elision was explicitly disabled by pthread_mutexattr_settype.	\
50f89d
+	 Do not use the elision path.					\
50f89d
+	 Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be	\
50f89d
+	 changed after mutex initialization.  */			\
50f89d
+      int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind));	\
50f89d
+      if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0)		\
50f89d
+	{								\
50f89d
+	  mutex_kind |= PTHREAD_MUTEX_ELISION_NP;			\
50f89d
+	  atomic_store_relaxed (&((m)->__data.__kind), mutex_kind);	\
50f89d
+	}								\
50f89d
+      if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0)			\
50f89d
+	{								\
50f89d
+	  s;								\
50f89d
+	}								\
50f89d
     }
50f89d
diff --git a/sysdeps/unix/sysv/linux/s390/force-elision.h b/sysdeps/unix/sysv/linux/s390/force-elision.h
50f89d
index d8a1b9972f739cfe..71f32367dd6b6489 100644
50f89d
--- a/sysdeps/unix/sysv/linux/s390/force-elision.h
50f89d
+++ b/sysdeps/unix/sysv/linux/s390/force-elision.h
50f89d
@@ -18,9 +18,45 @@
50f89d
 
50f89d
 /* Automatically enable elision for existing user lock kinds.  */
50f89d
 #define FORCE_ELISION(m, s)						\
50f89d
-  if (__pthread_force_elision						\
50f89d
-      && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0)	\
50f89d
+  if (__pthread_force_elision)						\
50f89d
     {									\
50f89d
-      mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP;			\
50f89d
-      s;								\
50f89d
+      /* See concurrency notes regarding __kind in			\
50f89d
+	 struct __pthread_mutex_s in					\
50f89d
+	 sysdeps/nptl/bits/thread-shared-types.h.			\
50f89d
+									\
50f89d
+	 There are the following cases for the kind of a mutex		\
50f89d
+	 (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags	\
50f89d
+	 PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where	\
50f89d
+	 only one of both flags can be set):				\
50f89d
+	 - both flags are not set:					\
50f89d
+	 This is the first lock operation for this mutex.  Enable	\
50f89d
+	 elision as it is not enabled so far.				\
50f89d
+	 Note: It can happen that multiple threads are calling e.g.	\
50f89d
+	 pthread_mutex_lock at the same time as the first lock		\
50f89d
+	 operation for this mutex.  Then elision is enabled for this	\
50f89d
+	 mutex by multiple threads.  Storing with relaxed MO is enough	\
50f89d
+	 as all threads will store the same new value for the kind of	\
50f89d
+	 the mutex.  But we have to ensure that we always use the	\
50f89d
+	 elision path regardless if this thread has enabled elision or	\
50f89d
+	 another one.							\
50f89d
+									\
50f89d
+	 - PTHREAD_MUTEX_ELISION_NP flag is set:			\
50f89d
+	 Elision was already enabled for this mutex by a previous lock	\
50f89d
+	 operation.  See case above.  Just use the elision path.	\
50f89d
+									\
50f89d
+	 - PTHREAD_MUTEX_NO_ELISION_NP flag is set:			\
50f89d
+	 Elision was explicitly disabled by pthread_mutexattr_settype.	\
50f89d
+	 Do not use the elision path.					\
50f89d
+	 Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be	\
50f89d
+	 changed after mutex initialization.  */			\
50f89d
+      int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind));	\
50f89d
+      if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0)		\
50f89d
+	{								\
50f89d
+	  mutex_kind |= PTHREAD_MUTEX_ELISION_NP;			\
50f89d
+	  atomic_store_relaxed (&((m)->__data.__kind), mutex_kind);	\
50f89d
+	}								\
50f89d
+      if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0)			\
50f89d
+	{								\
50f89d
+	  s;								\
50f89d
+	}								\
50f89d
     }
50f89d
diff --git a/sysdeps/unix/sysv/linux/x86/force-elision.h b/sysdeps/unix/sysv/linux/x86/force-elision.h
50f89d
index dd659c908f3046c1..61282d6678d89787 100644
50f89d
--- a/sysdeps/unix/sysv/linux/x86/force-elision.h
50f89d
+++ b/sysdeps/unix/sysv/linux/x86/force-elision.h
50f89d
@@ -18,9 +18,45 @@
50f89d
 
50f89d
 /* Automatically enable elision for existing user lock kinds.  */
50f89d
 #define FORCE_ELISION(m, s)						\
50f89d
-  if (__pthread_force_elision						\
50f89d
-      && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0)	\
50f89d
+  if (__pthread_force_elision)						\
50f89d
     {									\
50f89d
-      mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP;			\
50f89d
-      s;								\
50f89d
+      /* See concurrency notes regarding __kind in			\
50f89d
+	 struct __pthread_mutex_s in					\
50f89d
+	 sysdeps/nptl/bits/thread-shared-types.h.			\
50f89d
+									\
50f89d
+	 There are the following cases for the kind of a mutex		\
50f89d
+	 (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags	\
50f89d
+	 PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where	\
50f89d
+	 only one of both flags can be set):				\
50f89d
+	 - both flags are not set:					\
50f89d
+	 This is the first lock operation for this mutex.  Enable	\
50f89d
+	 elision as it is not enabled so far.				\
50f89d
+	 Note: It can happen that multiple threads are calling e.g.	\
50f89d
+	 pthread_mutex_lock at the same time as the first lock		\
50f89d
+	 operation for this mutex.  Then elision is enabled for this	\
50f89d
+	 mutex by multiple threads.  Storing with relaxed MO is enough	\
50f89d
+	 as all threads will store the same new value for the kind of	\
50f89d
+	 the mutex.  But we have to ensure that we always use the	\
50f89d
+	 elision path regardless if this thread has enabled elision or	\
50f89d
+	 another one.							\
50f89d
+									\
50f89d
+	 - PTHREAD_MUTEX_ELISION_NP flag is set:			\
50f89d
+	 Elision was already enabled for this mutex by a previous lock	\
50f89d
+	 operation.  See case above.  Just use the elision path.	\
50f89d
+									\
50f89d
+	 - PTHREAD_MUTEX_NO_ELISION_NP flag is set:			\
50f89d
+	 Elision was explicitly disabled by pthread_mutexattr_settype.	\
50f89d
+	 Do not use the elision path.					\
50f89d
+	 Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be	\
50f89d
+	 changed after mutex initialization.  */			\
50f89d
+      int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind));	\
50f89d
+      if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0)		\
50f89d
+	{								\
50f89d
+	  mutex_kind |= PTHREAD_MUTEX_ELISION_NP;			\
50f89d
+	  atomic_store_relaxed (&((m)->__data.__kind), mutex_kind);	\
50f89d
+	}								\
50f89d
+      if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0)			\
50f89d
+	{								\
50f89d
+	  s;								\
50f89d
+	}								\
50f89d
     }