Skip to content
This repository was archived by the owner on Jun 18, 2024. It is now read-only.

Commit

Permalink
scx: Call directly into ext.c for hotplug events
Browse files Browse the repository at this point in the history
The rq_online() and rq_offline() sched_class callbacks may be invoked on either
the domain creation path, or on the hotplug path. ext.c would previously only
invoke its hotplug logic when those callbacks are invoked on the hotplug path.
This turned out to be a bit brittle, as hotplug could break for sched_ext if we
first invoked rq_online() from the domain path, as it would cause us to skip
invoking it on the hotplug path due to hotplug implementation details.

To avoid this frailty (and fix a hotplug regression for us after merging
v6.10), let's instead just call directly into ext.c on the hotplug path. This
could be made into a sched_class callback if that's what schedulers want, but
that's kind of what rq_online() and rq_offline() are supposed to be, so it's a
bit awkward as is. It would have been ideal if we could have just used a
hotplug event notifier, but as far as I know that doesn't exist.

Signed-off-by: David Vernet <void@manifault.com>
  • Loading branch information
Byte-Lab committed Jun 5, 2024
1 parent bf76f6f commit 998970b
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 5 deletions.
20 changes: 20 additions & 0 deletions kernel/sched/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -9790,6 +9790,21 @@ int sched_cpu_activate(unsigned int cpu)
if (rq->rd) {
BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
set_rq_online(rq);
/*
* Unfortunately, we can't use the rq_online() and rq_offline()
* callbacks to pass hotplug events down to ext.c because those
* callbacks may be invoked on the domain rebuild path first,
* thus causing us to skip invoking rq_online() in the
* set_rq_online() call above. While we could just treat all
* rq_online() / rq_offline() calls as hotplug events, that
* would cause a lot of noise in BPF schedulers who would
* receive several callbacks for every hotplug event as the
* domains are torn down and recreated. Instead, just call
* directly into the scheduler on the hotplug activation and
* deactivation paths so there's no ambiguity in calling
* context.
*/
scx_rq_activate(rq);
}
rq_unlock_irqrestore(rq, &rf);

Expand Down Expand Up @@ -9833,6 +9848,11 @@ int sched_cpu_deactivate(unsigned int cpu)
rq_lock_irqsave(rq, &rf);
if (rq->rd) {
BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
/*
* See the comment at scx_rq_activate() for why we can't simply
* use the rq_online() and rq_offline() callbacks.
*/
scx_rq_deactivate(rq);
set_rq_offline(rq);
}
rq_unlock_irqrestore(rq, &rf);
Expand Down
7 changes: 2 additions & 5 deletions kernel/sched/ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -3218,13 +3218,13 @@ static void handle_hotplug(struct rq *rq, bool online)
online ? "online" : "offline");
}

static void rq_online_scx(struct rq *rq)
void scx_rq_activate(struct rq *rq)
{
handle_hotplug(rq, true);
rq->scx.flags |= SCX_RQ_ONLINE;
}

static void rq_offline_scx(struct rq *rq)
void scx_rq_deactivate(struct rq *rq)
{
rq->scx.flags &= ~SCX_RQ_ONLINE;
handle_hotplug(rq, false);
Expand Down Expand Up @@ -3861,9 +3861,6 @@ DEFINE_SCHED_CLASS(ext) = {
.balance = balance_scx,
.select_task_rq = select_task_rq_scx,
.set_cpus_allowed = set_cpus_allowed_scx,

.rq_online = rq_online_scx,
.rq_offline = rq_offline_scx,
#endif

#ifdef CONFIG_SCHED_CORE
Expand Down
4 changes: 4 additions & 0 deletions kernel/sched/ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ int scx_check_setscheduler(struct task_struct *p, int policy);
bool scx_can_stop_tick(struct rq *rq);
bool task_should_scx(struct task_struct *p);
void init_sched_ext_class(void);
void scx_rq_activate(struct rq *rq);
void scx_rq_deactivate(struct rq *rq);

static inline u32 scx_cpuperf_target(s32 cpu)
{
Expand Down Expand Up @@ -100,6 +102,8 @@ static inline bool scx_can_stop_tick(struct rq *rq) { return true; }
static inline bool task_on_scx(const struct task_struct *p) { return false; }
static inline void init_sched_ext_class(void) {}
static inline u32 scx_cpuperf_target(s32 cpu) { return 0; }
static inline void scx_rq_activate(struct rq *rq) {}
static inline void scx_rq_deactivate(struct rq *rq) {}

#define for_each_active_class for_each_class
#define for_balance_class_range for_class_range
Expand Down

0 comments on commit 998970b

Please sign in to comment.