[<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