Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

futex: Decrease the waiter count before the unlock operation

To support runtime resizing of the process private hash, it's required
to not use the obtained hash bucket once the reference count has been
dropped. The reference will be dropped after the unlock of the hash
bucket.
The amount of waiters is decremented after the unlock operation. There
is no requirement that this needs to happen after the unlock. The
increment happens before acquiring the lock to signal early that there
will be a waiter. The waiter can avoid blocking on the lock if it is
known that there will be no waiter.
There is no difference in terms of ordering if the decrement happens
before or after the unlock.

Decrease the waiter count before the unlock operation.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20250416162921.513656-10-bigeasy@linutronix.de

authored by

Sebastian Andrzej Siewior and committed by
Peter Zijlstra
fe00e88d 3f6b2330

+5 -5
+1 -1
kernel/futex/core.c
··· 537 537 void futex_q_unlock(struct futex_hash_bucket *hb) 538 538 __releases(&hb->lock) 539 539 { 540 - spin_unlock(&hb->lock); 541 540 futex_hb_waiters_dec(hb); 541 + spin_unlock(&hb->lock); 542 542 } 543 543 544 544 void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb,
+4 -4
kernel/futex/requeue.c
··· 456 456 ret = futex_get_value_locked(&curval, uaddr1); 457 457 458 458 if (unlikely(ret)) { 459 - double_unlock_hb(hb1, hb2); 460 459 futex_hb_waiters_dec(hb2); 460 + double_unlock_hb(hb1, hb2); 461 461 462 462 ret = get_user(curval, uaddr1); 463 463 if (ret) ··· 542 542 * waiter::requeue_state is correct. 543 543 */ 544 544 case -EFAULT: 545 - double_unlock_hb(hb1, hb2); 546 545 futex_hb_waiters_dec(hb2); 546 + double_unlock_hb(hb1, hb2); 547 547 ret = fault_in_user_writeable(uaddr2); 548 548 if (!ret) 549 549 goto retry; ··· 556 556 * exit to complete. 557 557 * - EAGAIN: The user space value changed. 558 558 */ 559 - double_unlock_hb(hb1, hb2); 560 559 futex_hb_waiters_dec(hb2); 560 + double_unlock_hb(hb1, hb2); 561 561 /* 562 562 * Handle the case where the owner is in the middle of 563 563 * exiting. Wait for the exit to complete otherwise ··· 674 674 put_pi_state(pi_state); 675 675 676 676 out_unlock: 677 - double_unlock_hb(hb1, hb2); 678 677 futex_hb_waiters_dec(hb2); 678 + double_unlock_hb(hb1, hb2); 679 679 } 680 680 wake_up_q(&wake_q); 681 681 return ret ? ret : task_count;