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>
This commit is contained in:
Tejun Heo 2026-07-13 22:18:43 -10:00
parent 70f8b17853
commit bbda59d853
2 changed files with 30 additions and 9 deletions

View File

@ -21,6 +21,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)
@ -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)

View File

@ -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 "/"; }