mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
sched_ext: Block proxy donors before taking control
Proxy execution retains mutex-blocked donors on the runqueue so their scheduling context can execute a lock owner. sched_ext cannot safely inherit such donors unless the BPF scheduler explicitly participates in their admission and ordering. Make sched_ext reject retained donors by default. Implement scx_allow_proxy_exec() to force blocked EXT tasks through the regular block path in schedule(). A donor retained by another scheduling class may already be queued when sched_ext is enabled or when a task switches to SCHED_EXT. Fully block the donor before sched_change_begin() records its queued state. This prevents sched_ext from importing a proxy session which the BPF scheduler did not admit, while leaving ordinary FAIR, RT and DL class transitions untouched. This is a preparatory change to support proxy execution with sched_ext. Signed-off-by: Andrea Righi <arighi@nvidia.com> Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
parent
6ff8452f63
commit
be8be8acb2
|
|
@ -26,7 +26,22 @@ DEFINE_RAW_SPINLOCK(scx_sched_lock);
|
|||
|
||||
bool scx_allow_proxy_exec(const struct task_struct *p)
|
||||
{
|
||||
return true;
|
||||
return p->sched_class != &ext_sched_class;
|
||||
}
|
||||
|
||||
/*
|
||||
* End retained proxy execution before sched_ext takes ownership of @p.
|
||||
* Called with @p's pi and rq locks held immediately before
|
||||
* sched_change_begin(). The caller must pass DEQUEUE_NOCLOCK so the rq clock
|
||||
* is updated only once.
|
||||
*/
|
||||
static void scx_prepare_task_sched_change(struct task_struct *p)
|
||||
{
|
||||
lockdep_assert_held(&p->pi_lock);
|
||||
lockdep_assert_rq_held(task_rq(p));
|
||||
|
||||
update_rq_clock(task_rq(p));
|
||||
sched_proxy_block_task(task_rq(p), p);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -4438,7 +4453,7 @@ int scx_check_setscheduler(struct task_struct *p, int policy)
|
|||
{
|
||||
lockdep_assert_rq_held(task_rq(p));
|
||||
|
||||
/* if disallow, reject transitioning into SCX */
|
||||
/* If disallow, reject transitioning into SCX. */
|
||||
if (scx_enabled() && READ_ONCE(p->scx.disallow) &&
|
||||
p->policy != policy && policy == SCHED_EXT)
|
||||
return -EACCES;
|
||||
|
|
@ -4446,6 +4461,20 @@ int scx_check_setscheduler(struct task_struct *p, int policy)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't carry a donor retained by another class into sched_ext. The caller
|
||||
* has updated the rq clock and invokes this immediately before
|
||||
* sched_change_begin() records the task's queued state.
|
||||
*/
|
||||
void scx_prepare_setscheduler(struct task_struct *p, int policy)
|
||||
{
|
||||
lockdep_assert_held(&p->pi_lock);
|
||||
lockdep_assert_rq_held(task_rq(p));
|
||||
|
||||
if (scx_enabled() && p->policy != policy && policy == SCHED_EXT)
|
||||
sched_proxy_block_task(task_rq(p), p);
|
||||
}
|
||||
|
||||
static void process_ddsp_deferred_locals(struct rq *rq)
|
||||
{
|
||||
struct task_struct *p;
|
||||
|
|
@ -7994,6 +8023,10 @@ static void scx_root_enable_workfn(struct kthread_work *work)
|
|||
|
||||
if (old_class != new_class)
|
||||
queue_flags |= DEQUEUE_CLASS;
|
||||
if (new_class == &ext_sched_class) {
|
||||
scx_prepare_task_sched_change(p);
|
||||
queue_flags |= DEQUEUE_NOCLOCK;
|
||||
}
|
||||
|
||||
scoped_guard (sched_change, p, queue_flags) {
|
||||
scx_set_task_slice(p, READ_ONCE(sch->slice_dfl));
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ bool scx_can_stop_tick(struct rq *rq);
|
|||
void scx_rq_activate(struct rq *rq);
|
||||
void scx_rq_deactivate(struct rq *rq);
|
||||
int scx_check_setscheduler(struct task_struct *p, int policy);
|
||||
void scx_prepare_setscheduler(struct task_struct *p, int policy);
|
||||
bool task_should_scx(int policy);
|
||||
bool scx_allow_ttwu_queue(const struct task_struct *p);
|
||||
bool scx_allow_proxy_exec(const struct task_struct *p);
|
||||
|
|
@ -62,6 +63,7 @@ static inline bool scx_can_stop_tick(struct rq *rq) { return true; }
|
|||
static inline void scx_rq_activate(struct rq *rq) {}
|
||||
static inline void scx_rq_deactivate(struct rq *rq) {}
|
||||
static inline int scx_check_setscheduler(struct task_struct *p, int policy) { return 0; }
|
||||
static inline void scx_prepare_setscheduler(struct task_struct *p, int policy) {}
|
||||
static inline bool task_on_scx(const struct task_struct *p) { return false; }
|
||||
static inline bool scx_allow_ttwu_queue(const struct task_struct *p) { return true; }
|
||||
static inline bool scx_allow_proxy_exec(const struct task_struct *p) { return true; }
|
||||
|
|
|
|||
|
|
@ -678,6 +678,8 @@ int __sched_setscheduler(struct task_struct *p,
|
|||
if (prev_class != next_class)
|
||||
queue_flags |= DEQUEUE_CLASS;
|
||||
|
||||
scx_prepare_setscheduler(p, policy);
|
||||
|
||||
scoped_guard (sched_change, p, queue_flags) {
|
||||
|
||||
if (!(attr->sched_flags & SCHED_FLAG_KEEP_PARAMS)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user