Two changes in this cycle:
- a micro-optimization in static_key_slow_inc_cpuslocked() - fix futex death-notification wakeup bug Signed-off-by: Ingo Molnar <mingo@kernel.org> -----BEGIN PGP SIGNATURE----- iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmOXi5sRHG1pbmdvQGtl cm5lbC5vcmcACgkQEnMQ0APhK1gf5A/8CbrmjosK6ls/NSLP7zVIOF3inAU8Ih0H pxkHWfDCzMG7WSTcjEH3AZl+hW7nXj41rC29i/7WyIxt4wslZiBQzpwEbmg92aF1 fZnmHtywvRPg1+l9XcYY6dHCL+3qr5K4v1plTXTgLLEQgKNAzO5XyPHLTYKrixGc 5hv1ntZnL9jw7+cTNmiS8tesenkrm1ZZC3IsqQcI7SxxTnrHjSgQQRRMMY2Wmom4 L9SKWTJ5xks2AgG/zzXCTqfSTBH9+tiqTLKq4vUqViIHGrWZxdEB3gPzm3qdXlyv 8IXiJ4ySGOEvK6Z6aaQOvVOJt/c7C7mx93NCLzGXS+dTOmAsead5IEtWBxUL90Un KwnV5RUcHgyeewpzTrY+GpYSgPk666HvBu0TEZrzkPH1aZR5cCa1AA52Y87pq6Xp YsAnz0X3s2daXToPBHZnXK+54PzkYyrqwtbAuolxW5h5PAKOKWQ5HLWtM5HD+qt6 oCtuVBxoTS14DsfM3zaNhMtQYykt2QgaxS5ic5Lt65HnxX1b85xxjNPukpCWuL4h TlTcaj3gW3cJybO+R9RTTAUITCx4ukLXUq/R/E4IKkX/6wWhm5a/KtRKUAxL1x4U BWDcQRhKn39Y4xKeLVQ4JHy74DItqLF8k7PFPUSYpmssLW8zLP54gTq9ontBU6CO bVGAaH+U2ZI= =7B6i -----END PGP SIGNATURE----- Merge tag 'locking-core-2022-12-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull locking updates from Ingo Molnar: "Two changes in this cycle: - a micro-optimization in static_key_slow_inc_cpuslocked() - fix futex death-notification wakeup bug" * tag 'locking-core-2022-12-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: futex: Resend potentially swallowed owner death notification jump_label: Use atomic_try_cmpxchg() in static_key_slow_inc_cpuslocked()
This commit is contained in:
commit
617fe4fa82
@ -638,6 +638,7 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr,
|
|||||||
bool pi, bool pending_op)
|
bool pi, bool pending_op)
|
||||||
{
|
{
|
||||||
u32 uval, nval, mval;
|
u32 uval, nval, mval;
|
||||||
|
pid_t owner;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* Futex address must be 32bit aligned */
|
/* Futex address must be 32bit aligned */
|
||||||
@ -659,6 +660,10 @@ retry:
|
|||||||
* 2. A woken up waiter is killed before it can acquire the
|
* 2. A woken up waiter is killed before it can acquire the
|
||||||
* futex in user space.
|
* futex in user space.
|
||||||
*
|
*
|
||||||
|
* In the second case, the wake up notification could be generated
|
||||||
|
* by the unlock path in user space after setting the futex value
|
||||||
|
* to zero or by the kernel after setting the OWNER_DIED bit below.
|
||||||
|
*
|
||||||
* In both cases the TID validation below prevents a wakeup of
|
* In both cases the TID validation below prevents a wakeup of
|
||||||
* potential waiters which can cause these waiters to block
|
* potential waiters which can cause these waiters to block
|
||||||
* forever.
|
* forever.
|
||||||
@ -667,24 +672,27 @@ retry:
|
|||||||
*
|
*
|
||||||
* 1) task->robust_list->list_op_pending != NULL
|
* 1) task->robust_list->list_op_pending != NULL
|
||||||
* @pending_op == true
|
* @pending_op == true
|
||||||
* 2) User space futex value == 0
|
* 2) The owner part of user space futex value == 0
|
||||||
* 3) Regular futex: @pi == false
|
* 3) Regular futex: @pi == false
|
||||||
*
|
*
|
||||||
* If these conditions are met, it is safe to attempt waking up a
|
* If these conditions are met, it is safe to attempt waking up a
|
||||||
* potential waiter without touching the user space futex value and
|
* potential waiter without touching the user space futex value and
|
||||||
* trying to set the OWNER_DIED bit. The user space futex value is
|
* trying to set the OWNER_DIED bit. If the futex value is zero,
|
||||||
* uncontended and the rest of the user space mutex state is
|
* the rest of the user space mutex state is consistent, so a woken
|
||||||
* consistent, so a woken waiter will just take over the
|
* waiter will just take over the uncontended futex. Setting the
|
||||||
* uncontended futex. Setting the OWNER_DIED bit would create
|
* OWNER_DIED bit would create inconsistent state and malfunction
|
||||||
* inconsistent state and malfunction of the user space owner died
|
* of the user space owner died handling. Otherwise, the OWNER_DIED
|
||||||
* handling.
|
* bit is already set, and the woken waiter is expected to deal with
|
||||||
|
* this.
|
||||||
*/
|
*/
|
||||||
if (pending_op && !pi && !uval) {
|
owner = uval & FUTEX_TID_MASK;
|
||||||
|
|
||||||
|
if (pending_op && !pi && !owner) {
|
||||||
futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
|
futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((uval & FUTEX_TID_MASK) != task_pid_vnr(curr))
|
if (owner != task_pid_vnr(curr))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -115,8 +115,6 @@ EXPORT_SYMBOL_GPL(static_key_count);
|
|||||||
|
|
||||||
void static_key_slow_inc_cpuslocked(struct static_key *key)
|
void static_key_slow_inc_cpuslocked(struct static_key *key)
|
||||||
{
|
{
|
||||||
int v, v1;
|
|
||||||
|
|
||||||
STATIC_KEY_CHECK_USE(key);
|
STATIC_KEY_CHECK_USE(key);
|
||||||
lockdep_assert_cpus_held();
|
lockdep_assert_cpus_held();
|
||||||
|
|
||||||
@ -132,11 +130,9 @@ void static_key_slow_inc_cpuslocked(struct static_key *key)
|
|||||||
* so it counts as "enabled" in jump_label_update(). Note that
|
* so it counts as "enabled" in jump_label_update(). Note that
|
||||||
* atomic_inc_unless_negative() checks >= 0, so roll our own.
|
* atomic_inc_unless_negative() checks >= 0, so roll our own.
|
||||||
*/
|
*/
|
||||||
for (v = atomic_read(&key->enabled); v > 0; v = v1) {
|
for (int v = atomic_read(&key->enabled); v > 0; )
|
||||||
v1 = atomic_cmpxchg(&key->enabled, v, v + 1);
|
if (likely(atomic_try_cmpxchg(&key->enabled, &v, v + 1)))
|
||||||
if (likely(v1 == v))
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
jump_label_lock();
|
jump_label_lock();
|
||||||
if (atomic_read(&key->enabled) == 0) {
|
if (atomic_read(&key->enabled) == 0) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user