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: Fix NO_RUN_TO_PARITY case

EEVDF expects the scheduler to allocate a time quantum to the selected
entity and then pick a new entity for next quantum.
Although this notion of time quantum is not strictly doable in our case,
we can ensure a minimum runtime for each task most of the time and pick a
new entity after a minimum time has elapsed.
Reuse the slice protection of run to parity to ensure such runtime
quantum.

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-3-vincent.guittot@linaro.org

authored by

Vincent Guittot and committed by
Peter Zijlstra
74eec636 9cdb4fe2

+29 -12
+9 -1
include/linux/sched.h
··· 583 583 u64 sum_exec_runtime; 584 584 u64 prev_sum_exec_runtime; 585 585 u64 vruntime; 586 - s64 vlag; 586 + union { 587 + /* 588 + * When !@on_rq this field is vlag. 589 + * When cfs_rq->curr == se (which implies @on_rq) 590 + * this field is vprot. See protect_slice(). 591 + */ 592 + s64 vlag; 593 + u64 vprot; 594 + }; 587 595 u64 slice; 588 596 589 597 u64 nr_migrations;
+20 -11
kernel/sched/fair.c
··· 882 882 } 883 883 884 884 /* 885 - * HACK, stash a copy of deadline at the point of pick in vlag, 886 - * which isn't used until dequeue. 885 + * Set the vruntime up to which an entity can run before looking 886 + * for another entity to pick. 887 + * In case of run to parity, we protect the entity up to its deadline. 888 + * When run to parity is disabled, we give a minimum quantum to the running 889 + * entity to ensure progress. 887 890 */ 888 891 static inline void set_protect_slice(struct sched_entity *se) 889 892 { 890 - se->vlag = se->deadline; 893 + u64 slice = se->slice; 894 + u64 vprot = se->deadline; 895 + 896 + if (!sched_feat(RUN_TO_PARITY)) 897 + slice = min(slice, normalized_sysctl_sched_base_slice); 898 + 899 + if (slice != se->slice) 900 + vprot = min_vruntime(vprot, se->vruntime + calc_delta_fair(slice, se)); 901 + 902 + se->vprot = vprot; 891 903 } 892 904 893 905 static inline bool protect_slice(struct sched_entity *se) 894 906 { 895 - return se->vlag == se->deadline; 907 + return ((s64)(se->vprot - se->vruntime) > 0); 896 908 } 897 909 898 910 static inline void cancel_protect_slice(struct sched_entity *se) 899 911 { 900 912 if (protect_slice(se)) 901 - se->vlag = se->deadline + 1; 913 + se->vprot = se->vruntime; 902 914 } 903 915 904 916 /* ··· 949 937 if (curr && (!curr->on_rq || !entity_eligible(cfs_rq, curr))) 950 938 curr = NULL; 951 939 952 - if (sched_feat(RUN_TO_PARITY) && curr && protect_slice(curr)) 940 + if (curr && protect_slice(curr)) 953 941 return curr; 954 942 955 943 /* Pick the leftmost entity if it's eligible */ ··· 1168 1156 cgroup_account_cputime(p, delta_exec); 1169 1157 } 1170 1158 1171 - static inline bool did_preempt_short(struct cfs_rq *cfs_rq, struct sched_entity *curr) 1159 + static inline bool resched_next_slice(struct cfs_rq *cfs_rq, struct sched_entity *curr) 1172 1160 { 1173 - if (!sched_feat(PREEMPT_SHORT)) 1174 - return false; 1175 - 1176 1161 if (protect_slice(curr)) 1177 1162 return false; 1178 1163 ··· 1257 1248 if (cfs_rq->nr_queued == 1) 1258 1249 return; 1259 1250 1260 - if (resched || did_preempt_short(cfs_rq, curr)) { 1251 + if (resched || resched_next_slice(cfs_rq, curr)) { 1261 1252 resched_curr_lazy(rq); 1262 1253 clear_buddies(cfs_rq, curr); 1263 1254 }