summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2026-07-13 22:18:43 -1000
committerTejun Heo <tj@kernel.org>2026-07-13 22:18:43 -1000
commitbbda59d85341d6d4d957596233646c84d9d9a451 (patch)
treefaf56200183941860ceb2a372fca8238a4a73aee
parent70f8b1785327f233d667d8fc0751a7d2ec231597 (diff)
downloadlinux-bbda59d85341d6d4d957596233646c84d9d9a451.tar.gz
linux-bbda59d85341d6d4d957596233646c84d9d9a451.zip
sched_ext: Add scx_skip_subtree_pre()
Factor the sibling/ancestor portion of scx_next_descendant_pre() out as scx_skip_subtree_pre(), a pre-order walk primitive that skips @pos's subtree, and call it from scx_next_descendant_pre(). Same locking rules as the existing primitive. Used in a follow-up to fast-skip subtrees that have nothing to do during a descendant walk. Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
-rw-r--r--kernel/sched/ext/sub.c37
-rw-r--r--kernel/sched/ext/sub.h2
2 files changed, 30 insertions, 9 deletions
diff --git a/kernel/sched/ext/sub.c b/kernel/sched/ext/sub.c
index 5fe2f79064dc..17ed0d28f383 100644
--- a/kernel/sched/ext/sub.c
+++ b/kernel/sched/ext/sub.c
@@ -22,6 +22,33 @@
#ifdef CONFIG_EXT_SUB_SCHED
/**
+ * scx_skip_subtree_pre - Skip @pos's subtree in a pre-order walk
+ * @pos: current position
+ * @root: walk root
+ *
+ * In a walk started by scx_next_descendant_pre(), continue past @pos's subtree:
+ * return @pos's next sibling, or the closest ancestor's next sibling, or NULL
+ * if @pos's subtree is the last under @root. Same locking rules.
+ */
+struct scx_sched *scx_skip_subtree_pre(struct scx_sched *pos, struct scx_sched *root)
+{
+ struct scx_sched *next;
+
+ lockdep_assert(lockdep_is_held(&scx_enable_mutex) ||
+ lockdep_is_held(&scx_sched_lock) ||
+ rcu_read_lock_any_held());
+
+ while (pos != root) {
+ next = list_next_or_null_rcu(&scx_parent(pos)->children, &pos->sibling,
+ struct scx_sched, sibling);
+ if (next)
+ return next;
+ pos = scx_parent(pos);
+ }
+ return NULL;
+}
+
+/**
* scx_next_descendant_pre - find the next descendant for pre-order walk
* @pos: the current position (%NULL to initiate traversal)
* @root: sched whose descendants to walk
@@ -48,15 +75,7 @@ struct scx_sched *scx_next_descendant_pre(struct scx_sched *pos, struct scx_sche
return next;
/* no child, visit my or the closest ancestor's next sibling */
- while (pos != root) {
- next = list_next_or_null_rcu(&scx_parent(pos)->children, &pos->sibling,
- struct scx_sched, sibling);
- if (next)
- return next;
- pos = scx_parent(pos);
- }
-
- return NULL;
+ return scx_skip_subtree_pre(pos, root);
}
static struct scx_sched *scx_find_sub_sched(u64 cgroup_id)
diff --git a/kernel/sched/ext/sub.h b/kernel/sched/ext/sub.h
index 45f3952b5d81..2688087a0654 100644
--- a/kernel/sched/ext/sub.h
+++ b/kernel/sched/ext/sub.h
@@ -15,6 +15,7 @@
#ifdef CONFIG_EXT_SUB_SCHED
+struct scx_sched *scx_skip_subtree_pre(struct scx_sched *pos, struct scx_sched *root);
struct scx_sched *scx_next_descendant_pre(struct scx_sched *pos, struct scx_sched *root);
void scx_set_task_sched(struct task_struct *p, struct scx_sched *sch);
struct cgroup *sch_cgroup(struct scx_sched *sch);
@@ -35,6 +36,7 @@ static inline const char *sch_cgrp_path(struct scx_sched *sch)
#else /* CONFIG_EXT_SUB_SCHED */
static inline struct scx_sched *scx_next_descendant_pre(struct scx_sched *pos, struct scx_sched *root) { return pos ? NULL : root; }
+static inline struct scx_sched *scx_skip_subtree_pre(struct scx_sched *pos, struct scx_sched *root) { return NULL; }
static inline void scx_set_task_sched(struct task_struct *p, struct scx_sched *sch) {}
static inline struct cgroup *sch_cgroup(struct scx_sched *sch) { return NULL; }
static inline const char *sch_cgrp_path(struct scx_sched *sch) { return "/"; }