mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
sched_ext: Split schedule_deferred() into locked and unlocked variants
schedule_deferred() currently requires the rq lock to be held so that it can use scheduler hooks for efficiency when available. However, there are cases where deferred actions need to be scheduled from contexts that don't hold the rq lock. Split into schedule_deferred() which can be called from any context and just queues irq_work, and schedule_deferred_locked() which requires the rq lock and can optimize by using scheduler hooks when available. Update the existing call site to use the _locked variant. Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com> Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
@@ -775,11 +775,27 @@ static void deferred_irq_workfn(struct irq_work *irq_work)
|
||||
* schedule_deferred - Schedule execution of deferred actions on an rq
|
||||
* @rq: target rq
|
||||
*
|
||||
* Schedule execution of deferred actions on @rq. Must be called with @rq
|
||||
* locked. Deferred actions are executed with @rq locked but unpinned, and thus
|
||||
* can unlock @rq to e.g. migrate tasks to other rqs.
|
||||
* Schedule execution of deferred actions on @rq. Deferred actions are executed
|
||||
* with @rq locked but unpinned, and thus can unlock @rq to e.g. migrate tasks
|
||||
* to other rqs.
|
||||
*/
|
||||
static void schedule_deferred(struct rq *rq)
|
||||
{
|
||||
/*
|
||||
* Queue an irq work. They are executed on IRQ re-enable which may take
|
||||
* a bit longer than the scheduler hook in schedule_deferred_locked().
|
||||
*/
|
||||
irq_work_queue(&rq->scx.deferred_irq_work);
|
||||
}
|
||||
|
||||
/**
|
||||
* schedule_deferred_locked - Schedule execution of deferred actions on an rq
|
||||
* @rq: target rq
|
||||
*
|
||||
* Schedule execution of deferred actions on @rq. Equivalent to
|
||||
* schedule_deferred() but requires @rq to be locked and can be more efficient.
|
||||
*/
|
||||
static void schedule_deferred_locked(struct rq *rq)
|
||||
{
|
||||
lockdep_assert_rq_held(rq);
|
||||
|
||||
@@ -812,12 +828,11 @@ static void schedule_deferred(struct rq *rq)
|
||||
}
|
||||
|
||||
/*
|
||||
* No scheduler hooks available. Queue an irq work. They are executed on
|
||||
* IRQ re-enable which may take a bit longer than the scheduler hooks.
|
||||
* The above WAKEUP and BALANCE paths should cover most of the cases and
|
||||
* the time to IRQ re-enable shouldn't be long.
|
||||
* No scheduler hooks available. Use the generic irq_work path. The
|
||||
* above WAKEUP and BALANCE paths should cover most of the cases and the
|
||||
* time to IRQ re-enable shouldn't be long.
|
||||
*/
|
||||
irq_work_queue(&rq->scx.deferred_irq_work);
|
||||
schedule_deferred(rq);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1211,7 +1226,7 @@ static void direct_dispatch(struct scx_sched *sch, struct task_struct *p,
|
||||
WARN_ON_ONCE(p->scx.dsq || !list_empty(&p->scx.dsq_list.node));
|
||||
list_add_tail(&p->scx.dsq_list.node,
|
||||
&rq->scx.ddsp_deferred_locals);
|
||||
schedule_deferred(rq);
|
||||
schedule_deferred_locked(rq);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user