mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Andrea Righi <arighi@nvidia.com>
To: Tejun Heo <tj@kernel.org>, David Vernet <void@manifault.com>,
	Changwoo Min <changwoo@igalia.com>
Cc: John Stultz <jstultz@google.com>,
	sched-ext@lists.linux.dev, linux-kernel@vger.kernel.org
Subject: [PATCH sched_ext/for-7.4] sched_ext: Keep proxy donors local through core-sched retries
Date: Thu, 15 Oct 2026 12:19:35 +0200	[thread overview]
Message-ID: <20261015101935.2844323-1-arighi@nvidia.com> (raw)

An abandoned blocked-donor pick can leave SCX_RQ_PROXY_PENDING set if
the next core-sched pick selects a higher-priority class without calling
pick_task_scx(). A cookie mismatch can then force the CPU idle, while
put_prev_task_scx() mistakes the stale flag for a proxy bookkeeping put.

A valid proxy put of an IMMED donor also schedules a local reenqueue
scan. If an SCX task wakes before the scan runs, rq->next_class becomes
ext again and rq_is_open() reports the CPU closed. The scan then sends
the parked donor back to BPF even though it is first on the local DSQ
and the CPU is switching to idle.

Require the donor's cookie to match before treating a put as a proxy
put. Mark donors parked by a proxy put in dsq_flags, clear the mark
when they leave the DSQ, and let rq_is_open() recognize a matching
marked donor at the head of the local DSQ while the rq donor is idle.

Fixes: 7ab553756463 ("sched_ext: Keep proxy donors with slice left on the local DSQ")
Reported-by: Tejun Heo <tj@kernel.org>
Link: https://lore.kernel.org/r/atCQB_nF5di8pgUN@gpd4
Signed-off-by: Andrea Righi <arighi@nvidia.com>
---
 include/linux/sched/ext.h |  1 +
 kernel/sched/ext/ext.c    | 28 +++++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/include/linux/sched/ext.h b/include/linux/sched/ext.h
index ae696d11dac9a..4267304823cf4 100644
--- a/include/linux/sched/ext.h
+++ b/include/linux/sched/ext.h
@@ -157,6 +157,7 @@ enum scx_ent_flags {
 /* scx_entity.dsq_flags */
 enum scx_ent_dsq_flags {
 	SCX_TASK_DSQ_ON_PRIQ	= 1 << 0, /* task is queued on the priority queue of a dsq */
+	SCX_TASK_DSQ_PROXY_IDLE	= 1 << 1, /* proxy donor parked through idle */
 };
 
 enum scx_dsq_lnode_flags {
diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
index 4fa294f810f4b..2465e792db2fb 100644
--- a/kernel/sched/ext/ext.c
+++ b/kernel/sched/ext/ext.c
@@ -437,6 +437,23 @@ static bool rq_is_open(struct rq *rq, u64 enq_flags)
 	if (sched_class_above(&ext_sched_class, rq->next_class))
 		return true;
 
+	/*
+	 * proxy_resched_idle() can put a blocked donor at the head of the local
+	 * DSQ and switch @rq's donor to idle. An SCX wakeup then raises
+	 * next_class to ext before the pending IMMED reenq scan runs. If the
+	 * first task was parked by that proxy put and its cookie can run here,
+	 * leave it local for the next pick instead of sending it back to BPF.
+	 */
+	if (rq->donor == rq->idle) {
+		struct task_struct *first;
+
+		first = list_first_entry_or_null(&rq->scx.local_dsq.list,
+						 struct task_struct, scx.dsq_list.node);
+		if (first && (first->scx.dsq_flags & SCX_TASK_DSQ_PROXY_IDLE) &&
+		    sched_cpu_cookie_match(rq, first))
+			return true;
+	}
+
 	/*
 	 * @rq is either picking, in transition to, or running an SCX task.
 	 */
@@ -1608,6 +1625,7 @@ static void dsq_dec_nr(struct scx_dispatch_q *dsq, struct task_struct *p)
 {
 	/* see dsq_inc_nr() */
 	WRITE_ONCE(dsq->nr, dsq->nr - 1);
+	p->scx.dsq_flags &= ~SCX_TASK_DSQ_PROXY_IDLE;
 
 	if (p->scx.flags & SCX_TASK_IMMED) {
 		struct rq *rq = container_of(dsq, struct rq, scx.local_dsq);
@@ -3521,12 +3539,18 @@ static void switch_class(struct rq *rq, struct task_struct *next)
 	}
 }
 
+/*
+ * A proxy retry can bypass pick_task_scx() and leave PROXY_PENDING set.
+ * A cookie mismatch means core scheduling forced this CPU idle, not that
+ * proxy resolution put a selected donor through idle.
+ */
 static void put_prev_task_scx(struct rq *rq, struct task_struct *p,
 			      struct task_struct *next)
 {
 	struct scx_sched *sch = scx_task_sched(p);
 	bool proxy_put = p->is_blocked && next == rq->idle &&
-			 (rq->scx.flags & SCX_RQ_PROXY_PENDING);
+			 (rq->scx.flags & SCX_RQ_PROXY_PENDING) &&
+			 sched_cpu_cookie_match(rq, p);
 	bool proxy_block = rq->scx.flags & SCX_RQ_PROXY_BLOCKING;
 	bool rescue_keep = false;
 
@@ -3612,6 +3636,8 @@ static void put_prev_task_scx(struct rq *rq, struct task_struct *p,
 						enq_flags |= SCX_ENQ_IMMED;
 				}
 
+				if (proxy_put)
+					p->scx.dsq_flags |= SCX_TASK_DSQ_PROXY_IDLE;
 				scx_dispatch_enqueue(sch, rq, &rq->scx.local_dsq, p, 0, 0,
 						     enq_flags);
 			}
-- 
2.56.0


                 reply	other threads:[~2026-10-15 10:19 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20261015101935.2844323-1-arighi@nvidia.com \
    --to=arighi@nvidia.com \
    --cc=changwoo@igalia.com \
    --cc=jstultz@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sched-ext@lists.linux.dev \
    --cc=tj@kernel.org \
    --cc=void@manifault.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®