Skip to content

Commit 617fe4f

Browse files
committed
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()
2 parents 2f60f83 + 90d7588 commit 617fe4f

File tree

2 files changed

+19
-15
lines changed

2 files changed

+19
-15
lines changed

kernel/futex/core.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,7 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr,
638638
bool pi, bool pending_op)
639639
{
640640
u32 uval, nval, mval;
641+
pid_t owner;
641642
int err;
642643

643644
/* Futex address must be 32bit aligned */
@@ -659,6 +660,10 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr,
659660
* 2. A woken up waiter is killed before it can acquire the
660661
* futex in user space.
661662
*
663+
* In the second case, the wake up notification could be generated
664+
* by the unlock path in user space after setting the futex value
665+
* to zero or by the kernel after setting the OWNER_DIED bit below.
666+
*
662667
* In both cases the TID validation below prevents a wakeup of
663668
* potential waiters which can cause these waiters to block
664669
* forever.
@@ -667,24 +672,27 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr,
667672
*
668673
* 1) task->robust_list->list_op_pending != NULL
669674
* @pending_op == true
670-
* 2) User space futex value == 0
675+
* 2) The owner part of user space futex value == 0
671676
* 3) Regular futex: @pi == false
672677
*
673678
* If these conditions are met, it is safe to attempt waking up a
674679
* potential waiter without touching the user space futex value and
675-
* trying to set the OWNER_DIED bit. The user space futex value is
676-
* uncontended and the rest of the user space mutex state is
677-
* consistent, so a woken waiter will just take over the
678-
* uncontended futex. Setting the OWNER_DIED bit would create
679-
* inconsistent state and malfunction of the user space owner died
680-
* handling.
680+
* trying to set the OWNER_DIED bit. If the futex value is zero,
681+
* the rest of the user space mutex state is consistent, so a woken
682+
* waiter will just take over the uncontended futex. Setting the
683+
* OWNER_DIED bit would create inconsistent state and malfunction
684+
* of the user space owner died handling. Otherwise, the OWNER_DIED
685+
* bit is already set, and the woken waiter is expected to deal with
686+
* this.
681687
*/
682-
if (pending_op && !pi && !uval) {
688+
owner = uval & FUTEX_TID_MASK;
689+
690+
if (pending_op && !pi && !owner) {
683691
futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
684692
return 0;
685693
}
686694

687-
if ((uval & FUTEX_TID_MASK) != task_pid_vnr(curr))
695+
if (owner != task_pid_vnr(curr))
688696
return 0;
689697

690698
/*

kernel/jump_label.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,6 @@ EXPORT_SYMBOL_GPL(static_key_count);
115115

116116
void static_key_slow_inc_cpuslocked(struct static_key *key)
117117
{
118-
int v, v1;
119-
120118
STATIC_KEY_CHECK_USE(key);
121119
lockdep_assert_cpus_held();
122120

@@ -132,11 +130,9 @@ void static_key_slow_inc_cpuslocked(struct static_key *key)
132130
* so it counts as "enabled" in jump_label_update(). Note that
133131
* atomic_inc_unless_negative() checks >= 0, so roll our own.
134132
*/
135-
for (v = atomic_read(&key->enabled); v > 0; v = v1) {
136-
v1 = atomic_cmpxchg(&key->enabled, v, v + 1);
137-
if (likely(v1 == v))
133+
for (int v = atomic_read(&key->enabled); v > 0; )
134+
if (likely(atomic_try_cmpxchg(&key->enabled, &v, v + 1)))
138135
return;
139-
}
140136

141137
jump_label_lock();
142138
if (atomic_read(&key->enabled) == 0) {

0 commit comments

Comments
 (0)