Subject: sched: next task selection variants Add a sched features that runs expired deadlines. Signed-off-by: Peter Zijlstra --- include/linux/sched.h | 1 kernel/sched.c | 1 kernel/sched_debug.c | 1 kernel/sched_fair.c | 54 +++++++++++++++++++++++++++++++++++++++++++++--- kernel/sched_features.h | 1 5 files changed, 55 insertions(+), 3 deletions(-) Index: linux-2.6/include/linux/sched.h =================================================================== --- linux-2.6.orig/include/linux/sched.h +++ linux-2.6/include/linux/sched.h @@ -957,6 +957,7 @@ struct sched_entity { #ifdef CONFIG_FAIR_GROUP_SCHED u64 deadline; u64 min_deadline; + unsigned int eligible; #endif unsigned int on_rq; struct list_head group_node; Index: linux-2.6/kernel/sched_fair.c =================================================================== --- linux-2.6.orig/kernel/sched_fair.c +++ linux-2.6/kernel/sched_fair.c @@ -478,10 +478,46 @@ static struct sched_entity *__pick_next_ static struct sched_entity *__pick_next_entity(struct cfs_root_rq *cfs_r_rq) { - if (!sched_feat(EEDF)) - return __pick_next_timeline(cfs_r_rq); + struct rb_node *node; + struct sched_entity *next; - return __pick_next_eedf(cfs_r_rq); + if (!sched_feat(EEDF)) { + if (sched_feat(DEADLINE)) { + next = __pick_next_edf(cfs_r_rq); + + next->eligible = entity_eligible(cfs_r_rq, next); + + if (next->eligible || entity_expired(cfs_r_rq, next)) + return next; + } + + next = __pick_next_timeline(cfs_r_rq); + next->eligible = 1; + + return next; + } + + node = cfs_r_rq->tasks_timeline.rb_node; + + /* + * If the smallest deadline has expired, pick that; if it's not + * eligible - penalize its slice but run it anyway. + */ + if (sched_feat(DEADLINE) && + deadline_expired(cfs_r_rq, se_of(node)->min_deadline)) { + struct sched_entity *next = __pick_next_edf(cfs_r_rq); + + schedstat_inc(container_of(cfs_r_rq, struct rq, cfs_root), + sched_expired); + + next->eligible = entity_eligible(cfs_r_rq, next); + return next; + } + + next = __pick_next_eedf(cfs_r_rq); + next->eligible = 1; + + return next; } /* @@ -822,6 +858,12 @@ static u64 sched_slice(struct cfs_rq *cf #ifdef CONFIG_FAIR_GROUP_SCHED /* + * Shorten the slice a little, so that we're just short of target. + * This avoids us running over the deadline all the time. + */ + slice -= slice / 8; + + /* * Limit the max slice length when there is contention (strictly * speaking we only need to do this when there are tasks of more * than a single group). This avoids very longs slices of a lightly @@ -829,6 +871,12 @@ static u64 sched_slice(struct cfs_rq *cf */ if (rq_of(cfs_rq)->cfs_root.nr_queued) slice = min_t(u64, slice, sysctl_sched_min_granularity); + + /* + * This task runs, even though it is not eligible for time; penalize it. + */ + if (!se->eligible) + slice /= 8; #endif return slice; Index: linux-2.6/kernel/sched_features.h =================================================================== --- linux-2.6.orig/kernel/sched_features.h +++ linux-2.6/kernel/sched_features.h @@ -8,6 +8,7 @@ SCHED_FEAT(HRTICK, 1) SCHED_FEAT(DOUBLE_TICK, 0) SCHED_FEAT(NORMALIZED_SLEEPER, 1) #ifdef CONFIG_FAIR_GROUP_SCHED +SCHED_FEAT(DEADLINE, 0) SCHED_FEAT(EEDF, 1) #endif SCHED_FEAT(ASYM_GRAN, 1) Index: linux-2.6/kernel/sched.c =================================================================== --- linux-2.6.orig/kernel/sched.c +++ linux-2.6/kernel/sched.c @@ -583,6 +583,7 @@ struct rq { unsigned int sched_switch; unsigned int sched_count; unsigned int sched_goidle; + unsigned int sched_expired; /* try_to_wake_up() stats */ unsigned int ttwu_count; Index: linux-2.6/kernel/sched_debug.c =================================================================== --- linux-2.6.orig/kernel/sched_debug.c +++ linux-2.6/kernel/sched_debug.c @@ -231,6 +231,7 @@ static void print_cpu(struct seq_file *m PN(next_balance); P(curr->pid); PN(clock); + P(sched_expired); P(cpu_load[0]); P(cpu_load[1]); P(cpu_load[2]);