Andreas Schwab
afe7a231ef
- pthread-rwlock-trylock-stalls.patch: nptl: Fix pthread_rwlock_try*lock stalls (BZ #23844) - arm-systemtap-probe-constraint.patch: arm: Use "nr" constraint for Systemtap probes (BZ #24164) - pthread-mutex-barrier.patch: Add compiler barriers around modifications of the robust mutex list for pthread_mutex_trylock (BZ #24180) - fork-handler-lock.patch: nptl: Avoid fork handler lock for async-signal-safe fork (BZ #24161) - pthread-join-probe.patch: nptl: Fix invalid Systemtap probe in pthread_join (BZ #24211) - riscv-clone-unwind.patch: RISC-V: Fix elfutils testsuite unwind failures (BZ #24040) OBS-URL: https://build.opensuse.org/request/show/677136 OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=518
174 lines
6.4 KiB
Diff
174 lines
6.4 KiB
Diff
2019-02-07 Stefan Liebler <stli@linux.ibm.com>
|
|
|
|
[BZ #24180]
|
|
* nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock):
|
|
Add compiler barriers and comments.
|
|
|
|
Index: glibc-2.29/nptl/pthread_mutex_trylock.c
|
|
===================================================================
|
|
--- glibc-2.29.orig/nptl/pthread_mutex_trylock.c
|
|
+++ glibc-2.29/nptl/pthread_mutex_trylock.c
|
|
@@ -94,6 +94,9 @@ __pthread_mutex_trylock (pthread_mutex_t
|
|
case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:
|
|
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
|
|
&mutex->__data.__list.__next);
|
|
+ /* We need to set op_pending before starting the operation. Also
|
|
+ see comments at ENQUEUE_MUTEX. */
|
|
+ __asm ("" ::: "memory");
|
|
|
|
oldval = mutex->__data.__lock;
|
|
do
|
|
@@ -119,7 +122,12 @@ __pthread_mutex_trylock (pthread_mutex_t
|
|
/* But it is inconsistent unless marked otherwise. */
|
|
mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
|
|
|
|
+ /* We must not enqueue the mutex before we have acquired it.
|
|
+ Also see comments at ENQUEUE_MUTEX. */
|
|
+ __asm ("" ::: "memory");
|
|
ENQUEUE_MUTEX (mutex);
|
|
+ /* We need to clear op_pending after we enqueue the mutex. */
|
|
+ __asm ("" ::: "memory");
|
|
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
|
|
|
/* Note that we deliberately exist here. If we fall
|
|
@@ -135,6 +143,8 @@ __pthread_mutex_trylock (pthread_mutex_t
|
|
int kind = PTHREAD_MUTEX_TYPE (mutex);
|
|
if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP)
|
|
{
|
|
+ /* We do not need to ensure ordering wrt another memory
|
|
+ access. Also see comments at ENQUEUE_MUTEX. */
|
|
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
|
|
NULL);
|
|
return EDEADLK;
|
|
@@ -142,6 +152,8 @@ __pthread_mutex_trylock (pthread_mutex_t
|
|
|
|
if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP)
|
|
{
|
|
+ /* We do not need to ensure ordering wrt another memory
|
|
+ access. */
|
|
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
|
|
NULL);
|
|
|
|
@@ -160,6 +172,9 @@ __pthread_mutex_trylock (pthread_mutex_t
|
|
id, 0);
|
|
if (oldval != 0 && (oldval & FUTEX_OWNER_DIED) == 0)
|
|
{
|
|
+ /* We haven't acquired the lock as it is already acquired by
|
|
+ another owner. We do not need to ensure ordering wrt another
|
|
+ memory access. */
|
|
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
|
|
|
return EBUSY;
|
|
@@ -173,13 +188,20 @@ __pthread_mutex_trylock (pthread_mutex_t
|
|
if (oldval == id)
|
|
lll_unlock (mutex->__data.__lock,
|
|
PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
|
|
+ /* FIXME This violates the mutex destruction requirements. See
|
|
+ __pthread_mutex_unlock_full. */
|
|
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
|
return ENOTRECOVERABLE;
|
|
}
|
|
}
|
|
while ((oldval & FUTEX_OWNER_DIED) != 0);
|
|
|
|
+ /* We must not enqueue the mutex before we have acquired it.
|
|
+ Also see comments at ENQUEUE_MUTEX. */
|
|
+ __asm ("" ::: "memory");
|
|
ENQUEUE_MUTEX (mutex);
|
|
+ /* We need to clear op_pending after we enqueue the mutex. */
|
|
+ __asm ("" ::: "memory");
|
|
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
|
|
|
mutex->__data.__owner = id;
|
|
@@ -211,10 +233,15 @@ __pthread_mutex_trylock (pthread_mutex_t
|
|
}
|
|
|
|
if (robust)
|
|
- /* Note: robust PI futexes are signaled by setting bit 0. */
|
|
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
|
|
- (void *) (((uintptr_t) &mutex->__data.__list.__next)
|
|
- | 1));
|
|
+ {
|
|
+ /* Note: robust PI futexes are signaled by setting bit 0. */
|
|
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
|
|
+ (void *) (((uintptr_t) &mutex->__data.__list.__next)
|
|
+ | 1));
|
|
+ /* We need to set op_pending before starting the operation. Also
|
|
+ see comments at ENQUEUE_MUTEX. */
|
|
+ __asm ("" ::: "memory");
|
|
+ }
|
|
|
|
oldval = mutex->__data.__lock;
|
|
|
|
@@ -223,12 +250,16 @@ __pthread_mutex_trylock (pthread_mutex_t
|
|
{
|
|
if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
|
|
{
|
|
+ /* We do not need to ensure ordering wrt another memory
|
|
+ access. */
|
|
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
|
return EDEADLK;
|
|
}
|
|
|
|
if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
|
|
{
|
|
+ /* We do not need to ensure ordering wrt another memory
|
|
+ access. */
|
|
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
|
|
|
/* Just bump the counter. */
|
|
@@ -250,6 +281,9 @@ __pthread_mutex_trylock (pthread_mutex_t
|
|
{
|
|
if ((oldval & FUTEX_OWNER_DIED) == 0)
|
|
{
|
|
+ /* We haven't acquired the lock as it is already acquired by
|
|
+ another owner. We do not need to ensure ordering wrt another
|
|
+ memory access. */
|
|
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
|
|
|
return EBUSY;
|
|
@@ -270,6 +304,9 @@ __pthread_mutex_trylock (pthread_mutex_t
|
|
if (INTERNAL_SYSCALL_ERROR_P (e, __err)
|
|
&& INTERNAL_SYSCALL_ERRNO (e, __err) == EWOULDBLOCK)
|
|
{
|
|
+ /* The kernel has not yet finished the mutex owner death.
|
|
+ We do not need to ensure ordering wrt another memory
|
|
+ access. */
|
|
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
|
|
|
return EBUSY;
|
|
@@ -287,7 +324,12 @@ __pthread_mutex_trylock (pthread_mutex_t
|
|
/* But it is inconsistent unless marked otherwise. */
|
|
mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
|
|
|
|
+ /* We must not enqueue the mutex before we have acquired it.
|
|
+ Also see comments at ENQUEUE_MUTEX. */
|
|
+ __asm ("" ::: "memory");
|
|
ENQUEUE_MUTEX (mutex);
|
|
+ /* We need to clear op_pending after we enqueue the mutex. */
|
|
+ __asm ("" ::: "memory");
|
|
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
|
|
|
/* Note that we deliberately exit here. If we fall
|
|
@@ -310,13 +352,20 @@ __pthread_mutex_trylock (pthread_mutex_t
|
|
PTHREAD_ROBUST_MUTEX_PSHARED (mutex)),
|
|
0, 0);
|
|
|
|
+ /* To the kernel, this will be visible after the kernel has
|
|
+ acquired the mutex in the syscall. */
|
|
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
|
return ENOTRECOVERABLE;
|
|
}
|
|
|
|
if (robust)
|
|
{
|
|
+ /* We must not enqueue the mutex before we have acquired it.
|
|
+ Also see comments at ENQUEUE_MUTEX. */
|
|
+ __asm ("" ::: "memory");
|
|
ENQUEUE_MUTEX_PI (mutex);
|
|
+ /* We need to clear op_pending after we enqueue the mutex. */
|
|
+ __asm ("" ::: "memory");
|
|
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
|
}
|
|
|