From: Tejun Heo <tj@kernel.org>
To: sched-ext@lists.linux.dev, linux-kernel@vger.kernel.org
Cc: David Vernet <void@manifault.com>,
Andrea Righi <arighi@nvidia.com>,
Changwoo Min <changwoo@igalia.com>,
Emil Tsalapatis <emil@etsalapatis.com>,
Daniel Jordan <daniel.m.jordan@oracle.com>
Subject: [PATCH v2 05/15] sched_ext: Relocate run_deferred() and its callees
Date: Fri, 06 Mar 2026 14:12:06 -1000 [thread overview]
Message-ID: <f452de511bd41ba99d77af11e37f76b0@kernel.org> (raw)
In-Reply-To: <20260306190623.1076074-6-tj@kernel.org>
Previously, both process_ddsp_deferred_locals() and reenq_local() required
forward declarations. Reorganize so that only run_deferred() needs to be
declared. Both callees are grouped right before run_deferred() for better
locality. This reduces forward declaration clutter and will ease adding more
to the run_deferred() path.
No functional changes.
v2: Also relocate process_ddsp_deferred_locals() next to run_deferred()
(Daniel Jordan).
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Reviewed-by: Daniel Jordan <daniel.m.jordan@oracle.com>
---
kernel/sched/ext.c | 186 ++++++++++++++++++++++++++---------------------------
1 file changed, 92 insertions(+), 94 deletions(-)
--- a/kernel/sched/ext.c
+++ b/kernel/sched/ext.c
@@ -193,9 +193,8 @@ MODULE_PARM_DESC(bypass_lb_intv_us, "byp
#define CREATE_TRACE_POINTS
#include <trace/events/sched_ext.h>
-static void process_ddsp_deferred_locals(struct rq *rq);
+static void run_deferred(struct rq *rq);
static bool task_dead_and_done(struct task_struct *p);
-static u32 reenq_local(struct scx_sched *sch, struct rq *rq);
static void scx_kick_cpu(struct scx_sched *sch, s32 cpu, u64 flags);
static void scx_disable(struct scx_sched *sch, enum scx_exit_kind kind);
static bool scx_vexit(struct scx_sched *sch, enum scx_exit_kind kind,
@@ -1003,23 +1002,6 @@ static int ops_sanitize_err(struct scx_s
return -EPROTO;
}
-static void run_deferred(struct rq *rq)
-{
- process_ddsp_deferred_locals(rq);
-
- if (!llist_empty(&rq->scx.deferred_reenq_locals)) {
- struct llist_node *llist =
- llist_del_all(&rq->scx.deferred_reenq_locals);
- struct scx_sched_pcpu *pos, *next;
-
- llist_for_each_entry_safe(pos, next, llist,
- deferred_reenq_locals_node) {
- init_llist_node(&pos->deferred_reenq_locals_node);
- reenq_local(pos->sch, rq);
- }
- }
-}
-
static void deferred_bal_cb_workfn(struct rq *rq)
{
run_deferred(rq);
@@ -2625,33 +2607,6 @@ has_tasks:
return true;
}
-static void process_ddsp_deferred_locals(struct rq *rq)
-{
- struct task_struct *p;
-
- lockdep_assert_rq_held(rq);
-
- /*
- * Now that @rq can be unlocked, execute the deferred enqueueing of
- * tasks directly dispatched to the local DSQs of other CPUs. See
- * direct_dispatch(). Keep popping from the head instead of using
- * list_for_each_entry_safe() as dispatch_local_dsq() may unlock @rq
- * temporarily.
- */
- while ((p = list_first_entry_or_null(&rq->scx.ddsp_deferred_locals,
- struct task_struct, scx.dsq_list.node))) {
- struct scx_sched *sch = scx_task_sched(p);
- struct scx_dispatch_q *dsq;
-
- list_del_init(&p->scx.dsq_list.node);
-
- dsq = find_dsq_for_dispatch(sch, rq, p->scx.ddsp_dsq_id, task_cpu(p));
- if (!WARN_ON_ONCE(dsq->id != SCX_DSQ_LOCAL))
- dispatch_to_local_dsq(sch, rq, dsq, p,
- p->scx.ddsp_enq_flags);
- }
-}
-
static void set_next_task_scx(struct rq *rq, struct task_struct *p, bool first)
{
struct scx_sched *sch = scx_task_sched(p);
@@ -3072,7 +3027,6 @@ static void rq_offline_scx(struct rq *rq
rq->scx.flags &= ~SCX_RQ_ONLINE;
}
-
static bool check_rq_for_timeouts(struct rq *rq)
{
struct scx_sched *sch;
@@ -3612,6 +3566,97 @@ int scx_check_setscheduler(struct task_s
return 0;
}
+static void process_ddsp_deferred_locals(struct rq *rq)
+{
+ struct task_struct *p;
+
+ lockdep_assert_rq_held(rq);
+
+ /*
+ * Now that @rq can be unlocked, execute the deferred enqueueing of
+ * tasks directly dispatched to the local DSQs of other CPUs. See
+ * direct_dispatch(). Keep popping from the head instead of using
+ * list_for_each_entry_safe() as dispatch_local_dsq() may unlock @rq
+ * temporarily.
+ */
+ while ((p = list_first_entry_or_null(&rq->scx.ddsp_deferred_locals,
+ struct task_struct, scx.dsq_list.node))) {
+ struct scx_sched *sch = scx_task_sched(p);
+ struct scx_dispatch_q *dsq;
+
+ list_del_init(&p->scx.dsq_list.node);
+
+ dsq = find_dsq_for_dispatch(sch, rq, p->scx.ddsp_dsq_id, task_cpu(p));
+ if (!WARN_ON_ONCE(dsq->id != SCX_DSQ_LOCAL))
+ dispatch_to_local_dsq(sch, rq, dsq, p,
+ p->scx.ddsp_enq_flags);
+ }
+}
+
+static u32 reenq_local(struct scx_sched *sch, struct rq *rq)
+{
+ LIST_HEAD(tasks);
+ u32 nr_enqueued = 0;
+ struct task_struct *p, *n;
+
+ lockdep_assert_rq_held(rq);
+
+ /*
+ * The BPF scheduler may choose to dispatch tasks back to
+ * @rq->scx.local_dsq. Move all candidate tasks off to a private list
+ * first to avoid processing the same tasks repeatedly.
+ */
+ list_for_each_entry_safe(p, n, &rq->scx.local_dsq.list,
+ scx.dsq_list.node) {
+ struct scx_sched *task_sch = scx_task_sched(p);
+
+ /*
+ * If @p is being migrated, @p's current CPU may not agree with
+ * its allowed CPUs and the migration_cpu_stop is about to
+ * deactivate and re-activate @p anyway. Skip re-enqueueing.
+ *
+ * While racing sched property changes may also dequeue and
+ * re-enqueue a migrating task while its current CPU and allowed
+ * CPUs disagree, they use %ENQUEUE_RESTORE which is bypassed to
+ * the current local DSQ for running tasks and thus are not
+ * visible to the BPF scheduler.
+ */
+ if (p->migration_pending)
+ continue;
+
+ if (!scx_is_descendant(task_sch, sch))
+ continue;
+
+ dispatch_dequeue(rq, p);
+ list_add_tail(&p->scx.dsq_list.node, &tasks);
+ }
+
+ list_for_each_entry_safe(p, n, &tasks, scx.dsq_list.node) {
+ list_del_init(&p->scx.dsq_list.node);
+ do_enqueue_task(rq, p, SCX_ENQ_REENQ, -1);
+ nr_enqueued++;
+ }
+
+ return nr_enqueued;
+}
+
+static void run_deferred(struct rq *rq)
+{
+ process_ddsp_deferred_locals(rq);
+
+ if (!llist_empty(&rq->scx.deferred_reenq_locals)) {
+ struct llist_node *llist =
+ llist_del_all(&rq->scx.deferred_reenq_locals);
+ struct scx_sched_pcpu *pos, *next;
+
+ llist_for_each_entry_safe(pos, next, llist,
+ deferred_reenq_locals_node) {
+ init_llist_node(&pos->deferred_reenq_locals_node);
+ reenq_local(pos->sch, rq);
+ }
+ }
+}
+
#ifdef CONFIG_NO_HZ_FULL
bool scx_can_stop_tick(struct rq *rq)
{
@@ -7702,53 +7747,6 @@ static const struct btf_kfunc_id_set scx
.set = &scx_kfunc_ids_dispatch,
};
-static u32 reenq_local(struct scx_sched *sch, struct rq *rq)
-{
- LIST_HEAD(tasks);
- u32 nr_enqueued = 0;
- struct task_struct *p, *n;
-
- lockdep_assert_rq_held(rq);
-
- /*
- * The BPF scheduler may choose to dispatch tasks back to
- * @rq->scx.local_dsq. Move all candidate tasks off to a private list
- * first to avoid processing the same tasks repeatedly.
- */
- list_for_each_entry_safe(p, n, &rq->scx.local_dsq.list,
- scx.dsq_list.node) {
- struct scx_sched *task_sch = scx_task_sched(p);
-
- /*
- * If @p is being migrated, @p's current CPU may not agree with
- * its allowed CPUs and the migration_cpu_stop is about to
- * deactivate and re-activate @p anyway. Skip re-enqueueing.
- *
- * While racing sched property changes may also dequeue and
- * re-enqueue a migrating task while its current CPU and allowed
- * CPUs disagree, they use %ENQUEUE_RESTORE which is bypassed to
- * the current local DSQ for running tasks and thus are not
- * visible to the BPF scheduler.
- */
- if (p->migration_pending)
- continue;
-
- if (!scx_is_descendant(task_sch, sch))
- continue;
-
- dispatch_dequeue(rq, p);
- list_add_tail(&p->scx.dsq_list.node, &tasks);
- }
-
- list_for_each_entry_safe(p, n, &tasks, scx.dsq_list.node) {
- list_del_init(&p->scx.dsq_list.node);
- do_enqueue_task(rq, p, SCX_ENQ_REENQ, -1);
- nr_enqueued++;
- }
-
- return nr_enqueued;
-}
-
__bpf_kfunc_start_defs();
/**
--
tejun
next prev parent reply other threads:[~2026-03-07 0:12 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-06 19:06 [PATCHSET sched_ext/for-7.1] sched_ext: Overhaul DSQ reenqueue infrastructure Tejun Heo
2026-03-06 19:06 ` [PATCH 01/15] sched_ext: Relocate scx_bpf_task_cgroup() and its BTF_ID to the end of kfunc section Tejun Heo
2026-03-06 20:45 ` Emil Tsalapatis
2026-03-06 23:20 ` Daniel Jordan
2026-03-06 19:06 ` [PATCH 02/15] sched_ext: Wrap global DSQs in per-node structure Tejun Heo
2026-03-06 20:52 ` Emil Tsalapatis
2026-03-06 23:20 ` Daniel Jordan
2026-03-06 19:06 ` [PATCH 03/15] sched_ext: Factor out pnode allocation and deallocation into helpers Tejun Heo
2026-03-06 20:54 ` Emil Tsalapatis
2026-03-06 23:21 ` Daniel Jordan
2026-03-06 19:06 ` [PATCH 04/15] sched_ext: Change find_global_dsq() to take CPU number instead of task Tejun Heo
2026-03-06 21:06 ` Emil Tsalapatis
2026-03-06 22:33 ` [PATCH v2 " Tejun Heo
2026-03-06 23:21 ` [PATCH " Daniel Jordan
2026-03-06 19:06 ` [PATCH 05/15] sched_ext: Relocate reenq_local() and run_deferred() Tejun Heo
2026-03-06 21:09 ` Emil Tsalapatis
2026-03-06 23:34 ` Daniel Jordan
2026-03-07 0:12 ` Tejun Heo [this message]
2026-03-06 19:06 ` [PATCH 06/15] sched_ext: Convert deferred_reenq_locals from llist to regular list Tejun Heo
2026-03-09 17:12 ` Emil Tsalapatis
2026-03-09 17:16 ` Emil Tsalapatis
2026-03-06 19:06 ` [PATCH 07/15] sched_ext: Wrap deferred_reenq_local_node into a struct Tejun Heo
2026-03-09 17:16 ` Emil Tsalapatis
2026-03-06 19:06 ` [PATCH 08/15] sched_ext: Introduce scx_bpf_dsq_reenq() for remote local DSQ reenqueue Tejun Heo
2026-03-09 17:33 ` Emil Tsalapatis
2026-03-06 19:06 ` [PATCH 09/15] sched_ext: Add reenq_flags plumbing to scx_bpf_dsq_reenq() Tejun Heo
2026-03-09 17:47 ` Emil Tsalapatis
2026-03-06 19:06 ` [PATCH 10/15] sched_ext: Add per-CPU data to DSQs Tejun Heo
2026-03-06 22:54 ` Andrea Righi
2026-03-06 22:56 ` Andrea Righi
2026-03-06 23:09 ` [PATCH v2 " Tejun Heo
2026-03-06 19:06 ` [PATCH 11/15] sched_ext: Factor out nldsq_cursor_next_task() and nldsq_cursor_lost_task() Tejun Heo
2026-03-06 19:06 ` [PATCH 12/15] sched_ext: Implement scx_bpf_dsq_reenq() for user DSQs Tejun Heo
2026-03-06 19:06 ` [PATCH 13/15] sched_ext: Optimize schedule_dsq_reenq() with lockless fast path Tejun Heo
2026-03-06 19:06 ` [PATCH 14/15] sched_ext: Simplify task state handling Tejun Heo
2026-03-06 19:06 ` [PATCH 15/15] sched_ext: Add SCX_TASK_REENQ_REASON flags Tejun Heo
2026-03-06 23:14 ` [PATCHSET sched_ext/for-7.1] sched_ext: Overhaul DSQ reenqueue infrastructure Andrea Righi
2026-03-07 15:38 ` Tejun Heo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f452de511bd41ba99d77af11e37f76b0@kernel.org \
--to=tj@kernel.org \
--cc=arighi@nvidia.com \
--cc=changwoo@igalia.com \
--cc=daniel.m.jordan@oracle.com \
--cc=emil@etsalapatis.com \
--cc=linux-kernel@vger.kernel.org \
--cc=sched-ext@lists.linux.dev \
--cc=void@manifault.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.