[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <aYms6mIxWl0FNqBF@jlelli-thinkpadt14gen4.remote.csb>
Date: Mon, 9 Feb 2026 10:46:18 +0100
From: Juri Lelli <juri.lelli@...hat.com>
To: Peter Zijlstra <peterz@...radead.org>
Cc: Ingo Molnar <mingo@...hat.com>,
Vincent Guittot <vincent.guittot@...aro.org>,
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>,
Philip Auld <pauld@...hat.com>,
Gabriele Monaco <gmonaco@...hat.com>, linux-kernel@...r.kernel.org,
Bruno Goncalves <bgoncalv@...hat.com>
Subject: Re: [PATCH] sched/deadline: Fix missing ENQUEUE_REPLENISH during PI
de-boosting
On 07/02/26 09:45, Peter Zijlstra wrote:
> On Fri, Feb 06, 2026 at 02:25:52PM +0100, Juri Lelli wrote:
>
> > @@ -284,6 +285,33 @@ static bool check_same_owner(struct task_struct *p)
> > uid_eq(cred->euid, pcred->uid));
> > }
> >
> > +#ifdef CONFIG_RT_MUTEXES
> > +static void __setscheduler_dl(struct task_struct *p,
> > + struct sched_change_ctx *scope)
> > +{
> > + struct task_struct *pi_task = rt_mutex_get_top_task(p);
> > +
> > + /*
> > + * In case a former DEADLINE task (either proper or boosted) gets
> > + * setscheduled to a lower priority class, check if it neeeds to
> > + * inherit parameters from a potential pi_task. In that case make
> > + * sure replenishment happens with the next enqueue.
> > + */
> > + if (!dl_prio(p->normal_prio) &&
> > + (pi_task && dl_prio(pi_task->prio))) {
> > + p->dl.pi_se = pi_task->dl.pi_se;
> > +
> > + if (scope && scope->queued)
> > + scope->flags |= ENQUEUE_REPLENISH;
> > + }
> > +}
> > +#else /* !CONFIG_RT_MUTEXES */
> > +static void __setscheduler_dl(struct task_struct *p,
> > + struct sched_change_ctx *scope)
> > +{
> > +}
> > +#endif /* !CONFIG_RT_MUTEXES */
> > +
> > #ifdef CONFIG_UCLAMP_TASK
> >
> > static int uclamp_validate(struct task_struct *p,
> > @@ -657,6 +685,7 @@ int __sched_setscheduler(struct task_struct *p,
> > p->prio = newprio;
> > }
> > __setscheduler_uclamp(p, attr);
> > + __setscheduler_dl(p, scope);
> >
> > if (scope->queued) {
> > /*
> >
>
> Urgh... :-)
Yeah.
> So normally it would be __setscheduler_params(), but that funks out
> because !dl_policy() -- after all, we're demoting the boosted task to be
> !DL.
In this particular case we have a DEADLINE task (holder) that didn't
take the chance of being boosted by another DEADLINE task (donor),
because donor had longer dynamic deadline when rt_mutex_setprio() was
called. So now p->dl.pi_se still points to &p->dl and so enqueue_task_dl
doesn't recognize the holder as boosted and takes the wrong path at the
start.
> So then we need to fix up things to the effective priority.
We can use effective priority, right.
> Should this not be inside the !KEEP_PARAMS thing? Something like so?
And do it inside !KEEP_PARAMS, indeed.
> (afaict nothing clears dl_se::pi_se except rt_mutex_setprio() so that
> should still be valid here -- so we don't need to go find it again)
But, maybe with something like this? I believe we need to make things
right at this point "promoting" the now becoming lower prio class task
to DEADLINE (inheriting from the task it didn't inherit from in the
past). Maybe we can avoid checking pi_task since dl_prio(newprio). And
also move everything in an helper to remove ifdeffery.
---
diff --git a/kernel/sched/syscalls.c b/kernel/sched/syscalls.c
index 6f10db3646e7f..856df1a22e3ca 100644
--- a/kernel/sched/syscalls.c
+++ b/kernel/sched/syscalls.c
@@ -655,6 +655,16 @@ int __sched_setscheduler(struct task_struct *p,
__setscheduler_params(p, attr);
p->sched_class = next_class;
p->prio = newprio;
+#ifdef CONFIG_RT_MUTEXES
+ if (dl_prio(newprio) && !dl_policy(policy)) {
+ struct task_struct *pi_task = rt_mutex_get_top_task(p);
+
+ if (pi_task) {
+ p->dl.pi_se = pi_task->dl.pi_se;
+ scope->flags |= ENQUEUE_REPLENISH;
+ }
+ }
+#endif
}
__setscheduler_uclamp(p, attr);
Powered by blists - more mailing lists