<feed xmlns='http://www.w3.org/2005/Atom'>
<title>laptop-kernel/kernel/sched/ext/ext.c, branch master</title>
<subtitle>Linux kernel tree for laptop</subtitle>
<id>https://git.zx2c4.com/laptop-kernel/atom/kernel/sched/ext/ext.c?h=master</id>
<link rel='self' href='https://git.zx2c4.com/laptop-kernel/atom/kernel/sched/ext/ext.c?h=master'/>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/laptop-kernel/'/>
<updated>2026-10-14T22:58:16Z</updated>
<entry>
<title>Merge tag 'sched_ext-for-7.3-rc7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext</title>
<updated>2026-10-14T22:58:16Z</updated>
<author>
<name>Linus Torvalds</name>
<email>torvalds@linux-foundation.org</email>
</author>
<published>2026-10-14T22:58:16Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/laptop-kernel/commit/?id=db7afcbf9eef65aa8bfe6edb5ff4b4a92d1a4792'/>
<id>urn:sha1:db7afcbf9eef65aa8bfe6edb5ff4b4a92d1a4792</id>
<content type='text'>
Pull sched_ext fixes from Tejun Heo:

 - A task that skipped the BPF scheduler on its way back to its CPU's
   local queue could stall there until the watchdog fired, as the CPU
   had already decided to go idle.

 - Use-after-free of a destroyed user dispatch queue by a deferred
   re-enqueue request.

 - A task could be moved off a dispatch queue while the dispatching CPU
   was still running ops.dequeue() on it.

 - Bypass mode mishandled a sub-scheduler bypass overlapping an
   ancestor's, as across a system suspend. Descendants could leave
   bypass mid-teardown and tasks could be stranded on bypass queues.

 - The idle CPU selection helper could return a CPU outside the allowed
   CPUs of a pinned or migration-disabled task.

* tag 'sched_ext-for-7.3-rc7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext:
  sched_ext: Wait for SCX_OPSS_DISPATCHING before moving tasks off DSQs
  sched_ext: Rename scx_reenq_wait_dispatching() to scx_wait_dispatching()
  sched_ext: idle: Respect task affinity in restricted CPU selection
  sched_ext: Fix the bypass dispatch claim for schedulers bypassed by an ancestor
  sched_ext: Propagate every bypass depth change to the descendants
  sched_ext: Fix use-after-free of a destroyed user DSQ by a deferred reenqueue
  sched_ext: Fix stall when a task enqueued with SCX_ENQ_LAST lands back on its CPU's local DSQ
</content>
</entry>
<entry>
<title>sched_ext: Wait for SCX_OPSS_DISPATCHING before moving tasks off DSQs</title>
<updated>2026-10-13T19:55:19Z</updated>
<author>
<name>Kuba Piecuch</name>
<email>jpiecuch@google.com</email>
</author>
<published>2026-10-12T21:07:46Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/laptop-kernel/commit/?id=2935062be77113c1c4565ca9d0c72180449aafee'/>
<id>urn:sha1:2935062be77113c1c4565ca9d0c72180449aafee</id>
<content type='text'>
A task can be found on a non-local DSQ while the CPU which dispatched it
is still running ops.dequeue() and hasn't cleared SCX_OPSS_DISPATCHING.
The DSQ consume and move paths don't wait for the dispatch to finish and
can operate on the task concurrently with the dispatcher.

Call scx_wait_dispatching() in scx_move_local_task_to_local_dsq(),
unlink_dsq_and_switch_rq_lock() and move_task_between_dsqs() before they
operate on the task. In scx_move_local_task_to_local_dsq(), wait before
scx_resolve_local_dsq() as it may update p-&gt;scx.flags.

Fixes: ebf1ccff79c4 ("sched_ext: Fix ops.dequeue() semantics")
Fixes: cb86607ada73 ("sched_ext: Don't run ops.dequeue() with a DSQ lock held")
Cc: stable@vger.kernel.org # v7.1+
Reviewed-by: Andrea Righi &lt;arighi@nvidia.com&gt;
Assisted-by: Claude:claude-opus-5.5
Signed-off-by: Kuba Piecuch &lt;jpiecuch@google.com&gt;
Signed-off-by: Tejun Heo &lt;tj@kernel.org&gt;
</content>
</entry>
<entry>
<title>sched_ext: Rename scx_reenq_wait_dispatching() to scx_wait_dispatching()</title>
<updated>2026-10-13T19:54:41Z</updated>
<author>
<name>Kuba Piecuch</name>
<email>jpiecuch@google.com</email>
</author>
<published>2026-10-12T21:07:45Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/laptop-kernel/commit/?id=18f5c699d1d0a003b2959af5871b33ac9a2400ec'/>
<id>urn:sha1:18f5c699d1d0a003b2959af5871b33ac9a2400ec</id>
<content type='text'>
Waiting for SCX_OPSS_DISPATCHING to clear isn't specific to the reenqueue
paths. Any path which takes a task off a DSQ can find it while the
dispatch is still in flight, and the next patch calls the helper from the
DSQ consume and move paths. Rename it to scx_wait_dispatching() and
update its comment accordingly.

No functional change.

Reviewed-by: Andrea Righi &lt;arighi@nvidia.com&gt;
Assisted-by: Claude:claude-opus-5.5
Signed-off-by: Kuba Piecuch &lt;jpiecuch@google.com&gt;
Signed-off-by: Tejun Heo &lt;tj@kernel.org&gt;
</content>
</entry>
<entry>
<title>sched_ext: Fix the bypass dispatch claim for schedulers bypassed by an ancestor</title>
<updated>2026-10-12T18:32:15Z</updated>
<author>
<name>Tejun Heo</name>
<email>tj@kernel.org</email>
</author>
<published>2026-10-11T21:35:12Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/laptop-kernel/commit/?id=5bdeca322a6f8d10acaf67cccab1f69747ee7be3'/>
<id>urn:sha1:5bdeca322a6f8d10acaf67cccab1f69747ee7be3</id>
<content type='text'>
scx_bypass() claims bypass dispatch when the scheduler's depth goes from
zero to one and releases it when the depth returns to zero, but propagates
only the depth to the descendants, not the claim. A descendant that starts
bypassing with its ancestor never claims, and one whose own bypass ends
under the ancestor's keeps its claim, as its depth does not return to zero.

A sub-scheduler enable whose bypass ends under a PM suspend thus leaks its
claim: the parent keeps hosting bypass dispatch and the sub-scheduler's next
bypass trips the WARN_ON_ONCE() on the claim. A sub-scheduler disable that
starts under a PM suspend has no claim, so once the resume lifts the root's
bypass its tasks sit on the parent's bypass DSQs with nobody consuming them.

Claim for every descendant whose depth goes from zero to one in the
propagation and release every scheduler in the subtree whose depth returned
to zero once the tasks have moved out of the bypass DSQs. A parent that is
bypassing itself when a descendant claims consumes only its own bypass DSQs,
empty until it leaves bypass and becomes the host.

Fixes: aa2a0a19686c ("sched_ext: Separate bypass dispatch enabling from bypass depth tracking")
Cc: stable@vger.kernel.org # v7.1+
Signed-off-by: Tejun Heo &lt;tj@kernel.org&gt;
Reviewed-by: Andrea Righi &lt;arighi@nvidia.com&gt;
</content>
</entry>
<entry>
<title>sched_ext: Propagate every bypass depth change to the descendants</title>
<updated>2026-10-12T18:32:03Z</updated>
<author>
<name>Tejun Heo</name>
<email>tj@kernel.org</email>
</author>
<published>2026-10-11T21:35:12Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/laptop-kernel/commit/?id=dcf7f650a24897d59b071f7f9a454d8b0b188b27'/>
<id>urn:sha1:dcf7f650a24897d59b071f7f9a454d8b0b188b27</id>
<content type='text'>
scx_bypass() propagates a depth change to the descendants only when the
scheduler's own depth crosses zero, so an own bypass that starts under an
ancestor's never reaches them. When the ancestor's bypass ends first, the
descendants leave bypass while the scheduler is still bypassing: a
sub-scheduler disabled under a PM suspend has its children re-queue their
tasks through their own BPF schedulers at resume, mid-teardown. If the own
bypass then ends, every descendant is decremented once more than incremented
and dec_bypass_depth() warns, though no current caller gets there.

Propagate on every call so that a descendant's depth is the sum of its own
bypasses and its ancestors'. The early return follows the walk, as a
descendant's depth is at least the scheduler's and nothing changes bypass
state unless the scheduler's own does.

Fixes: c7f0e467a27a ("sched_ext: Prepare bypass mode for hierarchical operation")
Cc: stable@vger.kernel.org # v7.1+
Signed-off-by: Tejun Heo &lt;tj@kernel.org&gt;
Reviewed-by: Andrea Righi &lt;arighi@nvidia.com&gt;
</content>
</entry>
<entry>
<title>sched_ext: Fix use-after-free of a destroyed user DSQ by a deferred reenqueue</title>
<updated>2026-10-10T08:29:39Z</updated>
<author>
<name>Tejun Heo</name>
<email>tj@kernel.org</email>
</author>
<published>2026-10-09T22:01:45Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/laptop-kernel/commit/?id=069403dff337feb192bfc70fb28ddc8a171e20c1'/>
<id>urn:sha1:069403dff337feb192bfc70fb28ddc8a171e20c1</id>
<content type='text'>
A deferred reenqueue can read a freed user DSQ. The request stays on its
CPU's deferred list until run_deferred() takes it, and the RCU callback that
frees the DSQ assumes that the grace period has flushed it, so exit_dsq()
checks the per-CPU node without the deferred list lock. A grace period waits
for readers in flight, not for a pending run_deferred(). A run_deferred()
which starts after the grace period began can detach the request right
before the callback looks and then read the freed DSQ's id.

Cancel the pending requests before the grace period instead. The irq work
that frees the DSQ unlinks every CPU's request under the per-CPU deferred
list lock, and schedule_dsq_reenq() ignores a new request under the same
lock once the id is invalid. Only a run_deferred() that started before the
grace period can hold a request, and it runs with IRQs disabled, so the
grace period waits for it and nothing touches the DSQ after the callback.

Fixes: 84b1a0ea0b7c ("sched_ext: Implement scx_bpf_dsq_reenq() for user DSQs")
Cc: stable@vger.kernel.org # v7.1+
Reported-and-tested-by: Hui Su &lt;sh_def@163.com&gt;
Link: https://lore.kernel.org/all/20261008024753.4096008-1-sh_def@163.com/
Signed-off-by: Tejun Heo &lt;tj@kernel.org&gt;
</content>
</entry>
<entry>
<title>sched_ext: Fix stall when a task enqueued with SCX_ENQ_LAST lands back on its CPU's local DSQ</title>
<updated>2026-10-10T08:29:32Z</updated>
<author>
<name>Tejun Heo</name>
<email>tj@kernel.org</email>
</author>
<published>2026-10-07T16:26:47Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/laptop-kernel/commit/?id=7a9df76679633cf26e0fea882a684012c6ec245a'/>
<id>urn:sha1:7a9df76679633cf26e0fea882a684012c6ec245a</id>
<content type='text'>
With SCX_OPS_ENQ_LAST, the last runnable task on a CPU is passed to
ops.enqueue() instead of being kept running. Exiting tasks without
SCX_OPS_ENQ_EXITING, migration disabled tasks without
SCX_OPS_ENQ_MIGRATION_DISABLED and tasks on an offline rq skip ops.enqueue()
and go straight to the local DSQ. This happens in put_prev_task_scx() after
the pick has settled on idle, so nothing reschedules the CPU, which idles
with the task queued until an unrelated wakeup lands on it or the watchdog
fires.

scx_mitosis, which sets SCX_OPS_ENQ_LAST without SCX_OPS_ENQ_EXITING, hit
this during mass cgroup teardown: exiting tasks stuck in exit_mmap() for
over 40 seconds.

A task put on the local DSQ runs, as anywhere else. If the SCX_ENQ_LAST
enqueue left the task on this CPU's local DSQ, set need_resched on the task
being switched in, as proxy_resched_idle() does. resched_curr() would flag
the task being put instead, and __schedule() clears that right after the
pick.

Fixes: f0e1a0643a59 ("sched_ext: Implement BPF extensible scheduler class")
Cc: stable@vger.kernel.org # v6.12+
Reported-by: Xiangyu Bu &lt;xbu@meta.com&gt;
Link: https://github.com/sched-ext/scx/pull/3870
Signed-off-by: Tejun Heo &lt;tj@kernel.org&gt;
Cc: Dan Schatzberg &lt;schatzberg.dan@gmail.com&gt;
</content>
</entry>
<entry>
<title>Merge tag 'sched_ext-for-7.3-rc6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext</title>
<updated>2026-10-07T00:03:46Z</updated>
<author>
<name>Linus Torvalds</name>
<email>torvalds@linux-foundation.org</email>
</author>
<published>2026-10-07T00:03:46Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/laptop-kernel/commit/?id=762122d75e50e4919ef77afc2dffdc4931c5be87'/>
<id>urn:sha1:762122d75e50e4919ef77afc2dffdc4931c5be87</id>
<content type='text'>
Pull sched_ext fixes from Tejun Heo:

 - Taking a CPU offline could hang, or stall until the watchdog ejected
   the BPF scheduler, when tasks on the dying CPU were still held by the
   scheduler or sitting on a user dispatch queue. Re-enqueue them onto
   the local queue when the runqueue goes offline so that the CPU pushes
   them off like the other sched classes.

 - The sequence number guarding against stale dispatches was per
   runqueue, so a task re-enqueued on another CPU could get the same
   number and a dispatch meant for its earlier instance was applied to
   the new one. Use a per-task counter.

 - A task dispatched to another CPU's local queue got its ops.dequeue()
   only when picked to run and flagged as a core-sched pick. Call it at
   insertion like for same-CPU dispatches.

* tag 'sched_ext-for-7.3-rc6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext:
  sched_ext: Generate qseq from a per-task counter
  selftests/sched_ext: Add a test for ops.dequeue() on remote local DSQ moves
  sched_ext: Call ops.dequeue() when a task arrives on a remote local DSQ
  sched_ext: Fix CPU hotplug hang when a dying CPU's tasks sit in the BPF scheduler
</content>
</entry>
<entry>
<title>sched_ext: Generate qseq from a per-task counter</title>
<updated>2026-10-03T23:23:31Z</updated>
<author>
<name>Kuba Piecuch</name>
<email>jpiecuch@google.com</email>
</author>
<published>2026-10-03T11:53:17Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/laptop-kernel/commit/?id=e6ac89b8b1c12e9104df45a14a26e2dfa96ded06'/>
<id>urn:sha1:e6ac89b8b1c12e9104df45a14a26e2dfa96ded06</id>
<content type='text'>
finish_dispatch() uses the qseq embedded in p-&gt;scx.ops_state to tell
whether the QUEUED instance of a task it's about to claim is the one
scx_bpf_dsq_insert() saw. qseq is generated from rq-&gt;scx.ops_qseq, but
the counters of different rqs are independent, so if a task is dequeued
and re-enqueued on a different rq between scx_bpf_dsq_insert() and
finish_dispatch(), the new QUEUED instance can end up with the same
qseq as the old one:

  CPU X                          CPU Z
  -----                          -----
                                 enqueue p on rq A, qseq = N
  ops.dispatch()
    scx_bpf_dsq_insert(p)
      records qseq N
                                 sched_setaffinity(p)
                                   dequeue p from rq A
                                   enqueue p on rq B, qseq = N
  finish_dispatch(p, N)
    qseq matches, p is claimed

The claim itself is still atomic so the core stays consistent, but an
insert issued for a previous QUEUED instance gets applied to a new one
which the BPF scheduler has just received through ops.enqueue(). This
breaks the guarantee that dispatches targeting a stale instance are
ignored.

Generate qseq from a per-task counter, p-&gt;scx.ops_qseq, instead so that
consecutive QUEUED instances of a task never share a qseq regardless of
which rq they're on. The counter is only updated in
scx_do_enqueue_task() with the task's rq locked, so no additional
synchronization is needed, and it fits in an existing hole in struct
sched_ext_entity on 64bit. Remove the now unused rq-&gt;scx.ops_qseq.

Never generate qseq 0. NONE and DISPATCHING don't carry a qseq, so
scx_bpf_dsq_insert() on a task in either state records 0. With a
per-task counter, every task's first QUEUED instance would otherwise get
qseq 0 and could be claimed by such an insert. Wrap the counter where
the QSEQ field wraps so that it can't reach a value that shifts to 0 on
32bit either.

Fixes: f0e1a0643a59 ("sched_ext: Implement BPF extensible scheduler class")
Cc: stable@vger.kernel.org # v6.12+
Assisted-by: Claude:claude-opus-5.5
Signed-off-by: Kuba Piecuch &lt;jpiecuch@google.com&gt;
Signed-off-by: Tejun Heo &lt;tj@kernel.org&gt;
</content>
</entry>
<entry>
<title>sched_ext: Call ops.dequeue() when a task arrives on a remote local DSQ</title>
<updated>2026-09-30T17:49:44Z</updated>
<author>
<name>Kuba Piecuch</name>
<email>jpiecuch@google.com</email>
</author>
<published>2026-09-30T14:23:58Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/laptop-kernel/commit/?id=af701b8d3238b9eb7cd450b0491300452c700bf5'/>
<id>urn:sha1:af701b8d3238b9eb7cd450b0491300452c700bf5</id>
<content type='text'>
When a task in the BPF scheduler's custody is moved to another CPU's
local DSQ, ops.dequeue() is only called once the task is picked for
execution, from set_next_task_scx() with SCX_DEQ_CORE_SCHED_EXEC, even
though no core-sched pick took place. It should instead be called
without flags when the task is inserted into the destination DSQ, as it
is for same-rq dispatches.

move_remote_task_to_local_dsq() sets p-&gt;scx.sticky_cpu across the
migration so that deactivate_task() on the source rq doesn't end custody.
Since commit b75aaea24c9f ("sched_ext: Properly mark SCX-internal
migrations via sticky_cpu"), enqueue_task_scx() only clears it after
inserting the task, so task_leave_custody() still sees the migration in
progress and skips the custody exit.

Clear p-&gt;scx.sticky_cpu as soon as enqueue_task_scx() has read it, as
was done before that commit. The source side is unaffected.

Fixes: ebf1ccff79c4 ("sched_ext: Fix ops.dequeue() semantics")
Cc: stable@vger.kernel.org # 7.1.x: 18d62044cda7: sched_ext: Preserve rq tracking across local DSQ dispatch
Cc: stable@vger.kernel.org # 7.1.x
Reviewed-by: Andrea Righi &lt;arighi@nvidia.com&gt;
Assisted-by: Claude:claude-opus-5.5
Signed-off-by: Kuba Piecuch &lt;jpiecuch@google.com&gt;
Signed-off-by: Tejun Heo &lt;tj@kernel.org&gt;
</content>
</entry>
</feed>
