Skip to content

Commit 6c67f8d

Browse files
author
Peter Zijlstra
committed
futex: Create futex_hash() get/put class
This gets us: hb = futex_hash(key) /* gets hb and inc users */ futex_hash_get(hb) /* inc users */ futex_hash_put(hb) /* dec users */ Signed-off-by: Peter Zijlstra (Intel) <[email protected]> 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 8486d12 commit 6c67f8d

File tree

5 files changed

+30
-24
lines changed

5 files changed

+30
-24
lines changed

kernel/futex/core.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ struct futex_hash_bucket *futex_hash(union futex_key *key)
122122
return &futex_queues[hash & futex_hashmask];
123123
}
124124

125+
void futex_hash_get(struct futex_hash_bucket *hb) { }
126+
void futex_hash_put(struct futex_hash_bucket *hb) { }
125127

126128
/**
127129
* futex_setup_timer - set up the sleeping hrtimer.
@@ -957,9 +959,7 @@ static void exit_pi_state_list(struct task_struct *curr)
957959
pi_state = list_entry(next, struct futex_pi_state, list);
958960
key = pi_state->key;
959961
if (1) {
960-
struct futex_hash_bucket *hb;
961-
962-
hb = futex_hash(&key);
962+
CLASS(hb, hb)(&key);
963963

964964
/*
965965
* We can race against put_pi_state() removing itself from the

kernel/futex/futex.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <linux/sched/wake_q.h>
88
#include <linux/compat.h>
99
#include <linux/uaccess.h>
10+
#include <linux/cleanup.h>
1011

1112
#ifdef CONFIG_PREEMPT_RT
1213
#include <linux/rcuwait.h>
@@ -202,6 +203,12 @@ futex_setup_timer(ktime_t *time, struct hrtimer_sleeper *timeout,
202203
int flags, u64 range_ns);
203204

204205
extern struct futex_hash_bucket *futex_hash(union futex_key *key);
206+
extern void futex_hash_get(struct futex_hash_bucket *hb);
207+
extern void futex_hash_put(struct futex_hash_bucket *hb);
208+
209+
DEFINE_CLASS(hb, struct futex_hash_bucket *,
210+
if (_T) futex_hash_put(_T),
211+
futex_hash(key), union futex_key *key);
205212

206213
/**
207214
* futex_match - Check whether two futex keys are equal

kernel/futex/pi.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -939,9 +939,8 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl
939939

940940
retry_private:
941941
if (1) {
942-
struct futex_hash_bucket *hb;
942+
CLASS(hb, hb)(&q.key);
943943

944-
hb = futex_hash(&q.key);
945944
futex_q_lock(&q, hb);
946945

947946
ret = futex_lock_pi_atomic(uaddr, hb, &q.key, &q.pi_state, current,
@@ -994,6 +993,16 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl
994993
goto no_block;
995994
}
996995

996+
/*
997+
* Caution; releasing @hb in-scope. The hb->lock is still locked
998+
* while the reference is dropped. The reference can not be dropped
999+
* after the unlock because if a user initiated resize is in progress
1000+
* then we might need to wake him. This can not be done after the
1001+
* rt_mutex_pre_schedule() invocation. The hb will remain valid because
1002+
* the thread, performing resize, will block on hb->lock during
1003+
* the requeue.
1004+
*/
1005+
futex_hash_put(no_free_ptr(hb));
9971006
/*
9981007
* Must be done before we enqueue the waiter, here is unfortunately
9991008
* under the hb lock, but that *should* work because it does nothing.
@@ -1119,7 +1128,6 @@ int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
11191128
{
11201129
u32 curval, uval, vpid = task_pid_vnr(current);
11211130
union futex_key key = FUTEX_KEY_INIT;
1122-
struct futex_hash_bucket *hb;
11231131
struct futex_q *top_waiter;
11241132
int ret;
11251133

@@ -1139,7 +1147,7 @@ int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
11391147
if (ret)
11401148
return ret;
11411149

1142-
hb = futex_hash(&key);
1150+
CLASS(hb, hb)(&key);
11431151
spin_lock(&hb->lock);
11441152
retry_hb:
11451153

kernel/futex/requeue.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -444,10 +444,8 @@ int futex_requeue(u32 __user *uaddr1, unsigned int flags1,
444444

445445
retry_private:
446446
if (1) {
447-
struct futex_hash_bucket *hb1, *hb2;
448-
449-
hb1 = futex_hash(&key1);
450-
hb2 = futex_hash(&key2);
447+
CLASS(hb, hb1)(&key1);
448+
CLASS(hb, hb2)(&key2);
451449

452450
futex_hb_waiters_inc(hb2);
453451
double_lock_hb(hb1, hb2);
@@ -817,9 +815,7 @@ int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
817815
switch (futex_requeue_pi_wakeup_sync(&q)) {
818816
case Q_REQUEUE_PI_IGNORE:
819817
{
820-
struct futex_hash_bucket *hb;
821-
822-
hb = futex_hash(&q.key);
818+
CLASS(hb, hb)(&q.key);
823819
/* The waiter is still on uaddr1 */
824820
spin_lock(&hb->lock);
825821
ret = handle_early_requeue_pi_wakeup(hb, &q, to);

kernel/futex/waitwake.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,6 @@ void futex_wake_mark(struct wake_q_head *wake_q, struct futex_q *q)
154154
*/
155155
int futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
156156
{
157-
struct futex_hash_bucket *hb;
158157
struct futex_q *this, *next;
159158
union futex_key key = FUTEX_KEY_INIT;
160159
DEFINE_WAKE_Q(wake_q);
@@ -170,7 +169,7 @@ int futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
170169
if ((flags & FLAGS_STRICT) && !nr_wake)
171170
return 0;
172171

173-
hb = futex_hash(&key);
172+
CLASS(hb, hb)(&key);
174173

175174
/* Make sure we really have tasks to wakeup */
176175
if (!futex_hb_waiters_pending(hb))
@@ -267,10 +266,8 @@ int futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
267266

268267
retry_private:
269268
if (1) {
270-
struct futex_hash_bucket *hb1, *hb2;
271-
272-
hb1 = futex_hash(&key1);
273-
hb2 = futex_hash(&key2);
269+
CLASS(hb, hb1)(&key1);
270+
CLASS(hb, hb2)(&key2);
274271

275272
double_lock_hb(hb1, hb2);
276273
op_ret = futex_atomic_op_inuser(op, uaddr2);
@@ -444,9 +441,8 @@ int futex_wait_multiple_setup(struct futex_vector *vs, int count, int *woken)
444441
u32 val = vs[i].w.val;
445442

446443
if (1) {
447-
struct futex_hash_bucket *hb;
444+
CLASS(hb, hb)(&q->key);
448445

449-
hb = futex_hash(&q->key);
450446
futex_q_lock(q, hb);
451447
ret = futex_get_value_locked(&uval, uaddr);
452448

@@ -618,9 +614,8 @@ int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
618614

619615
retry_private:
620616
if (1) {
621-
struct futex_hash_bucket *hb;
617+
CLASS(hb, hb)(&q->key);
622618

623-
hb = futex_hash(&q->key);
624619
futex_q_lock(q, hb);
625620

626621
ret = futex_get_value_locked(&uval, uaddr);

0 commit comments

Comments
 (0)