[PATCH v3 13/24] sched/deadline: Leave a dying task out of a rebuild of the accounting
From: Mathieu Desnoyers
Date: Thu Nov 05 2026 - 14:44:41 EST
A rebuild of the root domains' accounting finds the tasks of a cpuset
through css_task_iter, which hides an exiting task once its process has
no live thread left, and hides a dying thread of a process with live
threads only once cgroup_task_dead() takes it off the cpuset, after its
last schedule. The walk without cpusets finds every task. Either can
find a task at its last schedule, between the release of its bandwidth
there, task_non_contending() past its 0-lag time, and the reset of its
dl_bw: both run under the runqueue lock, which the walk does not take.
The walk then counts, in a root domain the rebuild has just cleared, a
bandwidth that nothing releases again.
Leave out a dead task that is not on the departed list: its bandwidth
is released, or being released. do_task_dead() sets TASK_DEAD under
pi_lock, which the walk holds, so a task found alive dies after the
walk, and releases what the walk counted. A dead task on the list keeps
its bandwidth until its timer, and the rebuild counts it where the list
says, as before.
Found by the Sashiko AI review of the second posting of this series.
Fixes: f9a25f776d78 ("cpusets: Rebuild root domain deadline accounting information")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@xxxxxxxxxxxx>
---
kernel/sched/deadline.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 7a0c27e76028..d9bd01a1bac0 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -3594,6 +3594,15 @@ void dl_add_task_root_domain(struct task_struct *p)
cpu = p->dl.dl_departed_cpu;
if (!cpu_active(cpu))
goto unlock;
+ } else if (READ_ONCE(p->__state) == TASK_DEAD) {
+ /*
+ * Dead and not departed: its bandwidth was released at its
+ * last schedule, under its runqueue lock and not this one,
+ * and dl_bw may still say otherwise. do_task_dead() sets
+ * TASK_DEAD under pi_lock before that, so a task found alive
+ * here dies after this walk, and releases what it counted.
+ */
+ goto unlock;
}
rq = cpu_rq(cpu);
dl_b = &rq->rd->dl_bw;
--
2.47.3