lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251117185550.365156-4-kprateek.nayak@amd.com>
Date: Mon, 17 Nov 2025 18:55:48 +0000
From: K Prateek Nayak <kprateek.nayak@....com>
To: Ingo Molnar <mingo@...hat.com>, Peter Zijlstra <peterz@...radead.org>,
	Juri Lelli <juri.lelli@...hat.com>, Vincent Guittot
	<vincent.guittot@...aro.org>, John Stultz <jstultz@...gle.com>, "Johannes
 Weiner" <hannes@...xchg.org>, Suren Baghdasaryan <surenb@...gle.com>,
	<linux-kernel@...r.kernel.org>
CC: Dietmar Eggemann <dietmar.eggemann@....com>, Steven Rostedt
	<rostedt@...dmis.org>, Ben Segall <bsegall@...gle.com>, Mel Gorman
	<mgorman@...e.de>, Valentin Schneider <vschneid@...hat.com>, K Prateek Nayak
	<kprateek.nayak@....com>
Subject: [RFC PATCH 3/5] sched/core: Track blocked tasks retained on rq for proxy

Track blocked task retained on runqueue to act as a proxy donor. This is
necessary since task's "blocked_on" relationship can be cleared without
holding the task_rq lock and a blocked donor can be forced to run on CPU
before a wakeup since task_is_blocked() returns false at the time of pick.

This is necessary for to fix a PSI task state corruption observed with
CONFIG_SCHED_PROXY_EXEC=y but it also serves as a medium to track the
lifecycle of proxy donor when it is retained on the rq for proxy.

Signed-off-by: K Prateek Nayak <kprateek.nayak@....com>
---
 include/linux/sched.h |  4 ++++
 kernel/sched/core.c   | 32 +++++++++++++++++++++++++++++++-
 kernel/sched/sched.h  |  2 ++
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index bb436ee1942d..f96ad1ec680b 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -978,6 +978,10 @@ struct task_struct {
 	unsigned			sched_contributes_to_load:1;
 	unsigned			sched_migrated:1;
 	unsigned			sched_task_hot:1;
+#ifdef CONFIG_SCHED_PROXY_EXEC
+	/* To indicate blocked task was retained on the rq for proxy. */
+	unsigned			sched_proxy:1;
+#endif
 
 	/* Force alignment to the next boundary: */
 	unsigned			:0;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 9f10cfbdc228..52a744beeca9 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -3659,6 +3659,9 @@ ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags,
 	}
 }
 
+static inline void set_task_proxy(struct task_struct *p);
+static inline void clear_task_proxy(struct task_struct *p);
+
 /*
  * Consider @p being inside a wait loop:
  *
@@ -3693,6 +3696,8 @@ static int ttwu_runnable(struct task_struct *p, int wake_flags)
 	rq = __task_rq_lock(p, &rf);
 	if (task_on_rq_queued(p)) {
 		update_rq_clock(rq);
+		if (is_proxy_task(p))
+			clear_task_proxy(p);
 		if (p->se.sched_delayed)
 			enqueue_task(rq, p, ENQUEUE_NOCLOCK | ENQUEUE_DELAYED);
 		if (!task_on_cpu(rq, p)) {
@@ -6460,8 +6465,10 @@ static bool try_to_block_task(struct rq *rq, struct task_struct *p,
 	 * blocked on a mutex, and we want to keep it on the runqueue
 	 * to be selectable for proxy-execution.
 	 */
-	if (!should_block)
+	if (!should_block) {
+		set_task_proxy(p);
 		return false;
+	}
 
 	p->sched_contributes_to_load =
 		(task_state & TASK_UNINTERRUPTIBLE) &&
@@ -6487,6 +6494,23 @@ static bool try_to_block_task(struct rq *rq, struct task_struct *p,
 }
 
 #ifdef CONFIG_SCHED_PROXY_EXEC
+bool is_proxy_task(struct task_struct *p)
+{
+	return !!p->sched_proxy;
+}
+
+static inline void set_task_proxy(struct task_struct *p)
+{
+	WARN_ON_ONCE(p->sched_proxy);
+	p->sched_proxy = 1;
+}
+
+static inline void clear_task_proxy(struct task_struct *p)
+{
+	WARN_ON_ONCE(!p->sched_proxy);
+	p->sched_proxy = 0;
+}
+
 static inline struct task_struct *proxy_resched_idle(struct rq *rq)
 {
 	put_prev_set_next_task(rq, rq->donor, rq->idle);
@@ -6502,6 +6526,9 @@ static bool __proxy_deactivate(struct rq *rq, struct task_struct *donor)
 	/* Don't deactivate if the state has been changed to TASK_RUNNING */
 	if (state == TASK_RUNNING)
 		return false;
+
+	clear_task_proxy(donor);
+
 	/*
 	 * Because we got donor from pick_next_task(), it is *crucial*
 	 * that we call proxy_resched_idle() before we deactivate it.
@@ -6649,6 +6676,9 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf)
 	return owner;
 }
 #else /* SCHED_PROXY_EXEC */
+bool is_proxy_task(struct task_struct *p) { return false; }
+static inline void set_task_proxy(struct task_struct *p) { }
+static inline void clear_task_proxy(p) { }
 static struct task_struct *
 find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf)
 {
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index b419a4d98461..fa2a2d5bff6d 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1362,6 +1362,8 @@ static inline u32 sched_rng(void)
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 #define raw_rq()		raw_cpu_ptr(&runqueues)
 
+bool is_proxy_task(struct task_struct *p);
+
 #ifdef CONFIG_SCHED_PROXY_EXEC
 static inline void rq_set_donor(struct rq *rq, struct task_struct *t)
 {
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ