mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-27 11:43:34 +08:00
Fix blocking pthread_join. [BZ #23137]
On s390 (31bit) if glibc is build with -Os, pthread_join sometimes blocks indefinitely. This is e.g. observable with testcase intl/tst-gettext6. pthread_join is calling lll_wait_tid(tid), which performs the futex-wait syscall in a loop as long as tid != 0 (thread is alive). On s390 (and build with -Os), tid is loaded from memory before comparing against zero and then the tid is loaded a second time in order to pass it to the futex-wait-syscall. If the thread exits in between, then the futex-wait-syscall is called with the value zero and it waits until a futex-wake occurs. As the thread is already exited, there won't be a futex-wake. In lll_wait_tid, the tid is stored to the local variable __tid, which is then used as argument for the futex-wait-syscall. But unfortunately the compiler is allowed to reload the value from memory. With this patch, the tid is loaded with atomic_load_acquire. Then the compiler is not allowed to reload the value for __tid from memory. ChangeLog: [BZ #23137] * sysdeps/nptl/lowlevellock.h (lll_wait_tid): Use atomic_load_acquire to load __tid.
This commit is contained in:
parent
15c19147a8
commit
1660901840
@ -1,3 +1,9 @@
|
||||
2018-05-04 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
[BZ #23137]
|
||||
* sysdeps/nptl/lowlevellock.h (lll_wait_tid):
|
||||
Use atomic_load_acquire to load __tid.
|
||||
|
||||
2018-05-02 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/x86_64/swapcontext.S (__swapcontext):
|
||||
|
@ -181,11 +181,14 @@ extern int __lll_timedlock_wait (int *futex, const struct timespec *,
|
||||
thread ID while the clone is running and is reset to zero by the kernel
|
||||
afterwards. The kernel up to version 3.16.3 does not use the private futex
|
||||
operations for futex wake-up when the clone terminates. */
|
||||
#define lll_wait_tid(tid) \
|
||||
do { \
|
||||
__typeof (tid) __tid; \
|
||||
while ((__tid = (tid)) != 0) \
|
||||
lll_futex_wait (&(tid), __tid, LLL_SHARED);\
|
||||
#define lll_wait_tid(tid) \
|
||||
do { \
|
||||
__typeof (tid) __tid; \
|
||||
/* We need acquire MO here so that we synchronize \
|
||||
with the kernel's store to 0 when the clone \
|
||||
terminates. (see above) */ \
|
||||
while ((__tid = atomic_load_acquire (&(tid))) != 0) \
|
||||
lll_futex_wait (&(tid), __tid, LLL_SHARED); \
|
||||
} while (0)
|
||||
|
||||
extern int __lll_timedwait_tid (int *, const struct timespec *)
|
||||
|
Loading…
Reference in New Issue
Block a user