From: Suleiman Souhlal <suleiman@google.com>
To: linux-kernel@vger.kernel.org
Cc: "Suleiman Souhlal" <suleiman@google.com>,
"Thomas Gleixner" <tglx@kernel.org>,
"Ingo Molnar" <mingo@redhat.com>,
"Peter Zijlstra" <peterz@infradead.org>,
"Darren Hart" <dvhart@infradead.org>,
"Davidlohr Bueso" <dave@stgolabs.net>,
"André Almeida" <andrealmeid@igalia.com>,
"Juri Lelli" <juri.lelli@redhat.com>,
"Vincent Guittot" <vincent.guittot@linaro.org>,
"Dietmar Eggemann" <dietmar.eggemann@arm.com>,
"Steven Rostedt" <rostedt@goodmis.org>,
"Ben Segall" <bsegall@google.com>, "Mel Gorman" <mgorman@suse.de>,
"Valentin Schneider" <vschneid@redhat.com>,
"K Prateek Nayak" <kprateek.nayak@amd.com>,
"zhidao su" <soolaugust@gmail.com>,
"John Stultz" <jstultz@google.com>,
"Qais Yousef" <qyousef@google.com>,
ssouhlal@FreeBSD.org
Subject: [RFC PATCH 10/12] futex: Optimistic spinning for PING futexes.
Date: Thu, 17 Sep 2026 04:33:34 +0000 [thread overview]
Message-ID: <20260917043339.2093426-11-suleiman@google.com> (raw)
In-Reply-To: <20260917043339.2093426-1-suleiman@google.com>
This allows a thread to spin on the owner of the futex instead of
unconditionally spinning, if the owner is currently running on
another CPU.
TODO: Currently allows every task to attempt to spin at the same time.
In the future, spinning will probably either use an osq or only the
top waiter will be allowed to wait. We've seen some long latencies
when using an osq that we still need to investigate.
Signed-off-by: Suleiman Souhlal <suleiman@google.com>
---
kernel/futex/ping.c | 80 +++++++++++++++++++++++++++++++++++++--------
1 file changed, 67 insertions(+), 13 deletions(-)
diff --git a/kernel/futex/ping.c b/kernel/futex/ping.c
index df701b437f16..e5765b2d3834 100644
--- a/kernel/futex/ping.c
+++ b/kernel/futex/ping.c
@@ -301,6 +301,50 @@ static int futex_lock_ping_atomic(u32 __user *uaddr,
return attach_to_pi_owner(uaddr, newval, key, ps, exiting, true);
}
+/*
+ * Returns >0 on successfully having taken the lock, <0 on error
+ */
+static int ping_spin_or_trylock(u32 __user *uaddr,
+ struct futex_pi_state *ping_state,
+ bool handoff)
+{
+ struct task_struct *owner = ping_mutex_owner(&ping_state->ping_mutex);
+ struct task_struct *new;
+ int ret;
+
+ if (owner && !owner_on_cpu(owner))
+ return 0;
+
+ /*
+ * XXX We'll want to try to limit spinning either with an osq or
+ * by only allowing the top waiter to spin.
+ */
+
+ while (1) {
+ new = ping_mutex_owner(&ping_state->ping_mutex);
+ ret = 0;
+ if (!owner || !new || new == current) {
+ ret = futex_trylock_ping_state(uaddr, ping_state,
+ handoff);
+ if (ret != 0)
+ break;
+ /* Spin on new owner if we didn't get the lock */
+ owner = ping_mutex_owner(&ping_state->ping_mutex);
+ goto next;
+ }
+ if (new != owner) {
+ owner = ping_mutex_owner(&ping_state->ping_mutex);
+ goto next;
+ }
+ if (!owner_on_cpu(owner) || need_resched())
+ break;
+next:
+ cpu_relax();
+ }
+
+ return ret;
+}
+
/*
* Return values:
* < 0: error.
@@ -387,9 +431,6 @@ int futex_lock_ping(u32 __user *uaddr, unsigned int flags, ktime_t *time,
queued = false;
should_handoff = false;
while (1) {
- set_task_blocked_on(current, &q.ping_state->ping_mutex,
- BO_T_PING_FUTEX);
-
set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE);
if (!queued) {
futex_queue(&q, hb, current);
@@ -400,6 +441,26 @@ int futex_lock_ping(u32 __user *uaddr, unsigned int flags, ktime_t *time,
__release(q->lock_ptr);
}
+ preempt_disable();
+ set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE);
+ ret = ping_spin_or_trylock(uaddr, q.ping_state,
+ should_handoff);
+ if (ret > 0) {
+ /* Got the futex */
+ ret = 0;
+ preempt_enable();
+ futex_q_lockptr_lock(&q);
+ goto out_unqueue;
+ } else if (ret < 0) {
+ preempt_enable();
+ futex_q_lockptr_lock(&q);
+ goto out_unqueue;
+ }
+ preempt_enable();
+
+ set_task_blocked_on(current, &q.ping_state->ping_mutex,
+ BO_T_PING_FUTEX);
+
futex_do_wait(&q, to);
clear_task_blocked_on(current,
@@ -414,19 +475,12 @@ int futex_lock_ping(u32 __user *uaddr, unsigned int flags, ktime_t *time,
ret = -EINTR;
goto out_unqueue;
}
-
- ret = futex_trylock_ping_state(uaddr, q.ping_state,
- should_handoff);
- if (ret > 0) {
- /* Got the futex */
- ret = 0;
- goto out_unqueue;
- } else if (ret < 0)
- goto out_unqueue;
should_handoff = true;
}
out_unqueue:
+ __set_current_state(TASK_RUNNING);
+
/*
* We got a pending signal or timeout, but the futex was handed
* off to us. Fix up the return value to indicate success.
@@ -581,7 +635,7 @@ int futex_unlock_ping(u32 __user *uaddr, unsigned int flags)
* no top_waiter.
*/
new = FUTEX_WAITERS;
- if (ping_state->handoff) {
+ if (ping_state->handoff) { /* Don't handoff to donor */
new |= task_pid_vnr(next);
ping_state->handoff = 0;
ping_state->pickup = 1;
--
2.55.0.1082.g2b9226bbc0-goog
next prev parent reply other threads:[~2026-09-17 4:34 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-17 4:33 [RFC PATCH 00/12] FUTEX_PING: A stealable futex using Proxy Execution Suleiman Souhlal
2026-09-17 4:33 ` [RFC PATCH 01/12] sched: Abstract task_struct->blocked_on by locking primitive Suleiman Souhlal
2026-09-17 4:33 ` [RFC PATCH 02/12] futex: Switch PI futex to use p->pi_futex_lock instead of p->pi_lock Suleiman Souhlal
2026-09-17 15:38 ` Peter Zijlstra
2026-09-18 7:11 ` Suleiman Souhlal
2026-09-18 10:07 ` K Prateek Nayak
2026-09-18 12:06 ` Peter Zijlstra
2026-09-17 4:33 ` [RFC PATCH 03/12] futex: Add "ping" parameter to pi_state management functions and export them Suleiman Souhlal
2026-09-17 4:33 ` [RFC PATCH 04/12] futex: Introduce stealable PI futex, FUTEX_*_PING Suleiman Souhlal
2026-09-17 4:33 ` [RFC PATCH 05/12] futex: Implement exit_ping_state_list() Suleiman Souhlal
2026-09-17 4:33 ` [RFC PATCH 06/12] futex: Address aborting from futex_lock_ping() while owning ping_state Suleiman Souhlal
2026-09-17 4:33 ` [RFC PATCH 07/12] futex: Make FUTEX_*_PING use Proxy Execution Suleiman Souhlal
2026-09-17 13:18 ` Jihan LIN
2026-09-17 14:39 ` K Prateek Nayak
2026-09-17 15:36 ` Peter Zijlstra
2026-09-17 4:33 ` [RFC PATCH 08/12] futex: Implement PING futex handoff Suleiman Souhlal
2026-09-17 4:33 ` [RFC PATCH 09/12] futex: Wake up donor in PING futex unlock Suleiman Souhlal
2026-09-17 4:33 ` Suleiman Souhlal [this message]
2026-09-17 4:33 ` [RFC PATCH 11/12] futex: Allow userspace stealing for PING futexes Suleiman Souhlal
2026-09-17 4:33 ` [RFC PATCH 12/12] tools/testing/futex: Add ping_bench, a tool for benchmarking futexes Suleiman Souhlal
2026-09-17 8:58 ` [RFC PATCH 00/12] FUTEX_PING: A stealable futex using Proxy Execution Peter Zijlstra
2026-09-17 17:53 ` John Stultz
2026-09-17 18:51 ` Steven Rostedt
2026-09-18 6:30 ` Suleiman Souhlal
2026-09-18 8:25 ` Peter Zijlstra
2026-09-18 6:07 ` Suleiman Souhlal
2026-09-18 8:07 ` Peter Zijlstra
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260917043339.2093426-11-suleiman@google.com \
--to=suleiman@google.com \
--cc=andrealmeid@igalia.com \
--cc=bsegall@google.com \
--cc=dave@stgolabs.net \
--cc=dietmar.eggemann@arm.com \
--cc=dvhart@infradead.org \
--cc=jstultz@google.com \
--cc=juri.lelli@redhat.com \
--cc=kprateek.nayak@amd.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mgorman@suse.de \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=qyousef@google.com \
--cc=rostedt@goodmis.org \
--cc=soolaugust@gmail.com \
--cc=ssouhlal@FreeBSD.org \
--cc=tglx@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=vschneid@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®