sched/fair: add triggers for OPP change requests
authorJuri Lelli <juri.lelli@arm.com>
Wed, 19 Aug 2015 18:47:12 +0000 (19:47 +0100)
committerLeo Yan <leo.yan@linaro.org>
Tue, 10 May 2016 08:53:22 +0000 (16:53 +0800)
Each time a task is {en,de}queued we might need to adapt the current
frequency to the new usage. Add triggers on {en,de}queue_task_fair() for
this purpose.  Only trigger a freq request if we are effectively waking up
or going to sleep.  Filter out load balancing related calls to reduce the
number of triggers.

[smuckle@linaro.org: resolve merge conflicts, define task_new,
 use renamed static key sched_freq]

cc: Ingo Molnar <mingo@redhat.com>
cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
Signed-off-by: Steve Muckle <smuckle@linaro.org>
kernel/sched/fair.c

index 3eb5beb590a8bfefc7ea273f20f284ed0c91f92f..844788da00bea14eff07192c5fb462bf5242d46c 100644 (file)
@@ -4144,6 +4144,21 @@ static inline void hrtick_update(struct rq *rq)
 }
 #endif
 
+static unsigned long capacity_orig_of(int cpu);
+static int cpu_util(int cpu);
+
+static void update_capacity_of(int cpu)
+{
+       unsigned long req_cap;
+
+       if (!sched_freq())
+               return;
+
+       /* Convert scale-invariant capacity to cpu. */
+       req_cap = cpu_util(cpu) * SCHED_CAPACITY_SCALE / capacity_orig_of(cpu);
+       set_cfs_cpu_capacity(cpu, true, req_cap);
+}
+
 static bool cpu_overutilized(int cpu);
 
 /*
@@ -4193,6 +4208,20 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
                if (!task_new && !rq->rd->overutilized &&
                    cpu_overutilized(rq->cpu))
                        rq->rd->overutilized = true;
+
+               /*
+                * We want to potentially trigger a freq switch
+                * request only for tasks that are waking up; this is
+                * because we get here also during load balancing, but
+                * in these cases it seems wise to trigger as single
+                * request after load balancing is done.
+                *
+                * XXX: how about fork()? Do we need a special
+                *      flag/something to tell if we are here after a
+                *      fork() (wakeup_task_new)?
+                */
+               if (!task_new)
+                       update_capacity_of(cpu_of(rq));
        }
        hrtick_update(rq);
 }
@@ -4251,9 +4280,24 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
                update_cfs_shares(cfs_rq);
        }
 
-       if (!se)
+       if (!se) {
                sub_nr_running(rq, 1);
 
+               /*
+                * We want to potentially trigger a freq switch
+                * request only for tasks that are going to sleep;
+                * this is because we get here also during load
+                * balancing, but in these cases it seems wise to
+                * trigger as single request after load balancing is
+                * done.
+                */
+               if (task_sleep) {
+                       if (rq->cfs.nr_running)
+                               update_capacity_of(cpu_of(rq));
+                       else if (sched_freq())
+                               set_cfs_cpu_capacity(cpu_of(rq), false, 0);
+               }
+       }
        hrtick_update(rq);
 }