[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250123202446.610203-12-bigeasy@linutronix.de>
Date: Thu, 23 Jan 2025 21:24:41 +0100
From: Sebastian Andrzej Siewior <bigeasy@...utronix.de>
To: linux-kernel@...r.kernel.org
Cc: André Almeida <andrealmeid@...lia.com>,
Darren Hart <dvhart@...radead.org>,
Davidlohr Bueso <dave@...olabs.net>,
Ingo Molnar <mingo@...hat.com>,
Juri Lelli <juri.lelli@...hat.com>,
Peter Zijlstra <peterz@...radead.org>,
Thomas Gleixner <tglx@...utronix.de>,
Valentin Schneider <vschneid@...hat.com>,
Waiman Long <longman@...hat.com>,
Sebastian Andrzej Siewior <bigeasy@...utronix.de>
Subject: [PATCH v7 11/15] futex: Acquire a hash reference in futex_wait_multiple_setup().
futex_wait_multiple_setup() changes task_struct::__state to
!TASK_RUNNING and then enqueues on multiple futexes. Every
futex_q_lock() acquires a reference on the global hash which is dropped
later.
If a rehash is in progress then the loop will block on
mm_struct::futex_hash_bucket for the rehash to complete and this will
lose the previously set task_struct::__state.
Acquire a reference on the local hash to avoiding blocking on
mm_struct::futex_hash_bucket.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@...utronix.de>
---
kernel/futex/core.c | 10 ++++++++++
kernel/futex/futex.h | 2 ++
kernel/futex/waitwake.c | 21 +++++++++++++++++++--
3 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index b0fb2b10a387c..7130019aa9ec6 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -129,6 +129,11 @@ static struct futex_hash_bucket *futex_hash_private(union futex_key *key,
return &fhb[hash & hash_mask];
}
+struct futex_private_hash *futex_get_private_hash(void)
+{
+ return NULL;
+}
+
/**
* futex_hash - Return the hash bucket in the global or local hash
* @key: Pointer to the futex key for which the hash is calculated
@@ -152,6 +157,11 @@ struct futex_hash_bucket *futex_hash(union futex_key *key)
return &futex_queues[hash & (futex_hashsize - 1)];
}
+bool futex_put_private_hash(struct futex_private_hash *hb_p)
+{
+ return false;
+}
+
void futex_hash_put(struct futex_hash_bucket *hb)
{
}
diff --git a/kernel/futex/futex.h b/kernel/futex/futex.h
index 5b33016648ecd..d6fa6f663d9ad 100644
--- a/kernel/futex/futex.h
+++ b/kernel/futex/futex.h
@@ -205,6 +205,8 @@ futex_setup_timer(ktime_t *time, struct hrtimer_sleeper *timeout,
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);
+extern struct futex_private_hash *futex_get_private_hash(void);
+extern bool futex_put_private_hash(struct futex_private_hash *hb_p);
/**
* futex_match - Check whether two futex keys are equal
diff --git a/kernel/futex/waitwake.c b/kernel/futex/waitwake.c
index 03e2f546967d8..419af848deadb 100644
--- a/kernel/futex/waitwake.c
+++ b/kernel/futex/waitwake.c
@@ -396,7 +396,7 @@ int futex_unqueue_multiple(struct futex_vector *v, int count)
}
/**
- * futex_wait_multiple_setup - Prepare to wait and enqueue multiple futexes
+ * __futex_wait_multiple_setup - Prepare to wait and enqueue multiple futexes
* @vs: The futex list to wait on
* @count: The size of the list
* @woken: Index of the last woken futex, if any. Used to notify the
@@ -411,7 +411,7 @@ int futex_unqueue_multiple(struct futex_vector *v, int count)
* - 0 - Success
* - <0 - -EFAULT, -EWOULDBLOCK or -EINVAL
*/
-int futex_wait_multiple_setup(struct futex_vector *vs, int count, int *woken)
+static int __futex_wait_multiple_setup(struct futex_vector *vs, int count, int *woken)
{
struct futex_hash_bucket *hb;
bool retry = false;
@@ -500,6 +500,23 @@ int futex_wait_multiple_setup(struct futex_vector *vs, int count, int *woken)
return 0;
}
+int futex_wait_multiple_setup(struct futex_vector *vs, int count, int *woken)
+{
+ struct futex_private_hash *hb_p;
+ int ret;
+
+ /*
+ * Assume to have a private futex and acquire a reference on the private
+ * hash to avoid blocking on mm_struct::futex_hash_bucket during rehash
+ * after changing the task state.
+ */
+ hb_p = futex_get_private_hash();
+ ret = __futex_wait_multiple_setup(vs, count, woken);
+ if (hb_p)
+ futex_put_private_hash(hb_p);
+ return ret;
+}
+
/**
* futex_sleep_multiple - Check sleeping conditions and sleep
* @vs: List of futexes to wait for
--
2.47.2
Powered by blists - more mailing lists