summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2026-07-21 11:25:14 -1000
committerTejun Heo <tj@kernel.org>2026-07-21 22:26:57 -1000
commit2c91169377f44e2f2b0b79bc0365f0722987a650 (patch)
treee56c90d553cc2cbec7dca2549c511598d8f61a88
parentb20dfde5ec543597f7f178f7b96cf6ebcc50e5ee (diff)
sched_ext: Blame the DSQ's owning scheduler for a runnable stall
check_rq_for_timeouts() blames a runnable stall on the task's owner. Under a sub-scheduler hierarchy the stalled task can be sitting on a DSQ that a different scheduler has to drain, e.g. an ancestor's bypass DSQ while the owner is bypassing. The drainer then escapes blame while the owner is exited, and when the owner's exit is already claimed, nothing actionable is reported at all. Blame the DSQ's owning scheduler instead. The local DSQ is consumed by the cpu itself and keeps blame on the owner. Detection keeps the owner's timeout and single-scheduler behavior is unchanged. Reviewed-by: Andrea Righi <arighi@nvidia.com> Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r--kernel/sched/ext/ext.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
index b730eac4b13f..96389ec31ab8 100644
--- a/kernel/sched/ext/ext.c
+++ b/kernel/sched/ext/ext.c
@@ -3391,8 +3391,19 @@ static bool check_rq_for_timeouts(struct rq *rq)
if (unlikely(time_after(jiffies,
last_runnable + READ_ONCE(sch->watchdog_timeout)))) {
+ struct scx_dispatch_q *dsq = READ_ONCE(p->scx.dsq);
u32 dur_ms = jiffies_to_msecs(jiffies - last_runnable);
+ /*
+ * A task can be stuck on a DSQ that a sched other than
+ * its owner is responsible for draining, e.g. an
+ * ancestor's bypass DSQ while the owner is bypassing.
+ * Blame the drainer. The local DSQ is consumed by the
+ * cpu itself and keeps blame on the owner.
+ */
+ if (dsq && dsq->sched && dsq->id != SCX_DSQ_LOCAL)
+ sch = dsq->sched;
+
__scx_exit(sch, SCX_EXIT_ERROR_STALL, 0, cpu_of(rq),
"%s[%d] failed to run for %u.%03us",
p->comm, p->pid, dur_ms / 1000,