Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

sched/fair: Remove spurious shorter slice preemption

Even if the waking task can preempt current, it might not be the one
selected by pick_task_fair. Check that the waking task will be selected
if we cancel the slice protection before doing so.

Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20250708165630.1948751-4-vincent.guittot@linaro.org

authored by

Vincent Guittot and committed by
Peter Zijlstra
9de74a98 74eec636

+14 -30
+14 -30
kernel/sched/fair.c
··· 932 932 * 933 933 * Which allows tree pruning through eligibility. 934 934 */ 935 - static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq) 935 + static struct sched_entity *__pick_eevdf(struct cfs_rq *cfs_rq, bool protect) 936 936 { 937 937 struct rb_node *node = cfs_rq->tasks_timeline.rb_root.rb_node; 938 938 struct sched_entity *se = __pick_first_entity(cfs_rq); ··· 949 949 if (curr && (!curr->on_rq || !entity_eligible(cfs_rq, curr))) 950 950 curr = NULL; 951 951 952 - if (curr && protect_slice(curr)) 952 + if (curr && protect && protect_slice(curr)) 953 953 return curr; 954 954 955 955 /* Pick the leftmost entity if it's eligible */ ··· 991 991 best = curr; 992 992 993 993 return best; 994 + } 995 + 996 + static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq) 997 + { 998 + return __pick_eevdf(cfs_rq, true); 994 999 } 995 1000 996 1001 struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq) ··· 1179 1174 return false; 1180 1175 1181 1176 return !entity_eligible(cfs_rq, curr); 1182 - } 1183 - 1184 - static inline bool do_preempt_short(struct cfs_rq *cfs_rq, 1185 - struct sched_entity *pse, struct sched_entity *se) 1186 - { 1187 - if (!sched_feat(PREEMPT_SHORT)) 1188 - return false; 1189 - 1190 - if (pse->slice >= se->slice) 1191 - return false; 1192 - 1193 - if (!entity_eligible(cfs_rq, pse)) 1194 - return false; 1195 - 1196 - if (entity_before(pse, se)) 1197 - return true; 1198 - 1199 - if (!entity_eligible(cfs_rq, se)) 1200 - return true; 1201 - 1202 - return false; 1203 1177 } 1204 1178 1205 1179 /* ··· 8642 8658 struct sched_entity *se = &donor->se, *pse = &p->se; 8643 8659 struct cfs_rq *cfs_rq = task_cfs_rq(donor); 8644 8660 int cse_is_idle, pse_is_idle; 8661 + bool do_preempt_short = false; 8645 8662 8646 8663 if (unlikely(se == pse)) 8647 8664 return; ··· 8691 8706 * When non-idle entity preempt an idle entity, 8692 8707 * don't give idle entity slice protection. 8693 8708 */ 8694 - cancel_protect_slice(se); 8709 + do_preempt_short = true; 8695 8710 goto preempt; 8696 8711 } 8697 8712 ··· 8709 8724 /* 8710 8725 * If @p has a shorter slice than current and @p is eligible, override 8711 8726 * current's slice protection in order to allow preemption. 8712 - * 8713 - * Note that even if @p does not turn out to be the most eligible 8714 - * task at this moment, current's slice protection will be lost. 8715 8727 */ 8716 - if (do_preempt_short(cfs_rq, pse, se)) 8717 - cancel_protect_slice(se); 8728 + do_preempt_short = sched_feat(PREEMPT_SHORT) && (pse->slice < se->slice); 8718 8729 8719 8730 /* 8720 8731 * If @p has become the most eligible task, force preemption. 8721 8732 */ 8722 - if (pick_eevdf(cfs_rq) == pse) 8733 + if (__pick_eevdf(cfs_rq, !do_preempt_short) == pse) 8723 8734 goto preempt; 8724 8735 8725 8736 return; 8726 8737 8727 8738 preempt: 8739 + if (do_preempt_short) 8740 + cancel_protect_slice(se); 8741 + 8728 8742 resched_curr_lazy(rq); 8729 8743 } 8730 8744