robust mutexes: Fix broken x86 assembly by removing it
authorTorvald Riegel <triegel@redhat.com>
Thu, 22 Dec 2016 09:20:43 +0000 (10:20 +0100)
committerTorvald Riegel <triegel@redhat.com>
Fri, 13 Jan 2017 16:16:07 +0000 (17:16 +0100)
commit65810f0ef05e8c9e333f17a44e77808b163ca298
tree09928382f6015251c3b351650204f65fc8d6ec21
parentf32941d80c7f532031061f8dd4704fab9c275cfe
robust mutexes: Fix broken x86 assembly by removing it

lll_robust_unlock on i386 and x86_64 first sets the futex word to
FUTEX_WAITERS|0 before calling __lll_unlock_wake, which will set the
futex word to 0.  If the thread is killed between these steps, then the
futex word will be FUTEX_WAITERS|0, and the kernel (at least current
upstream) will not set it to FUTEX_OWNER_DIED|FUTEX_WAITERS because 0 is
not equal to the TID of the crashed thread.

The lll_robust_lock assembly code on i386 and x86_64 is not prepared to
deal with this case because the fastpath tries to only CAS 0 to TID and
not FUTEX_WAITERS|0 to TID; the slowpath simply waits until it can CAS 0
to TID or the futex_word has the FUTEX_OWNER_DIED bit set.

This issue is fixed by removing the custom x86 assembly code and using
the generic C code instead.  However, instead of adding more duplicate
code to the custom x86 lowlevellock.h, the code of the lll_robust* functions
is inlined into the single call sites that exist for each of these functions
in the pthread_mutex_* functions.  The robust mutex paths in the latter
have been slightly reorganized to make them simpler.

This patch is meant to be easy to backport, so C11-style atomics are not
used.

[BZ #20985]
* nptl/Makefile: Adapt.
* nptl/pthread_mutex_cond_lock.c (LLL_ROBUST_MUTEX_LOCK): Remove.
(LLL_ROBUST_MUTEX_LOCK_MODIFIER): New.
* nptl/pthread_mutex_lock.c (LLL_ROBUST_MUTEX_LOCK): Remove.
(LLL_ROBUST_MUTEX_LOCK_MODIFIER): New.
(__pthread_mutex_lock_full): Inline lll_robust* functions and adapt.
* nptl/pthread_mutex_timedlock.c (pthread_mutex_timedlock): Inline
lll_robust* functions and adapt.
* nptl/pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Likewise.
* sysdeps/nptl/lowlevellock.h (__lll_robust_lock_wait,
__lll_robust_lock, lll_robust_cond_lock, __lll_robust_timedlock_wait,
__lll_robust_timedlock, __lll_robust_unlock): Remove.
* sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_robust_lock,
lll_robust_cond_lock, lll_robust_timedlock, lll_robust_unlock): Remove.
* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_robust_lock,
lll_robust_cond_lock, lll_robust_timedlock, lll_robust_unlock): Remove.
* sysdeps/unix/sysv/linux/sparc/lowlevellock.h (__lll_robust_lock_wait,
__lll_robust_lock, lll_robust_cond_lock, __lll_robust_timedlock_wait,
__lll_robust_timedlock, __lll_robust_unlock): Remove.
* nptl/lowlevelrobustlock.c: Remove file.
* nptl/lowlevelrobustlock.sym: Likewise.
* sysdeps/unix/sysv/linux/i386/lowlevelrobustlock.S: Likewise.
* sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S: Likewise.
14 files changed:
ChangeLog
nptl/Makefile
nptl/lowlevelrobustlock.c [deleted file]
nptl/lowlevelrobustlock.sym [deleted file]
nptl/pthread_mutex_cond_lock.c
nptl/pthread_mutex_lock.c
nptl/pthread_mutex_timedlock.c
nptl/pthread_mutex_unlock.c
sysdeps/nptl/lowlevellock.h
sysdeps/unix/sysv/linux/i386/lowlevellock.h
sysdeps/unix/sysv/linux/i386/lowlevelrobustlock.S [deleted file]
sysdeps/unix/sysv/linux/sparc/lowlevellock.h
sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S [deleted file]