about summary refs log tree commit diff
path: root/nptl/pthread_mutex_timedlock.c
diff options
context:
space:
mode:
authorCarlos O'Donell <carlos@redhat.com>2017-07-29 00:02:03 -0400
committerCarlos O'Donell <carlos@redhat.com>2017-07-29 00:02:03 -0400
commit5920a4a624b1f4db310d1c44997b640e2a4653e5 (patch)
treee58989b49f6aae484bcdf13adad65bdbe79273e3 /nptl/pthread_mutex_timedlock.c
parentd95fcb2df478efbf4f8537ba898374043ac4561f (diff)
downloadglibc-5920a4a624b1f4db310d1c44997b640e2a4653e5.tar.gz
glibc-5920a4a624b1f4db310d1c44997b640e2a4653e5.tar.xz
glibc-5920a4a624b1f4db310d1c44997b640e2a4653e5.zip
mutex: Fix robust mutex lock acquire (Bug 21778)
65810f0ef05e8c9e333f17a44e77808b163ca298 fixed a robust mutex bug but
introduced BZ 21778: if the CAS used to try to acquire a lock fails, the
expected value is not updated, which breaks other cases in the loce
acquisition loop.  The fix is to simply update the expected value with
the value returned by the CAS, which ensures that behavior is as if the
first case with the CAS never happened (if the CAS fails).

This is a regression introduced in the last release.

Tested on x86_64, i686, ppc64, ppc64le, s390x, aarch64, armv7hl.
Diffstat (limited to 'nptl/pthread_mutex_timedlock.c')
-rw-r--r--nptl/pthread_mutex_timedlock.c13
1 files changed, 8 insertions, 5 deletions
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)
 	    {