diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index af207f03856d..9046b2ea68c6 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -9859,18 +9859,13 @@ static void wakeup_preempt_fair(struct rq *rq, struct task_struct *p, int wake_f cse_is_idle = se_is_idle(se); pse_is_idle = se_is_idle(pse); + nse = se; /* * Preempt an idle entity in favor of a non-idle entity (and don't preempt * in the inverse case). */ - if (cse_is_idle && !pse_is_idle) { - /* - * When non-idle entity preempt an idle entity, - * don't give idle entity slice protection. - */ - preempt_action = PREEMPT_WAKEUP_SHORT; + if (cse_is_idle && !pse_is_idle) goto preempt; - } if (cse_is_idle != pse_is_idle) return; @@ -9933,16 +9928,23 @@ static void wakeup_preempt_fair(struct rq *rq, struct task_struct *p, int wake_f goto preempt; } + /* + * If @p is eligible but not the next task to run then cancel protection + * to prevent large scheduling latency + */ + if (preempt_action == PREEMPT_WAKEUP_SHORT && entity_eligible(cfs_rq, pse)) + goto preempt; + if (sched_feat(RUN_TO_PARITY)) update_protect_slice(cfs_rq, se); return; preempt: - if (preempt_action == PREEMPT_WAKEUP_SHORT) { - cancel_protect_slice(se); + cancel_protect_slice(se); + + if (preempt_action == PREEMPT_WAKEUP_SHORT) set_short_buddy(cfs_rq, pse); - } resched_curr_lazy(rq); }