Signed-off-by: Peter Zijlstra (Intel) <pet...@infradead.org>
---
 kernel/sched/core.c     |    6 +++++-
 kernel/sched/deadline.c |    2 ++
 kernel/sched/fair.c     |   29 +++++++++++++++++++++++++++++
 kernel/sched/sched.h    |    6 +++++-
 4 files changed, 41 insertions(+), 2 deletions(-)

--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6501,6 +6504,7 @@ void __init sched_init(void)
 #endif /* CONFIG_SMP */
                hrtick_rq_init(rq);
                atomic_set(&rq->nr_iowait, 0);
+               fair_server_init(rq);
        }
 
        set_load_weight(&init_task, false);
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -5239,6 +5239,9 @@ enqueue_task_fair(struct rq *rq, struct
         */
        util_est_enqueue(&rq->cfs, p);
 
+       if (!rq->cfs.h_nr_running)
+               dl_server_start(&rq->fair_server);
+
        /*
         * If in_iowait is set, the code below may not trigger any cpufreq
         * utilization updates, so do it here explicitly with the IOWAIT flag
@@ -5374,6 +5377,9 @@ static void dequeue_task_fair(struct rq
        if (!se)
                sub_nr_running(rq, 1);
 
+       if (!rq->cfs.h_nr_running)
+               dl_server_stop(&rq->fair_server);
+
        util_est_dequeue(&rq->cfs, p, task_sleep);
        hrtick_update(rq);
 }
@@ -6903,6 +6909,29 @@ done: __maybe_unused;
        return NULL;
 }
 
+static bool fair_server_has_tasks(struct sched_dl_entity *dl_se)
+{
+       return !!dl_se->rq->cfs.nr_running;
+}
+
+static struct task_struct *fair_server_pick(struct sched_dl_entity *dl_se)
+{
+       return pick_next_task_fair(dl_se->rq, NULL, NULL);
+}
+
+void fair_server_init(struct rq *rq)
+{
+       struct sched_dl_entity *dl_se = &rq->fair_server;
+
+       init_dl_entity(dl_se);
+
+       dl_se->dl_runtime = TICK_NSEC;
+       dl_se->dl_deadline = 20 * TICK_NSEC;
+       dl_se->dl_period = 20 * TICK_NSEC;
+
+       dl_server_init(dl_se, rq, fair_server_has_tasks, fair_server_pick);
+}
+
 /*
  * Account for a descheduled task:
  */
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -345,6 +345,8 @@ extern void dl_server_init(struct sched_
                    dl_server_has_tasks_f has_tasks,
                    dl_server_pick_f pick);
 
+extern void fair_server_init(struct rq *);
+
 #ifdef CONFIG_CGROUP_SCHED
 
 #include <linux/cgroup.h>
@@ -905,6 +907,8 @@ struct rq {
        struct rt_rq            rt;
        struct dl_rq            dl;
 
+       struct sched_dl_entity  fair_server;
+
 #ifdef CONFIG_FAIR_GROUP_SCHED
        /* list of leaf cfs_rq on this CPU: */
        struct list_head        leaf_cfs_rq_list;
@@ -968,7 +972,7 @@ struct rq {
 
        /* This is used to determine avg_idle's max value */
        u64                     max_idle_balance_cost;
-#endif
+#endif /* CONFIG_SMP */
 
 #ifdef CONFIG_IRQ_TIME_ACCOUNTING
        u64                     prev_irq_time;


Reply via email to