mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
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) <peterz@infradead.org> 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-7-bigeasy@linutronix.de
This commit is contained in:
parent
8486d12f55
commit
6c67f8d880
|
|
@ -122,6 +122,8 @@ struct futex_hash_bucket *futex_hash(union futex_key *key)
|
|||
return &futex_queues[hash & futex_hashmask];
|
||||
}
|
||||
|
||||
void futex_hash_get(struct futex_hash_bucket *hb) { }
|
||||
void futex_hash_put(struct futex_hash_bucket *hb) { }
|
||||
|
||||
/**
|
||||
* futex_setup_timer - set up the sleeping hrtimer.
|
||||
|
|
@ -957,9 +959,7 @@ static void exit_pi_state_list(struct task_struct *curr)
|
|||
pi_state = list_entry(next, struct futex_pi_state, list);
|
||||
key = pi_state->key;
|
||||
if (1) {
|
||||
struct futex_hash_bucket *hb;
|
||||
|
||||
hb = futex_hash(&key);
|
||||
CLASS(hb, hb)(&key);
|
||||
|
||||
/*
|
||||
* We can race against put_pi_state() removing itself from the
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/sched/wake_q.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/cleanup.h>
|
||||
|
||||
#ifdef CONFIG_PREEMPT_RT
|
||||
#include <linux/rcuwait.h>
|
||||
|
|
@ -202,6 +203,12 @@ futex_setup_timer(ktime_t *time, struct hrtimer_sleeper *timeout,
|
|||
int flags, u64 range_ns);
|
||||
|
||||
extern struct futex_hash_bucket *futex_hash(union futex_key *key);
|
||||
extern void futex_hash_get(struct futex_hash_bucket *hb);
|
||||
extern void futex_hash_put(struct futex_hash_bucket *hb);
|
||||
|
||||
DEFINE_CLASS(hb, struct futex_hash_bucket *,
|
||||
if (_T) futex_hash_put(_T),
|
||||
futex_hash(key), union futex_key *key);
|
||||
|
||||
/**
|
||||
* futex_match - Check whether two futex keys are equal
|
||||
|
|
|
|||
|
|
@ -939,9 +939,8 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl
|
|||
|
||||
retry_private:
|
||||
if (1) {
|
||||
struct futex_hash_bucket *hb;
|
||||
CLASS(hb, hb)(&q.key);
|
||||
|
||||
hb = futex_hash(&q.key);
|
||||
futex_q_lock(&q, hb);
|
||||
|
||||
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
|
|||
goto no_block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Caution; releasing @hb in-scope. The hb->lock is still locked
|
||||
* while the reference is dropped. The reference can not be dropped
|
||||
* after the unlock because if a user initiated resize is in progress
|
||||
* then we might need to wake him. This can not be done after the
|
||||
* rt_mutex_pre_schedule() invocation. The hb will remain valid because
|
||||
* the thread, performing resize, will block on hb->lock during
|
||||
* the requeue.
|
||||
*/
|
||||
futex_hash_put(no_free_ptr(hb));
|
||||
/*
|
||||
* Must be done before we enqueue the waiter, here is unfortunately
|
||||
* 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)
|
|||
{
|
||||
u32 curval, uval, vpid = task_pid_vnr(current);
|
||||
union futex_key key = FUTEX_KEY_INIT;
|
||||
struct futex_hash_bucket *hb;
|
||||
struct futex_q *top_waiter;
|
||||
int ret;
|
||||
|
||||
|
|
@ -1139,7 +1147,7 @@ int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
hb = futex_hash(&key);
|
||||
CLASS(hb, hb)(&key);
|
||||
spin_lock(&hb->lock);
|
||||
retry_hb:
|
||||
|
||||
|
|
|
|||
|
|
@ -444,10 +444,8 @@ int futex_requeue(u32 __user *uaddr1, unsigned int flags1,
|
|||
|
||||
retry_private:
|
||||
if (1) {
|
||||
struct futex_hash_bucket *hb1, *hb2;
|
||||
|
||||
hb1 = futex_hash(&key1);
|
||||
hb2 = futex_hash(&key2);
|
||||
CLASS(hb, hb1)(&key1);
|
||||
CLASS(hb, hb2)(&key2);
|
||||
|
||||
futex_hb_waiters_inc(hb2);
|
||||
double_lock_hb(hb1, hb2);
|
||||
|
|
@ -817,9 +815,7 @@ int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
|
|||
switch (futex_requeue_pi_wakeup_sync(&q)) {
|
||||
case Q_REQUEUE_PI_IGNORE:
|
||||
{
|
||||
struct futex_hash_bucket *hb;
|
||||
|
||||
hb = futex_hash(&q.key);
|
||||
CLASS(hb, hb)(&q.key);
|
||||
/* The waiter is still on uaddr1 */
|
||||
spin_lock(&hb->lock);
|
||||
ret = handle_early_requeue_pi_wakeup(hb, &q, to);
|
||||
|
|
|
|||
|
|
@ -154,7 +154,6 @@ void futex_wake_mark(struct wake_q_head *wake_q, struct futex_q *q)
|
|||
*/
|
||||
int futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
|
||||
{
|
||||
struct futex_hash_bucket *hb;
|
||||
struct futex_q *this, *next;
|
||||
union futex_key key = FUTEX_KEY_INIT;
|
||||
DEFINE_WAKE_Q(wake_q);
|
||||
|
|
@ -170,7 +169,7 @@ int futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
|
|||
if ((flags & FLAGS_STRICT) && !nr_wake)
|
||||
return 0;
|
||||
|
||||
hb = futex_hash(&key);
|
||||
CLASS(hb, hb)(&key);
|
||||
|
||||
/* Make sure we really have tasks to wakeup */
|
||||
if (!futex_hb_waiters_pending(hb))
|
||||
|
|
@ -267,10 +266,8 @@ int futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
|
|||
|
||||
retry_private:
|
||||
if (1) {
|
||||
struct futex_hash_bucket *hb1, *hb2;
|
||||
|
||||
hb1 = futex_hash(&key1);
|
||||
hb2 = futex_hash(&key2);
|
||||
CLASS(hb, hb1)(&key1);
|
||||
CLASS(hb, hb2)(&key2);
|
||||
|
||||
double_lock_hb(hb1, hb2);
|
||||
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)
|
|||
u32 val = vs[i].w.val;
|
||||
|
||||
if (1) {
|
||||
struct futex_hash_bucket *hb;
|
||||
CLASS(hb, hb)(&q->key);
|
||||
|
||||
hb = futex_hash(&q->key);
|
||||
futex_q_lock(q, hb);
|
||||
ret = futex_get_value_locked(&uval, uaddr);
|
||||
|
||||
|
|
@ -618,9 +614,8 @@ int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
|
|||
|
||||
retry_private:
|
||||
if (1) {
|
||||
struct futex_hash_bucket *hb;
|
||||
CLASS(hb, hb)(&q->key);
|
||||
|
||||
hb = futex_hash(&q->key);
|
||||
futex_q_lock(q, hb);
|
||||
|
||||
ret = futex_get_value_locked(&uval, uaddr);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user