about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--nptl/Makefile2
-rw-r--r--nptl/pthread_mutex_lock.c13
-rw-r--r--nptl/pthread_mutex_timedlock.c13
-rw-r--r--nptl/tst-mutex7.c45
-rw-r--r--nptl/tst-mutex7robust.c7
6 files changed, 73 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog
index 4cec993f99..5368e15fb7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,17 @@
-2017-07-23  Nathan Rossi  <nathan@nathanrossi.com>
+2017-07-29  Torvald Riegel  <triegel@redhat.com>
+	    Carlos O'Donell  <carlos@redhat.com>
+
+	[BZ 21778]
+	* nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock): Update
+	oldval if the CAS fails.
+	* nptl/pthread_mutex_lock.c (__pthread_mutex_lock_full): Likewise.
+	* nptl/tst-mutex7.c: Add comments explaining template test.
+	(ROBUST, DELAY_NSEC, ROUNDS, N): New.
+	(tf, do_test): Use them.
+	* nptl/tst-mutex7robust.c: New file.
+	* nptl/Makefile (tests): Add new test.
+
+2017-07-28  Nathan Rossi  <nathan@nathanrossi.com>
 
 	[BZ #21779]
 	* sysdeps/unix/sysv/linux/microblaze/pt-vfork.S: Branch using PLT.
diff --git a/nptl/Makefile b/nptl/Makefile
index 7e54684a36..5cb1bb2c3d 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -230,7 +230,7 @@ LDLIBS-tst-thread_local1 = -lstdc++
 
 tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
 	tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \
-	tst-mutex7 tst-mutex9 tst-mutex5a tst-mutex7a \
+	tst-mutex7 tst-mutex9 tst-mutex5a tst-mutex7a tst-mutex7robust \
 	tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \
 	tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \
 	tst-mutexpi9 \
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
index b76475bc63..8c485035eb 100644
--- a/nptl/pthread_mutex_lock.c
+++ b/nptl/pthread_mutex_lock.c
@@ -197,11 +197,14 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
 	{
 	  /* Try to acquire the lock through a CAS from 0 (not acquired) to
 	     our TID | assume_other_futex_waiters.  */
-	  if (__glibc_likely ((oldval == 0)
-			      && (atomic_compare_and_exchange_bool_acq
-				  (&mutex->__data.__lock,
-				   id | assume_other_futex_waiters, 0) == 0)))
-	      break;
+	  if (__glibc_likely (oldval == 0))
+	    {
+	      oldval
+	        = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+	            id | assume_other_futex_waiters, 0);
+	      if (__glibc_likely (oldval == 0))
+		break;
+	    }
 
 	  if ((oldval & FUTEX_OWNER_DIED) != 0)
 	    {
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
index be5338178f..d5ec3141f3 100644
--- a/nptl/pthread_mutex_timedlock.c
+++ b/nptl/pthread_mutex_timedlock.c
@@ -154,11 +154,14 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
 	{
 	  /* Try to acquire the lock through a CAS from 0 (not acquired) to
 	     our TID | assume_other_futex_waiters.  */
-	  if (__glibc_likely ((oldval == 0)
-			      && (atomic_compare_and_exchange_bool_acq
-				  (&mutex->__data.__lock,
-				   id | assume_other_futex_waiters, 0) == 0)))
-	      break;
+	  if (__glibc_likely (oldval == 0))
+	    {
+	      oldval
+	        = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+	            id | assume_other_futex_waiters, 0);
+	      if (__glibc_likely (oldval == 0))
+		break;
+	    }
 
 	  if ((oldval & FUTEX_OWNER_DIED) != 0)
 	    {
diff --git a/nptl/tst-mutex7.c b/nptl/tst-mutex7.c
index a11afdba5e..08fe251eeb 100644
--- a/nptl/tst-mutex7.c
+++ b/nptl/tst-mutex7.c
@@ -22,25 +22,41 @@
 #include <stdlib.h>
 #include <time.h>
 
-
+/* This test is a template for other tests to use.  Other tests define
+   the following macros to change the behaviour of the template test.
+   The test is very simple, it configures N threads given the parameters
+   below and then proceeds to go through mutex lock and unlock
+   operations in each thread as described before for the thread
+   function.  */
 #ifndef TYPE
 # define TYPE PTHREAD_MUTEX_DEFAULT
 #endif
-
+#ifndef ROBUST
+# define ROBUST PTHREAD_MUTEX_STALLED
+#endif
+#ifndef DELAY_NSEC
+# define DELAY_NSEC 11000
+#endif
+#ifndef ROUNDS
+# define ROUNDS 1000
+#endif
+#ifndef N
+# define N 100
+#endif
 
 static pthread_mutex_t lock;
 
-
-#define ROUNDS 1000
-#define N 100
-
-
+/* Each thread locks and the subsequently unlocks the lock, yielding
+   the smallest critical section possible.  After the unlock the thread
+   waits DELAY_NSEC nanoseconds before doing the lock and unlock again.
+   Every thread does this ROUNDS times.  The lock and unlock are
+   checked for errors.  */
 static void *
 tf (void *arg)
 {
   int nr = (long int) arg;
   int cnt;
-  struct timespec ts = { .tv_sec = 0, .tv_nsec = 11000 };
+  struct timespec ts = { .tv_sec = 0, .tv_nsec = DELAY_NSEC };
 
   for (cnt = 0; cnt < ROUNDS; ++cnt)
     {
@@ -56,13 +72,16 @@ tf (void *arg)
 	  return (void *) 1l;
 	}
 
-      nanosleep (&ts, NULL);
+      if ((ts.tv_sec > 0) || (ts.tv_nsec > 0))
+	nanosleep (&ts, NULL);
     }
 
   return NULL;
 }
 
-
+/* Setup and run N threads, where each thread does as described
+   in the above thread function.  The threads are given a minimal 1MiB
+   stack since they don't do anything between the lock and unlock.  */
 static int
 do_test (void)
 {
@@ -80,6 +99,12 @@ do_test (void)
       exit (1);
     }
 
+  if (pthread_mutexattr_setrobust (&a, ROBUST) != 0)
+    {
+      puts ("mutexattr_setrobust failed");
+      exit (1);
+    }
+
 #ifdef ENABLE_PI
   if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
     {
diff --git a/nptl/tst-mutex7robust.c b/nptl/tst-mutex7robust.c
new file mode 100644
index 0000000000..8221a61d29
--- /dev/null
+++ b/nptl/tst-mutex7robust.c
@@ -0,0 +1,7 @@
+/* Bug 21778: Fix oversight in robust mutex lock acquisition.  */
+#define TYPE PTHREAD_MUTEX_NORMAL
+#define ROBUST PTHREAD_MUTEX_ROBUST
+#define DELAY_NSEC 0
+#define ROUNDS 1000
+#define N 32
+#include "tst-mutex7.c"