Re: [PATCH v26 10/10] sched: Handle blocked-waiter migration (and return migration)

Steven Rostedt
2026-03-26T22:52:10Z

On Tue, 24 Mar 2026 19:13:25 +0000
John Stultz <jstultz@google.com> wrote:

> kernel/sched/core.c | 225 ++++++++++++++++++++++++++++++++++++++------
> 1 file changed, 197 insertions(+), 28 deletions(-)
>
> diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> index 4ed24ef590f73..49e4528450083 100644
> --- a/kernel/sched/core.c
> +++ b/kernel/sched/core.c
> @@ -3643,6 +3643,23 @@ void update_rq_avg_idle(struct rq *rq)
> rq->idle_stamp = 0;
> }
>
> +#ifdef CONFIG_SCHED_PROXY_EXEC
> +static inline void proxy_set_task_cpu(struct task_struct *p, int cpu)
> +{
> + unsigned int wake_cpu;
> +
> + /*
> + * Since we are enqueuing a blocked task on a cpu it may
> + * not be able to run on, preserve wake_cpu when we
> + * __set_task_cpu so we can return the task to where it
> + * was previously runnable.
> + */
> + wake_cpu = p->wake_cpu;
> + __set_task_cpu(p, cpu);
> + p->wake_cpu = wake_cpu;
> +}
> +#endif /* CONFIG_SCHED_PROXY_EXEC */

Hmm, this is only used in proxy_migrate_task() which is also within a
#ifdef CONFIG_SCHED_PROXY_EXEC block. Why did you put this function here
and create yet another #ifdef block with the same conditional?

Couldn't you just add it just before where it is used?

[..]

> +/*
> + * If the blocked-on relationship crosses CPUs, migrate @p to the
> + * owner's CPU.
> + *
> + * This is because we must respect the CPU affinity of execution
> + * contexts (owner) but we can ignore affinity for scheduling
> + * contexts (@p). So we have to move scheduling contexts towards
> + * potential execution contexts.
> + *
> + * Note: The owner can disappear, but simply migrate to @target_cpu
> + * and leave that CPU to sort things out.
> + */
> +static void proxy_migrate_task(struct rq *rq, struct rq_flags *rf,
> + struct task_struct *p, int target_cpu)
> + __must_hold(__rq_lockp(rq))
> +{
> + struct rq *target_rq = cpu_rq(target_cpu);
> +
> + lockdep_assert_rq_held(rq);
> + WARN_ON(p == rq->curr);
> + /*
> + * Since we are migrating a blocked donor, it could be rq->donor,
> + * and we want to make sure there aren't any references from this
> + * rq to it before we drop the lock. This avoids another cpu
> + * jumping in and grabbing the rq lock and referencing rq->donor
> + * or cfs_rq->curr, etc after we have migrated it to another cpu,
> + * and before we pick_again in __schedule.
> + *
> + * So call proxy_resched_idle() to drop the rq->donor references
> + * before we release the lock.
> + */
> + proxy_resched_idle(rq);
> +
> + deactivate_task(rq, p, DEQUEUE_NOCLOCK);
> + proxy_set_task_cpu(p, target_cpu);
> +
> + proxy_release_rq_lock(rq, rf);
> +
> + attach_one_task(target_rq, p);
> +
> + proxy_reacquire_rq_lock(rq, rf);
> +}

-- Steve