|
Davidlohr Bueso |
5c8ef6 |
From 340576590dac4bb58d532a8ad5bfa806d8ab473c Mon Sep 17 00:00:00 2001
|
|
Davidlohr Bueso |
5c8ef6 |
From: Thomas Gleixner <tglx@linutronix.de>
|
|
Davidlohr Bueso |
5c8ef6 |
Date: Thu, 2 Sep 2021 11:48:51 +0200
|
|
Davidlohr Bueso |
5c8ef6 |
Subject: [PATCH] futex: Avoid redundant task lookup
|
|
Davidlohr Bueso |
5c8ef6 |
Git-commit: 340576590dac4bb58d532a8ad5bfa806d8ab473c
|
|
Davidlohr Bueso |
5c8ef6 |
Patch-mainline: v5.15-rc1
|
|
Davidlohr Bueso |
5c8ef6 |
References: bsc#1190137 bsc#1189998
|
|
Davidlohr Bueso |
5c8ef6 |
|
|
Davidlohr Bueso |
5c8ef6 |
No need to do the full VPID based task lookup and validation of the top
|
|
Davidlohr Bueso |
5c8ef6 |
waiter when the user space futex was acquired on it's behalf during the
|
|
Davidlohr Bueso |
5c8ef6 |
requeue_pi operation. The task is known already and it cannot go away
|
|
Davidlohr Bueso |
5c8ef6 |
before requeue_pi_wake_futex() has been invoked.
|
|
Davidlohr Bueso |
5c8ef6 |
|
|
Davidlohr Bueso |
5c8ef6 |
Split out the actual attach code from attach_pi_state_owner() and use that
|
|
Davidlohr Bueso |
5c8ef6 |
instead of the full blown variant.
|
|
Davidlohr Bueso |
5c8ef6 |
|
|
Davidlohr Bueso |
5c8ef6 |
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
Davidlohr Bueso |
5c8ef6 |
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
|
|
Davidlohr Bueso |
5c8ef6 |
Link: https://lore.kernel.org/r/20210902094414.676104881@linutronix.de
|
|
Davidlohr Bueso |
5c8ef6 |
Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
|
|
Davidlohr Bueso |
5c8ef6 |
|
|
Davidlohr Bueso |
5c8ef6 |
---
|
|
Davidlohr Bueso |
5c8ef6 |
kernel/futex.c | 67 ++++++++++++++++++++++++++++----------------------
|
|
Davidlohr Bueso |
5c8ef6 |
1 file changed, 37 insertions(+), 30 deletions(-)
|
|
Davidlohr Bueso |
5c8ef6 |
|
|
Davidlohr Bueso |
5c8ef6 |
diff --git a/kernel/futex.c b/kernel/futex.c
|
|
Davidlohr Bueso |
5c8ef6 |
index 82cd270f25a0..a316dce74c3d 100644
|
|
Davidlohr Bueso |
5c8ef6 |
--- a/kernel/futex.c
|
|
Davidlohr Bueso |
5c8ef6 |
+++ b/kernel/futex.c
|
|
Davidlohr Bueso |
5c8ef6 |
@@ -1263,6 +1263,36 @@ static int handle_exit_race(u32 __user *uaddr, u32 uval,
|
|
Davidlohr Bueso |
5c8ef6 |
return -ESRCH;
|
|
Davidlohr Bueso |
5c8ef6 |
}
|
|
Davidlohr Bueso |
5c8ef6 |
|
|
Davidlohr Bueso |
5c8ef6 |
+static void __attach_to_pi_owner(struct task_struct *p, union futex_key *key,
|
|
Davidlohr Bueso |
5c8ef6 |
+ struct futex_pi_state **ps)
|
|
Davidlohr Bueso |
5c8ef6 |
+{
|
|
Davidlohr Bueso |
5c8ef6 |
+ /*
|
|
Davidlohr Bueso |
5c8ef6 |
+ * No existing pi state. First waiter. [2]
|
|
Davidlohr Bueso |
5c8ef6 |
+ *
|
|
Davidlohr Bueso |
5c8ef6 |
+ * This creates pi_state, we have hb->lock held, this means nothing can
|
|
Davidlohr Bueso |
5c8ef6 |
+ * observe this state, wait_lock is irrelevant.
|
|
Davidlohr Bueso |
5c8ef6 |
+ */
|
|
Davidlohr Bueso |
5c8ef6 |
+ struct futex_pi_state *pi_state = alloc_pi_state();
|
|
Davidlohr Bueso |
5c8ef6 |
+
|
|
Davidlohr Bueso |
5c8ef6 |
+ /*
|
|
Davidlohr Bueso |
5c8ef6 |
+ * Initialize the pi_mutex in locked state and make @p
|
|
Davidlohr Bueso |
5c8ef6 |
+ * the owner of it:
|
|
Davidlohr Bueso |
5c8ef6 |
+ */
|
|
Davidlohr Bueso |
5c8ef6 |
+ rt_mutex_init_proxy_locked(&pi_state->pi_mutex, p);
|
|
Davidlohr Bueso |
5c8ef6 |
+
|
|
Davidlohr Bueso |
5c8ef6 |
+ /* Store the key for possible exit cleanups: */
|
|
Davidlohr Bueso |
5c8ef6 |
+ pi_state->key = *key;
|
|
Davidlohr Bueso |
5c8ef6 |
+
|
|
Davidlohr Bueso |
5c8ef6 |
+ WARN_ON(!list_empty(&pi_state->list));
|
|
Davidlohr Bueso |
5c8ef6 |
+ list_add(&pi_state->list, &p->pi_state_list);
|
|
Davidlohr Bueso |
5c8ef6 |
+ /*
|
|
Davidlohr Bueso |
5c8ef6 |
+ * Assignment without holding pi_state->pi_mutex.wait_lock is safe
|
|
Davidlohr Bueso |
5c8ef6 |
+ * because there is no concurrency as the object is not published yet.
|
|
Davidlohr Bueso |
5c8ef6 |
+ */
|
|
Davidlohr Bueso |
5c8ef6 |
+ pi_state->owner = p;
|
|
Davidlohr Bueso |
5c8ef6 |
+
|
|
Davidlohr Bueso |
5c8ef6 |
+ *ps = pi_state;
|
|
Davidlohr Bueso |
5c8ef6 |
+}
|
|
Davidlohr Bueso |
5c8ef6 |
/*
|
|
Davidlohr Bueso |
5c8ef6 |
* Lookup the task for the TID provided from user space and attach to
|
|
Davidlohr Bueso |
5c8ef6 |
* it after doing proper sanity checks.
|
|
Davidlohr Bueso |
5c8ef6 |
@@ -1272,7 +1302,6 @@ static int attach_to_pi_owner(u32 __user *uaddr, u32 uval, union futex_key *key,
|
|
Davidlohr Bueso |
5c8ef6 |
struct task_struct **exiting)
|
|
Davidlohr Bueso |
5c8ef6 |
{
|
|
Davidlohr Bueso |
5c8ef6 |
pid_t pid = uval & FUTEX_TID_MASK;
|
|
Davidlohr Bueso |
5c8ef6 |
- struct futex_pi_state *pi_state;
|
|
Davidlohr Bueso |
5c8ef6 |
struct task_struct *p;
|
|
Davidlohr Bueso |
5c8ef6 |
|
|
Davidlohr Bueso |
5c8ef6 |
/*
|
|
Davidlohr Bueso |
5c8ef6 |
@@ -1324,36 +1353,11 @@ static int attach_to_pi_owner(u32 __user *uaddr, u32 uval, union futex_key *key,
|
|
Davidlohr Bueso |
5c8ef6 |
return ret;
|
|
Davidlohr Bueso |
5c8ef6 |
}
|
|
Davidlohr Bueso |
5c8ef6 |
|
|
Davidlohr Bueso |
5c8ef6 |
- /*
|
|
Davidlohr Bueso |
5c8ef6 |
- * No existing pi state. First waiter. [2]
|
|
Davidlohr Bueso |
5c8ef6 |
- *
|
|
Davidlohr Bueso |
5c8ef6 |
- * This creates pi_state, we have hb->lock held, this means nothing can
|
|
Davidlohr Bueso |
5c8ef6 |
- * observe this state, wait_lock is irrelevant.
|
|
Davidlohr Bueso |
5c8ef6 |
- */
|
|
Davidlohr Bueso |
5c8ef6 |
- pi_state = alloc_pi_state();
|
|
Davidlohr Bueso |
5c8ef6 |
-
|
|
Davidlohr Bueso |
5c8ef6 |
- /*
|
|
Davidlohr Bueso |
5c8ef6 |
- * Initialize the pi_mutex in locked state and make @p
|
|
Davidlohr Bueso |
5c8ef6 |
- * the owner of it:
|
|
Davidlohr Bueso |
5c8ef6 |
- */
|
|
Davidlohr Bueso |
5c8ef6 |
- rt_mutex_init_proxy_locked(&pi_state->pi_mutex, p);
|
|
Davidlohr Bueso |
5c8ef6 |
-
|
|
Davidlohr Bueso |
5c8ef6 |
- /* Store the key for possible exit cleanups: */
|
|
Davidlohr Bueso |
5c8ef6 |
- pi_state->key = *key;
|
|
Davidlohr Bueso |
5c8ef6 |
-
|
|
Davidlohr Bueso |
5c8ef6 |
- WARN_ON(!list_empty(&pi_state->list));
|
|
Davidlohr Bueso |
5c8ef6 |
- list_add(&pi_state->list, &p->pi_state_list);
|
|
Davidlohr Bueso |
5c8ef6 |
- /*
|
|
Davidlohr Bueso |
5c8ef6 |
- * Assignment without holding pi_state->pi_mutex.wait_lock is safe
|
|
Davidlohr Bueso |
5c8ef6 |
- * because there is no concurrency as the object is not published yet.
|
|
Davidlohr Bueso |
5c8ef6 |
- */
|
|
Davidlohr Bueso |
5c8ef6 |
- pi_state->owner = p;
|
|
Davidlohr Bueso |
5c8ef6 |
+ __attach_to_pi_owner(p, key, ps);
|
|
Davidlohr Bueso |
5c8ef6 |
raw_spin_unlock_irq(&p->pi_lock);
|
|
Davidlohr Bueso |
5c8ef6 |
|
|
Davidlohr Bueso |
5c8ef6 |
put_task_struct(p);
|
|
Davidlohr Bueso |
5c8ef6 |
|
|
Davidlohr Bueso |
5c8ef6 |
- *ps = pi_state;
|
|
Davidlohr Bueso |
5c8ef6 |
-
|
|
Davidlohr Bueso |
5c8ef6 |
return 0;
|
|
Davidlohr Bueso |
5c8ef6 |
}
|
|
Davidlohr Bueso |
5c8ef6 |
|
|
Davidlohr Bueso |
5c8ef6 |
@@ -1464,11 +1468,14 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
|
|
Davidlohr Bueso |
5c8ef6 |
* @task is guaranteed to be alive and it cannot be exiting
|
|
Davidlohr Bueso |
5c8ef6 |
* because it is either sleeping or waiting in
|
|
Davidlohr Bueso |
5c8ef6 |
* futex_requeue_pi_wakeup_sync().
|
|
Davidlohr Bueso |
5c8ef6 |
+ *
|
|
Davidlohr Bueso |
5c8ef6 |
+ * No need to do the full attach_to_pi_owner() exercise
|
|
Davidlohr Bueso |
5c8ef6 |
+ * because @task is known and valid.
|
|
Davidlohr Bueso |
5c8ef6 |
*/
|
|
Davidlohr Bueso |
5c8ef6 |
if (set_waiters) {
|
|
Davidlohr Bueso |
5c8ef6 |
- ret = attach_to_pi_owner(uaddr, newval, key, ps,
|
|
Davidlohr Bueso |
5c8ef6 |
- exiting);
|
|
Davidlohr Bueso |
5c8ef6 |
- WARN_ON(ret);
|
|
Davidlohr Bueso |
5c8ef6 |
+ raw_spin_lock_irq(&task->pi_lock);
|
|
Davidlohr Bueso |
5c8ef6 |
+ __attach_to_pi_owner(task, key, ps);
|
|
Davidlohr Bueso |
5c8ef6 |
+ raw_spin_unlock_irq(&task->pi_lock);
|
|
Davidlohr Bueso |
5c8ef6 |
}
|
|
Davidlohr Bueso |
5c8ef6 |
return 1;
|
|
Davidlohr Bueso |
5c8ef6 |
}
|
|
Davidlohr Bueso |
5c8ef6 |
--
|
|
Davidlohr Bueso |
5c8ef6 |
2.26.2
|
|
Davidlohr Bueso |
5c8ef6 |
|