|
|
c6d234 |
commit 5920a4a624b1f4db310d1c44997b640e2a4653e5
|
|
|
c6d234 |
Author: Carlos O'Donell <carlos@redhat.com>
|
|
|
c6d234 |
Date: Sat Jul 29 00:02:03 2017 -0400
|
|
|
c6d234 |
|
|
|
c6d234 |
mutex: Fix robust mutex lock acquire (Bug 21778)
|
|
|
c6d234 |
|
|
|
c6d234 |
65810f0ef05e8c9e333f17a44e77808b163ca298 fixed a robust mutex bug but
|
|
|
c6d234 |
introduced BZ 21778: if the CAS used to try to acquire a lock fails, the
|
|
|
c6d234 |
expected value is not updated, which breaks other cases in the loce
|
|
|
c6d234 |
acquisition loop. The fix is to simply update the expected value with
|
|
|
c6d234 |
the value returned by the CAS, which ensures that behavior is as if the
|
|
|
c6d234 |
first case with the CAS never happened (if the CAS fails).
|
|
|
c6d234 |
|
|
|
c6d234 |
This is a regression introduced in the last release.
|
|
|
c6d234 |
|
|
|
c6d234 |
Tested on x86_64, i686, ppc64, ppc64le, s390x, aarch64, armv7hl.
|
|
|
c6d234 |
|
|
|
c6d234 |
Index: glibc-2.17-c758a686/nptl/Makefile
|
|
|
c6d234 |
===================================================================
|
|
|
c6d234 |
--- glibc-2.17-c758a686.orig/nptl/Makefile
|
|
|
c6d234 |
+++ glibc-2.17-c758a686/nptl/Makefile
|
|
|
c6d234 |
@@ -204,7 +204,7 @@ CFLAGS-tst-thread-exit-clobber.o = -std=
|
|
|
c6d234 |
tests = tst-typesizes \
|
|
|
c6d234 |
tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
|
|
|
c6d234 |
tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \
|
|
|
c6d234 |
- tst-mutex7 tst-mutex8 tst-mutex9 tst-mutex5a tst-mutex7a \
|
|
|
c6d234 |
+ tst-mutex7 tst-mutex8 tst-mutex9 tst-mutex5a tst-mutex7a tst-mutex7robust \
|
|
|
c6d234 |
tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \
|
|
|
c6d234 |
tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a tst-mutexpi8 \
|
|
|
c6d234 |
tst-mutexpi9 \
|
|
|
c6d234 |
Index: glibc-2.17-c758a686/nptl/pthread_mutex_lock.c
|
|
|
c6d234 |
===================================================================
|
|
|
c6d234 |
--- glibc-2.17-c758a686.orig/nptl/pthread_mutex_lock.c
|
|
|
c6d234 |
+++ glibc-2.17-c758a686/nptl/pthread_mutex_lock.c
|
|
|
c6d234 |
@@ -198,11 +198,14 @@ __pthread_mutex_lock_full (pthread_mutex
|
|
|
c6d234 |
{
|
|
|
c6d234 |
/* Try to acquire the lock through a CAS from 0 (not acquired) to
|
|
|
c6d234 |
our TID | assume_other_futex_waiters. */
|
|
|
c6d234 |
- if (__glibc_likely ((oldval == 0)
|
|
|
c6d234 |
- && (atomic_compare_and_exchange_bool_acq
|
|
|
c6d234 |
- (&mutex->__data.__lock,
|
|
|
c6d234 |
- id | assume_other_futex_waiters, 0) == 0)))
|
|
|
c6d234 |
- break;
|
|
|
c6d234 |
+ if (__glibc_likely (oldval == 0))
|
|
|
c6d234 |
+ {
|
|
|
c6d234 |
+ oldval
|
|
|
c6d234 |
+ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
|
|
|
c6d234 |
+ id | assume_other_futex_waiters, 0);
|
|
|
c6d234 |
+ if (__glibc_likely (oldval == 0))
|
|
|
c6d234 |
+ break;
|
|
|
c6d234 |
+ }
|
|
|
c6d234 |
|
|
|
c6d234 |
if ((oldval & FUTEX_OWNER_DIED) != 0)
|
|
|
c6d234 |
{
|
|
|
c6d234 |
Index: glibc-2.17-c758a686/nptl/pthread_mutex_timedlock.c
|
|
|
c6d234 |
===================================================================
|
|
|
c6d234 |
--- glibc-2.17-c758a686.orig/nptl/pthread_mutex_timedlock.c
|
|
|
c6d234 |
+++ glibc-2.17-c758a686/nptl/pthread_mutex_timedlock.c
|
|
|
c6d234 |
@@ -154,11 +154,14 @@ pthread_mutex_timedlock (pthread_mutex_t
|
|
|
c6d234 |
{
|
|
|
c6d234 |
/* Try to acquire the lock through a CAS from 0 (not acquired) to
|
|
|
c6d234 |
our TID | assume_other_futex_waiters. */
|
|
|
c6d234 |
- if (__glibc_likely ((oldval == 0)
|
|
|
c6d234 |
- && (atomic_compare_and_exchange_bool_acq
|
|
|
c6d234 |
- (&mutex->__data.__lock,
|
|
|
c6d234 |
- id | assume_other_futex_waiters, 0) == 0)))
|
|
|
c6d234 |
- break;
|
|
|
c6d234 |
+ if (__glibc_likely (oldval == 0))
|
|
|
c6d234 |
+ {
|
|
|
c6d234 |
+ oldval
|
|
|
c6d234 |
+ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
|
|
|
c6d234 |
+ id | assume_other_futex_waiters, 0);
|
|
|
c6d234 |
+ if (__glibc_likely (oldval == 0))
|
|
|
c6d234 |
+ break;
|
|
|
c6d234 |
+ }
|
|
|
c6d234 |
|
|
|
c6d234 |
if ((oldval & FUTEX_OWNER_DIED) != 0)
|
|
|
c6d234 |
{
|
|
|
c6d234 |
Index: glibc-2.17-c758a686/nptl/tst-mutex7.c
|
|
|
c6d234 |
===================================================================
|
|
|
c6d234 |
--- glibc-2.17-c758a686.orig/nptl/tst-mutex7.c
|
|
|
c6d234 |
+++ glibc-2.17-c758a686/nptl/tst-mutex7.c
|
|
|
c6d234 |
@@ -22,25 +22,41 @@
|
|
|
c6d234 |
#include <stdlib.h>
|
|
|
c6d234 |
#include <time.h>
|
|
|
c6d234 |
|
|
|
c6d234 |
-
|
|
|
c6d234 |
+/* This test is a template for other tests to use. Other tests define
|
|
|
c6d234 |
+ the following macros to change the behaviour of the template test.
|
|
|
c6d234 |
+ The test is very simple, it configures N threads given the parameters
|
|
|
c6d234 |
+ below and then proceeds to go through mutex lock and unlock
|
|
|
c6d234 |
+ operations in each thread as described before for the thread
|
|
|
c6d234 |
+ function. */
|
|
|
c6d234 |
#ifndef TYPE
|
|
|
c6d234 |
# define TYPE PTHREAD_MUTEX_DEFAULT
|
|
|
c6d234 |
#endif
|
|
|
c6d234 |
-
|
|
|
c6d234 |
+#ifndef ROBUST
|
|
|
c6d234 |
+# define ROBUST PTHREAD_MUTEX_STALLED
|
|
|
c6d234 |
+#endif
|
|
|
c6d234 |
+#ifndef DELAY_NSEC
|
|
|
c6d234 |
+# define DELAY_NSEC 11000
|
|
|
c6d234 |
+#endif
|
|
|
c6d234 |
+#ifndef ROUNDS
|
|
|
c6d234 |
+# define ROUNDS 1000
|
|
|
c6d234 |
+#endif
|
|
|
c6d234 |
+#ifndef N
|
|
|
c6d234 |
+# define N 100
|
|
|
c6d234 |
+#endif
|
|
|
c6d234 |
|
|
|
c6d234 |
static pthread_mutex_t lock;
|
|
|
c6d234 |
|
|
|
c6d234 |
-
|
|
|
c6d234 |
-#define ROUNDS 1000
|
|
|
c6d234 |
-#define N 100
|
|
|
c6d234 |
-
|
|
|
c6d234 |
-
|
|
|
c6d234 |
+/* Each thread locks and the subsequently unlocks the lock, yielding
|
|
|
c6d234 |
+ the smallest critical section possible. After the unlock the thread
|
|
|
c6d234 |
+ waits DELAY_NSEC nanoseconds before doing the lock and unlock again.
|
|
|
c6d234 |
+ Every thread does this ROUNDS times. The lock and unlock are
|
|
|
c6d234 |
+ checked for errors. */
|
|
|
c6d234 |
static void *
|
|
|
c6d234 |
tf (void *arg)
|
|
|
c6d234 |
{
|
|
|
c6d234 |
int nr = (long int) arg;
|
|
|
c6d234 |
int cnt;
|
|
|
c6d234 |
- struct timespec ts = { .tv_sec = 0, .tv_nsec = 11000 };
|
|
|
c6d234 |
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = DELAY_NSEC };
|
|
|
c6d234 |
|
|
|
c6d234 |
for (cnt = 0; cnt < ROUNDS; ++cnt)
|
|
|
c6d234 |
{
|
|
|
c6d234 |
@@ -56,13 +72,16 @@ tf (void *arg)
|
|
|
c6d234 |
return (void *) 1l;
|
|
|
c6d234 |
}
|
|
|
c6d234 |
|
|
|
c6d234 |
- nanosleep (&ts, NULL);
|
|
|
c6d234 |
+ if ((ts.tv_sec > 0) || (ts.tv_nsec > 0))
|
|
|
c6d234 |
+ nanosleep (&ts, NULL);
|
|
|
c6d234 |
}
|
|
|
c6d234 |
|
|
|
c6d234 |
return NULL;
|
|
|
c6d234 |
}
|
|
|
c6d234 |
|
|
|
c6d234 |
-
|
|
|
c6d234 |
+/* Setup and run N threads, where each thread does as described
|
|
|
c6d234 |
+ in the above thread function. The threads are given a minimal 1MiB
|
|
|
c6d234 |
+ stack since they don't do anything between the lock and unlock. */
|
|
|
c6d234 |
static int
|
|
|
c6d234 |
do_test (void)
|
|
|
c6d234 |
{
|
|
|
c6d234 |
@@ -80,6 +99,12 @@ do_test (void)
|
|
|
c6d234 |
exit (1);
|
|
|
c6d234 |
}
|
|
|
c6d234 |
|
|
|
c6d234 |
+ if (pthread_mutexattr_setrobust (&a, ROBUST) != 0)
|
|
|
c6d234 |
+ {
|
|
|
c6d234 |
+ puts ("mutexattr_setrobust failed");
|
|
|
c6d234 |
+ exit (1);
|
|
|
c6d234 |
+ }
|
|
|
c6d234 |
+
|
|
|
c6d234 |
#ifdef ENABLE_PI
|
|
|
c6d234 |
if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
|
|
|
c6d234 |
{
|
|
|
c6d234 |
Index: glibc-2.17-c758a686/nptl/tst-mutex7robust.c
|
|
|
c6d234 |
===================================================================
|
|
|
c6d234 |
--- /dev/null
|
|
|
c6d234 |
+++ glibc-2.17-c758a686/nptl/tst-mutex7robust.c
|
|
|
c6d234 |
@@ -0,0 +1,7 @@
|
|
|
c6d234 |
+/* Bug 21778: Fix oversight in robust mutex lock acquisition. */
|
|
|
c6d234 |
+#define TYPE PTHREAD_MUTEX_NORMAL
|
|
|
c6d234 |
+#define ROBUST PTHREAD_MUTEX_ROBUST
|
|
|
c6d234 |
+#define DELAY_NSEC 0
|
|
|
c6d234 |
+#define ROUNDS 1000
|
|
|
c6d234 |
+#define N 32
|
|
|
c6d234 |
+#include "tst-mutex7.c"
|