mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
sched_ext: Merge branch 'for-7.3-fixes' into for-7.4
Pull to receive680edc7f23("sched_ext: Don't queue balance callbacks from a core-sched pick") and resolve its conflict with the proxy execution work here so that for-next merges clean. Conflicts: - do_pick_task_scx():680edc7f23samples sched_core_enabled() into a new local next to the prev declaration, which3d6577ea93("sched_ext: Split curr|donor references properly") changed to rq->donor. Kept rq->donor and added the local. Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
commit
9c0af54cb4
|
|
@ -3735,7 +3735,8 @@ static struct task_struct *first_local_task(struct rq *rq)
|
|||
}
|
||||
|
||||
/*
|
||||
* Run dispatch and queue the follow-up work for a pick.
|
||||
* Run dispatch for a pick. The follow-up work is queued by do_pick_task_scx()
|
||||
* once the pick is final.
|
||||
*/
|
||||
static enum scx_dsp_verdict dispatch_pick(struct rq *rq, struct rq_flags *rf,
|
||||
struct task_struct *prev)
|
||||
|
|
@ -3745,18 +3746,6 @@ static enum scx_dsp_verdict dispatch_pick(struct rq *rq, struct rq_flags *rf,
|
|||
rq_unpin_lock(rq, rf);
|
||||
verdict = dispatch_one(rq, prev);
|
||||
rq_repin_lock(rq, rf);
|
||||
maybe_queue_balance_callback(rq);
|
||||
|
||||
/*
|
||||
* Defer to a balance callback which can drop rq lock and enable IRQs.
|
||||
* Waiting directly in the pick path would deadlock against CPUs sending
|
||||
* us IPIs (e.g. TLB flushes) while we wait for them.
|
||||
*/
|
||||
if (unlikely(rq->scx.kick_sync_pending)) {
|
||||
rq->scx.kick_sync_pending = false;
|
||||
queue_balance_callback(rq, &rq->scx.kick_sync_bal_cb,
|
||||
kick_sync_wait_bal_cb);
|
||||
}
|
||||
|
||||
return verdict;
|
||||
}
|
||||
|
|
@ -3783,23 +3772,20 @@ static enum scx_dsp_verdict dispatch_core_pick(struct rq *rq, struct rq_flags *r
|
|||
|
||||
verdict = dispatch_one(rq, prev);
|
||||
|
||||
if (cpu_of(rq) == smp_processor_id()) {
|
||||
maybe_queue_balance_callback(rq);
|
||||
|
||||
/* see dispatch_pick() */
|
||||
if (unlikely(rq->scx.kick_sync_pending)) {
|
||||
rq->scx.kick_sync_pending = false;
|
||||
queue_balance_callback(rq, &rq->scx.kick_sync_bal_cb,
|
||||
kick_sync_wait_bal_cb);
|
||||
}
|
||||
} else if (unlikely(rq->scx.flags & SCX_RQ_BAL_CB_PENDING)) {
|
||||
/*
|
||||
* Balance callbacks must run in the context that queued them,
|
||||
* so they can't be queued on another CPU's rq. Run the deferred
|
||||
* work directly instead.
|
||||
*/
|
||||
/*
|
||||
* A pick that returns a task isn't final under core scheduling: the
|
||||
* selection goes on to pick the siblings, and their dispatch can
|
||||
* release the rq lock, which can't happen with balance callbacks
|
||||
* queued. Don't queue the deferred work as a balance callback, for this
|
||||
* CPU or a sibling, and run it from irq_work instead.
|
||||
*
|
||||
* do_pick_task_scx() leaves %SCX_RQ_BAL_CB_PENDING alone under core
|
||||
* scheduling, so that the early return above leaves it to the dispatch
|
||||
* in flight, which handles it here.
|
||||
*/
|
||||
if (unlikely(rq->scx.flags & SCX_RQ_BAL_CB_PENDING)) {
|
||||
rq->scx.flags &= ~SCX_RQ_BAL_CB_PENDING;
|
||||
run_deferred(rq);
|
||||
schedule_deferred(rq);
|
||||
}
|
||||
|
||||
rq_repin_lock(rq, rf);
|
||||
|
|
@ -3822,6 +3808,7 @@ static struct task_struct *
|
|||
do_pick_task_scx(struct rq *rq, struct rq_flags *rf, bool force_scx)
|
||||
{
|
||||
struct task_struct *prev = rq->donor;
|
||||
bool core_sched = sched_core_enabled(rq);
|
||||
enum scx_dsp_verdict verdict;
|
||||
struct task_struct *p;
|
||||
|
||||
|
|
@ -3833,13 +3820,20 @@ do_pick_task_scx(struct rq *rq, struct rq_flags *rf, bool force_scx)
|
|||
|
||||
rq_modified_begin(rq, &ext_sched_class);
|
||||
|
||||
if (sched_core_enabled(rq))
|
||||
/*
|
||||
* Core scheduling can get enabled while dispatch_pick() has the rq lock
|
||||
* released. Stick to @core_sched, so that the follow-up work below
|
||||
* matches the dispatch that ran.
|
||||
*/
|
||||
if (core_sched)
|
||||
verdict = dispatch_core_pick(rq, rf, prev);
|
||||
else
|
||||
verdict = dispatch_pick(rq, rf, prev);
|
||||
|
||||
if (verdict == SCX_DSP_RETRY)
|
||||
return RETRY_TASK;
|
||||
if (verdict == SCX_DSP_RETRY) {
|
||||
p = RETRY_TASK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If any higher-priority sched class enqueued a runnable task on this
|
||||
|
|
@ -3849,8 +3843,10 @@ do_pick_task_scx(struct rq *rq, struct rq_flags *rf, bool force_scx)
|
|||
* If @force_scx is true, always try to pick a SCHED_EXT task,
|
||||
* regardless of any higher-priority sched classes activity.
|
||||
*/
|
||||
if (!force_scx && rq_modified_above(rq, &ext_sched_class))
|
||||
return RETRY_TASK;
|
||||
if (!force_scx && rq_modified_above(rq, &ext_sched_class)) {
|
||||
p = RETRY_TASK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're keeping @prev, replenish slice if necessary and keep running
|
||||
|
|
@ -3866,7 +3862,7 @@ do_pick_task_scx(struct rq *rq, struct rq_flags *rf, bool force_scx)
|
|||
} else {
|
||||
p = first_local_task(rq);
|
||||
if (!p)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
if (unlikely(!p->scx.slice) && scx_task_can_stay_on_cpu(rq, p)) {
|
||||
struct scx_sched *sch = scx_task_sched(p);
|
||||
|
|
@ -3881,6 +3877,40 @@ do_pick_task_scx(struct rq *rq, struct rq_flags *rf, bool force_scx)
|
|||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (cpu_of(rq) != smp_processor_id())
|
||||
return p;
|
||||
|
||||
/*
|
||||
* Balance callbacks must be consumed before the rq lock is released, so
|
||||
* queue them only when the pick is final. On RETRY_TASK, or after a
|
||||
* NULL pick from the dl_server, the core continues picking and can
|
||||
* release the rq lock (e.g., prev_balance() or another dispatch). In
|
||||
* that case, run the deferred work from irq_work, which doesn't depend
|
||||
* on the current rq lock section, and leave the kick sync wait pending
|
||||
* for the next pick.
|
||||
*/
|
||||
if (p != RETRY_TASK && (p || !force_scx)) {
|
||||
/* under core scheduling, see dispatch_core_pick() */
|
||||
if (!core_sched)
|
||||
maybe_queue_balance_callback(rq);
|
||||
|
||||
/*
|
||||
* Defer to a balance callback which can drop rq lock and enable
|
||||
* IRQs. Waiting directly in the pick path would deadlock against
|
||||
* CPUs sending us IPIs (e.g., TLB flushes) while we wait for
|
||||
* them.
|
||||
*/
|
||||
if (unlikely(rq->scx.kick_sync_pending)) {
|
||||
rq->scx.kick_sync_pending = false;
|
||||
queue_balance_callback(rq, &rq->scx.kick_sync_bal_cb,
|
||||
kick_sync_wait_bal_cb);
|
||||
}
|
||||
} else if (!core_sched && (rq->scx.flags & SCX_RQ_BAL_CB_PENDING)) {
|
||||
rq->scx.flags &= ~SCX_RQ_BAL_CB_PENDING;
|
||||
schedule_deferred(rq);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user