Skip to content

Commit fe00e88

Browse files
Sebastian Andrzej SiewiorPeter Zijlstra
authored andcommitted
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 <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 3f6b233 commit fe00e88

File tree

2 files changed

+5
-5
lines changed

2 files changed

+5
-5
lines changed

kernel/futex/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,8 +537,8 @@ void futex_q_lock(struct futex_q *q, struct futex_hash_bucket *hb)
537537
void futex_q_unlock(struct futex_hash_bucket *hb)
538538
__releases(&hb->lock)
539539
{
540-
spin_unlock(&hb->lock);
541540
futex_hb_waiters_dec(hb);
541+
spin_unlock(&hb->lock);
542542
}
543543

544544
void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb,

kernel/futex/requeue.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,8 @@ int futex_requeue(u32 __user *uaddr1, unsigned int flags1,
456456
ret = futex_get_value_locked(&curval, uaddr1);
457457

458458
if (unlikely(ret)) {
459-
double_unlock_hb(hb1, hb2);
460459
futex_hb_waiters_dec(hb2);
460+
double_unlock_hb(hb1, hb2);
461461

462462
ret = get_user(curval, uaddr1);
463463
if (ret)
@@ -542,8 +542,8 @@ int futex_requeue(u32 __user *uaddr1, unsigned int flags1,
542542
* waiter::requeue_state is correct.
543543
*/
544544
case -EFAULT:
545-
double_unlock_hb(hb1, hb2);
546545
futex_hb_waiters_dec(hb2);
546+
double_unlock_hb(hb1, hb2);
547547
ret = fault_in_user_writeable(uaddr2);
548548
if (!ret)
549549
goto retry;
@@ -556,8 +556,8 @@ int futex_requeue(u32 __user *uaddr1, unsigned int flags1,
556556
* exit to complete.
557557
* - EAGAIN: The user space value changed.
558558
*/
559-
double_unlock_hb(hb1, hb2);
560559
futex_hb_waiters_dec(hb2);
560+
double_unlock_hb(hb1, hb2);
561561
/*
562562
* Handle the case where the owner is in the middle of
563563
* exiting. Wait for the exit to complete otherwise
@@ -674,8 +674,8 @@ int futex_requeue(u32 __user *uaddr1, unsigned int flags1,
674674
put_pi_state(pi_state);
675675

676676
out_unlock:
677-
double_unlock_hb(hb1, hb2);
678677
futex_hb_waiters_dec(hb2);
678+
double_unlock_hb(hb1, hb2);
679679
}
680680
wake_up_q(&wake_q);
681681
return ret ? ret : task_count;

0 commit comments

Comments
 (0)