mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
sched_ext: Replay ecaps notifications suppressed by bypass
scx_process_sync_ecaps() consumes ecaps syncs while the sched is bypassing without delivering ops.sub_ecaps_updated(), leaving reported_ecaps stale. Nothing re-queued a sync when bypass lifted, so a cid whose caps never change again would never be notified. Attach-time initial grants hit this every time: they are consumed during the enable bypass window, so a sched never learned its initial effective caps through the callback. Re-queue a sync for every (sched, cpu) with an undelivered delta at the per-cpu bypass exit in scx_bypass(), next to the idle renotify catch-up. The next balance on the cpu then delivers the pending delta with proper dispatch context. Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
This commit is contained in:
parent
ca3aec453d
commit
75c268ed57
|
|
@ -5662,8 +5662,10 @@ void scx_bypass(struct scx_sched *sch, bool bypass)
|
|||
pcpu->flags |= SCX_SCHED_PCPU_BYPASSING;
|
||||
} else {
|
||||
pcpu->flags &= ~SCX_SCHED_PCPU_BYPASSING;
|
||||
if (was_bypassing)
|
||||
if (was_bypassing) {
|
||||
unbypass_renotify_idle(rq, pos, pcpu);
|
||||
scx_unbypass_replay_ecaps(rq, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -575,6 +575,41 @@ void scx_process_sync_ecaps(struct rq *rq, struct task_struct *prev)
|
|||
scx_schedule_reenq_local(rq, SCX_REENQ_CAP_REVOKE);
|
||||
}
|
||||
|
||||
/**
|
||||
* scx_unbypass_replay_ecaps - Replay a bypass-suppressed ecaps notification
|
||||
* @rq: rq of the cpu leaving bypass
|
||||
* @sch: scheduler that just left bypass on @rq's cpu
|
||||
*
|
||||
* scx_process_sync_ecaps() consumes syncs while bypassing without delivering
|
||||
* ops.sub_ecaps_updated(), leaving reported_ecaps stale. Nothing re-queues a
|
||||
* sync when bypass lifts, so without a replay a cid that never changes again
|
||||
* would never be notified. The attach-time initial grants are the acute case
|
||||
* as they are consumed during the enable bypass window. Re-queue a sync for
|
||||
* any undelivered delta so the next balance delivers it.
|
||||
*/
|
||||
void scx_unbypass_replay_ecaps(struct rq *rq, struct scx_sched *sch)
|
||||
{
|
||||
s32 cpu = cpu_of(rq);
|
||||
struct scx_sched_pcpu *pcpu = per_cpu_ptr(sch->pcpu, cpu);
|
||||
struct scx_pshard *ps;
|
||||
s32 cid;
|
||||
|
||||
lockdep_assert_rq_held(rq);
|
||||
|
||||
/* root holds every cap and never uses ecaps */
|
||||
if (!sch->level)
|
||||
return;
|
||||
|
||||
if (READ_ONCE(pcpu->ecaps) == pcpu->reported_ecaps)
|
||||
return;
|
||||
|
||||
cid = __scx_cpu_to_cid(cpu);
|
||||
ps = sch->pshard[scx_cid_to_shard[cid]];
|
||||
|
||||
guard(raw_spinlock)(&ps->lock);
|
||||
queue_sync_ecaps(sch, cid);
|
||||
}
|
||||
|
||||
/*
|
||||
* A cpu came back. Re-seed each sub-sched's ecaps on the cpu's cid. The sync
|
||||
* recomputes effective caps from the pshard and fires ops.sub_ecaps_updated()
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ void scx_free_pshards(struct scx_sched *sch);
|
|||
s32 scx_alloc_pshards(struct scx_sched *sch);
|
||||
void scx_init_root_caps(struct scx_sched *sch);
|
||||
void scx_process_sync_ecaps(struct rq *rq, struct task_struct *prev);
|
||||
void scx_unbypass_replay_ecaps(struct rq *rq, struct scx_sched *sch);
|
||||
void scx_online_ecaps(struct rq *rq);
|
||||
void scx_offline_ecaps(struct rq *rq);
|
||||
void scx_discard_ecaps_to_sync(s32 cpu, struct scx_sched_pcpu *pcpu);
|
||||
|
|
@ -58,6 +59,7 @@ static inline void scx_free_pshards(struct scx_sched *sch) {}
|
|||
static inline s32 scx_alloc_pshards(struct scx_sched *sch) { return 0; }
|
||||
static inline void scx_init_root_caps(struct scx_sched *sch) {}
|
||||
static inline void scx_process_sync_ecaps(struct rq *rq, struct task_struct *prev) {}
|
||||
static inline void scx_unbypass_replay_ecaps(struct rq *rq, struct scx_sched *sch) {}
|
||||
static inline void scx_online_ecaps(struct rq *rq) {}
|
||||
static inline void scx_offline_ecaps(struct rq *rq) {}
|
||||
static inline void scx_discard_ecaps_to_sync(s32 cpu, struct scx_sched_pcpu *pcpu) {}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user