Re: [PATCH 1/7] sched/core: Fix pick_next_task() self recursion

From: Aaron Lu

Date: Thu Sep 03 2026 - 08:45:43 EST


On Fri, Aug 28, 2026 at 12:17:00PM +0200, Peter Zijlstra wrote:
> It is possible for another sibling to end up in pick_next_task() when:
>
> pick_next_task()
> pick_task()
> sched_class::pick_task()
>
> drops the core wide rq->lock. In this case they end up trampling the core wide
> task selection state, possibly leading to NULL derefs. Detect this case by
> keeping a local copy of core_task_seq, a value that is incremented on
> {en,de}queue and schedule.
>
> Since RETRY_TASK is only possible when a higher priority task gets enqueued
> during the lock break, this must mean core_task_seq will also be incremented
> and is thus completely covered by the seq number mismatch.

For the uncookied no-sync fast path, we should check if core wide is
still uncookied after lock is re-acquired? Something like below, or we
can pick an uncookied task when sibling picked a cookied one:

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index cd0149f5f6693..781f751acdb5b 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6314,6 +6314,14 @@ pick_next_task(struct rq *rq, struct rq_flags *rf)
goto restart;

if (!next->core_cookie) {
+ /*
+ * pick_task() can drop the core rq lock through newidle balance.
+ * If a sibling established a core-wide cookie while the lock was
+ * dropped, the uncookied no-sync fast path is no longer valid.
+ */
+ if (unlikely(rq->core->core_cookie))
+ goto restart;
+
rq->core_pick = NULL;
rq->core_dl_server = NULL;
/*

We can also do a core_task_seq check above but if sibling picked an
uncookied task, it's actually OK for this rq to go this fast path so I
chose to check rq->core->core_cookie here.