Re: [PATCH] sched/rt: Push RT tasks when preempted by a deadline task

From: Eric yang

Date: Wed Jun 24 2026 - 22:27:14 EST


Hi Prateek,

Thank you for the review!

> next can be NULL if we are coming here from sched_change_begin()
> for the current task [...] NULL pointer dereference !!!

You are absolutely right. put_prev_task() in sched.h always passes
NULL as 'next':

static inline void put_prev_task(struct rq *rq, struct task_struct *prev)
{
prev->sched_class->put_prev_task(rq, prev, NULL);
}

So when sched_change_begin() calls put_prev_task() for the currently
running RT task (e.g. during a priority/affinity change), next is NULL
and dl_task(next) will dereference it. I'll fix this with a NULL guard:

if (next && dl_task(next))
rt_queue_push_tasks(rq);

> If there are short running deadline tasks, we'll unnecessarily push
> a task and pull it back later. Is that not a concern?

This is a valid concern. The push is asynchronous (queued via IPI), so
there is an inherent delay before the RT task actually migrates. If the
DL task finishes before the push executes, the push becomes a no-op
since rt_queue_push_tasks() checks has_pushable_tasks() and the RT
task will have already been re-selected on this CPU.

If the RT task does get migrated and the DL task then exits shortly
after, pull_rt_task() triggered from the DL task's dequeue path will
bring it back. This round-trip is not free, but it is the same
trade-off already accepted in __schedule() when a DL task preempts
an RT task there.

The alternative -- never pushing -- means that while a DL task runs,
other CPUs may sit idle or run lower-priority work while a migratable
RT task is stuck waiting. For real-time workloads, that latency cost
is typically worse than an occasional unnecessary migration.

That said, I agree this is worth calling out explicitly in the commit
message. I'll update it accordingly in v2.

Thanks again for the careful review.

Best regards,
yangsonghua

杨送华 <yangsonghua@xxxxxxxxxxx> 于2026年6月25日周四 10:13写道:
>
> Hi Prateek, Thank you for the review! > next can be NULL if we are coming here from sched_change_begin() > for the current task [...] NULL pointer dereference !!! You are absolutely right. put_prev_task() in sched.h always passes NULL as 'next': static inline void put_prev_task(struct rq *rq, struct task_struct *prev) { prev->sched_class->put_prev_task(rq, prev, NULL); } So when sched_change_begin() calls put_prev_task() for the currently running RT task (e.g. during a priority/affinity change), next is NULL and dl_task(next) will dereference it. I'll fix this with a NULL guard: if (next && dl_task(next)) rt_queue_push_tasks(rq); > If there are short running deadline tasks, we'll unnecessarily push > a task and pull it back later. Is that not a concern? This is a valid concern. The push is asynchronous (queued via IPI), so there is an inherent delay before the RT task actually migrates. If the DL task finishes before the push executes, the push becomes a no-op since rt_queue_push_tasks() checks has_pushable_tasks() and the RT task will have already been re-selected on this CPU. If the RT task does get migrated and the DL task then exits shortly after, pull_rt_task() triggered from the DL task's dequeue path will bring it back. This round-trip is not free, but it is the same trade-off already accepted in __schedule() when a DL task preempts an RT task there. The alternative -- never pushing -- means that while a DL task runs, other CPUs may sit idle or run lower-priority work while a migratable RT task is stuck waiting. For real-time workloads, that latency cost is typically worse than an occasional unnecessary migration. That said, I agree this is worth calling out explicitly in the commit message. I'll update it accordingly in v2. Thanks again for the careful review. Best regards, yangsonghua > From: "K Prateek Nayak"<kprateek.nayak@xxxxxxx> > Date: Wed, Jun 24, 2026, 11:53 > Subject: Re: [PATCH] sched/rt: Push RT tasks when preempted by a deadline task > To: "yangsonghua"<jluyangsonghua@xxxxxxxxx>, "Ingo Molnar"<mingo@xxxxxxxxxx>, "Peter Zijlstra"<peterz@xxxxxxxxxxxxx> > Cc: "Juri Lelli"<juri.lelli@xxxxxxxxxx>, "Vincent Guittot"<vincent.guittot@xxxxxxxxxx>, "Dietmar Eggemann"<dietmar.eggemann@xxxxxxx>, "Steven Rostedt"<rostedt@xxxxxxxxxxx>, "Ben Segall"<bsegall@xxxxxxxxxx>, "Valentin Schneider"<vschneid@xxxxxxxxxx>, <linux-kernel@xxxxxxxxxxxxxxx>, "yangsonghua"<yangsonghua@xxxxxxxxxxx> > Hello Yangsonghua, > > On 6/24/2026 8:34 AM, yangsonghua wrote: > > @@ -1736,14 +1737,24 @@ static void put_prev_task_rt(struct rq *rq, struct task_struct *p, struct task_s > > > > update_rt_rq_load_avg(rq_clock_pelt(rq), rq, 1); > > > > - if (task_is_blocked(p)) > > - return; > > /* > > * The previous task needs to be made eligible for pushing > > - * if it is still active > > + * if it is still active and migratable. > > */ > > - if (on_rt_rq(&p->rt) && p->nr_cpus_allowed > 1) > > + if (!task_is_blocked(p) && on_rt_rq(&p->rt) && p->nr_cpus_allowed > 1) > > enqueue_pushable_task(rq, p); > > + > > + /* > > + * When a deadline task takes over this CPU, try to push any queued > > + * RT tasks to CPUs running lower-priority work. This is independent > > + * of whether p itself is pushable: even if p is pinned or blocked, > > + * there may be other migratable RT tasks already in pushable_tasks. > > + * > > + * rt_queue_push_tasks() guards on has_pushable_tasks() internally, > > + * so this is a no-op if nothing is queued. > > + */ > > + if (dl_task(next)) > > + rt_queue_push_tasks(rq); > > next can be NULL if we are are coming here from sched_change_begin() > for the current task: > > sched_change_begin() > put_prev_task() > put_prev_task_rt(rq, prev, next = NULL) > dl_task(next) > dl_prio(next->prio) !!! NULL pointer dereference !!! > > Do we avoid this in some way? > > I don't know if this push was intentionally avoided or not. If there > are short running deadline task, we'll unnecessarily push a task and > pull it back later. Is that not a concern? > > -- > Thanks and Regards, > Prateek >
>
> 声明:这封邮件只允许文件接收者阅读,有很高的机密性要求。禁止其他人使用、打开、复制或转发里面的任何内容。如果本邮件错误地发给了你,请联系邮件发出者并删除这个文件。机密及法律的特权并不因为误发邮件而放弃或丧失。任何提出的观点或意见只属于作者的个人见解,并不一定代表本公司。
> Disclaimer: This email is intended to be read only by the designated recipient of the document and has high confidentiality requirements. Anyone else is prohibited from using, opening, copying or forwarding any of the contents inside. If this email was sent to you by mistake, please contact the sender of the email and delete this file immediately. Confidentiality and legal privileges are not waived or lost by misdirected emails. Any views or opinions expressed in the email are those of the author and do not necessarily represent those of the Company.
>