aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched
diff options
context:
space:
mode:
authorSteve Muckle <steve.muckle@linaro.org>2016-03-24 18:26:07 -0400
committerIngo Molnar <mingo@kernel.org>2016-04-23 08:20:40 -0400
commita2c6c91f98247fef0fe75216d607812485aeb0df (patch)
tree6869393fd94f588a69e079f9ae4ea14d1dc68562 /kernel/sched
parent41e0d37f7ac81297c07ba311e4ad39465b8c8295 (diff)
sched/fair: Call cpufreq hook in additional paths
The cpufreq hook should be called any time the root CFS rq utilization changes. This can occur when a task is switched to or from the fair class, or a task moves between groups or CPUs, but these paths currently do not call the cpufreq hook. Fix this by adding the hook to attach_entity_load_avg() and detach_entity_load_avg(). Suggested-by: Vincent Guittot <vincent.guittot@linaro.org> Signed-off-by: Steve Muckle <smuckle@linaro.org> [ Added the .update_freq argument to update_cfs_rq_load_avg() to avoid a double cpufreq call. ] Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Byungchul Park <byungchul.park@lge.com> Cc: Dietmar Eggemann <dietmar.eggemann@arm.com> Cc: Juri Lelli <Juri.Lelli@arm.com> Cc: Michael Turquette <mturquette@baylibre.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Morten Rasmussen <morten.rasmussen@arm.com> Cc: Patrick Bellasi <patrick.bellasi@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Rafael J. Wysocki <rafael@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/1458858367-2831-1-git-send-email-smuckle@linaro.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/sched')
-rw-r--r--kernel/sched/fair.c73
1 files changed, 42 insertions, 31 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 81552819444c..c328bd77fe35 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -2874,13 +2874,41 @@ static inline void update_tg_load_avg(struct cfs_rq *cfs_rq, int force) {}
2874 2874
2875static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq); 2875static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq);
2876 2876
2877static inline void cfs_rq_util_change(struct cfs_rq *cfs_rq)
2878{
2879 struct rq *rq = rq_of(cfs_rq);
2880 int cpu = cpu_of(rq);
2881
2882 if (cpu == smp_processor_id() && &rq->cfs == cfs_rq) {
2883 unsigned long max = rq->cpu_capacity_orig;
2884
2885 /*
2886 * There are a few boundary cases this might miss but it should
2887 * get called often enough that that should (hopefully) not be
2888 * a real problem -- added to that it only calls on the local
2889 * CPU, so if we enqueue remotely we'll miss an update, but
2890 * the next tick/schedule should update.
2891 *
2892 * It will not get called when we go idle, because the idle
2893 * thread is a different class (!fair), nor will the utilization
2894 * number include things like RT tasks.
2895 *
2896 * As is, the util number is not freq-invariant (we'd have to
2897 * implement arch_scale_freq_capacity() for that).
2898 *
2899 * See cpu_util().
2900 */
2901 cpufreq_update_util(rq_clock(rq),
2902 min(cfs_rq->avg.util_avg, max), max);
2903 }
2904}
2905
2877/* Group cfs_rq's load_avg is used for task_h_load and update_cfs_share */ 2906/* Group cfs_rq's load_avg is used for task_h_load and update_cfs_share */
2878static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) 2907static inline int
2908update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq, bool update_freq)
2879{ 2909{
2880 struct sched_avg *sa = &cfs_rq->avg; 2910 struct sched_avg *sa = &cfs_rq->avg;
2881 struct rq *rq = rq_of(cfs_rq);
2882 int decayed, removed_load = 0, removed_util = 0; 2911 int decayed, removed_load = 0, removed_util = 0;
2883 int cpu = cpu_of(rq);
2884 2912
2885 if (atomic_long_read(&cfs_rq->removed_load_avg)) { 2913 if (atomic_long_read(&cfs_rq->removed_load_avg)) {
2886 s64 r = atomic_long_xchg(&cfs_rq->removed_load_avg, 0); 2914 s64 r = atomic_long_xchg(&cfs_rq->removed_load_avg, 0);
@@ -2896,7 +2924,7 @@ static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
2896 removed_util = 1; 2924 removed_util = 1;
2897 } 2925 }
2898 2926
2899 decayed = __update_load_avg(now, cpu, sa, 2927 decayed = __update_load_avg(now, cpu_of(rq_of(cfs_rq)), sa,
2900 scale_load_down(cfs_rq->load.weight), cfs_rq->curr != NULL, cfs_rq); 2928 scale_load_down(cfs_rq->load.weight), cfs_rq->curr != NULL, cfs_rq);
2901 2929
2902#ifndef CONFIG_64BIT 2930#ifndef CONFIG_64BIT
@@ -2904,29 +2932,8 @@ static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
2904 cfs_rq->load_last_update_time_copy = sa->last_update_time; 2932 cfs_rq->load_last_update_time_copy = sa->last_update_time;
2905#endif 2933#endif
2906 2934
2907 if (cpu == smp_processor_id() && &rq->cfs == cfs_rq && 2935 if (update_freq && (decayed || removed_util))
2908 (decayed || removed_util)) { 2936 cfs_rq_util_change(cfs_rq);
2909 unsigned long max = rq->cpu_capacity_orig;
2910
2911 /*
2912 * There are a few boundary cases this might miss but it should
2913 * get called often enough that that should (hopefully) not be
2914 * a real problem -- added to that it only calls on the local
2915 * CPU, so if we enqueue remotely we'll miss an update, but
2916 * the next tick/schedule should update.
2917 *
2918 * It will not get called when we go idle, because the idle
2919 * thread is a different class (!fair), nor will the utilization
2920 * number include things like RT tasks.
2921 *
2922 * As is, the util number is not freq-invariant (we'd have to
2923 * implement arch_scale_freq_capacity() for that).
2924 *
2925 * See cpu_util().
2926 */
2927 cpufreq_update_util(rq_clock(rq),
2928 min(sa->util_avg, max), max);
2929 }
2930 2937
2931 return decayed || removed_load; 2938 return decayed || removed_load;
2932} 2939}
@@ -2947,7 +2954,7 @@ static inline void update_load_avg(struct sched_entity *se, int update_tg)
2947 se->on_rq * scale_load_down(se->load.weight), 2954 se->on_rq * scale_load_down(se->load.weight),
2948 cfs_rq->curr == se, NULL); 2955 cfs_rq->curr == se, NULL);
2949 2956
2950 if (update_cfs_rq_load_avg(now, cfs_rq) && update_tg) 2957 if (update_cfs_rq_load_avg(now, cfs_rq, true) && update_tg)
2951 update_tg_load_avg(cfs_rq, 0); 2958 update_tg_load_avg(cfs_rq, 0);
2952} 2959}
2953 2960
@@ -2976,6 +2983,8 @@ skip_aging:
2976 cfs_rq->avg.load_sum += se->avg.load_sum; 2983 cfs_rq->avg.load_sum += se->avg.load_sum;
2977 cfs_rq->avg.util_avg += se->avg.util_avg; 2984 cfs_rq->avg.util_avg += se->avg.util_avg;
2978 cfs_rq->avg.util_sum += se->avg.util_sum; 2985 cfs_rq->avg.util_sum += se->avg.util_sum;
2986
2987 cfs_rq_util_change(cfs_rq);
2979} 2988}
2980 2989
2981static void detach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se) 2990static void detach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se)
@@ -2988,6 +2997,8 @@ static void detach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *s
2988 cfs_rq->avg.load_sum = max_t(s64, cfs_rq->avg.load_sum - se->avg.load_sum, 0); 2997 cfs_rq->avg.load_sum = max_t(s64, cfs_rq->avg.load_sum - se->avg.load_sum, 0);
2989 cfs_rq->avg.util_avg = max_t(long, cfs_rq->avg.util_avg - se->avg.util_avg, 0); 2998 cfs_rq->avg.util_avg = max_t(long, cfs_rq->avg.util_avg - se->avg.util_avg, 0);
2990 cfs_rq->avg.util_sum = max_t(s32, cfs_rq->avg.util_sum - se->avg.util_sum, 0); 2999 cfs_rq->avg.util_sum = max_t(s32, cfs_rq->avg.util_sum - se->avg.util_sum, 0);
3000
3001 cfs_rq_util_change(cfs_rq);
2991} 3002}
2992 3003
2993/* Add the load generated by se into cfs_rq's load average */ 3004/* Add the load generated by se into cfs_rq's load average */
@@ -3005,7 +3016,7 @@ enqueue_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se)
3005 cfs_rq->curr == se, NULL); 3016 cfs_rq->curr == se, NULL);
3006 } 3017 }
3007 3018
3008 decayed = update_cfs_rq_load_avg(now, cfs_rq); 3019 decayed = update_cfs_rq_load_avg(now, cfs_rq, !migrated);
3009 3020
3010 cfs_rq->runnable_load_avg += sa->load_avg; 3021 cfs_rq->runnable_load_avg += sa->load_avg;
3011 cfs_rq->runnable_load_sum += sa->load_sum; 3022 cfs_rq->runnable_load_sum += sa->load_sum;
@@ -6213,7 +6224,7 @@ static void update_blocked_averages(int cpu)
6213 if (throttled_hierarchy(cfs_rq)) 6224 if (throttled_hierarchy(cfs_rq))
6214 continue; 6225 continue;
6215 6226
6216 if (update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq)) 6227 if (update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq, true))
6217 update_tg_load_avg(cfs_rq, 0); 6228 update_tg_load_avg(cfs_rq, 0);
6218 } 6229 }
6219 raw_spin_unlock_irqrestore(&rq->lock, flags); 6230 raw_spin_unlock_irqrestore(&rq->lock, flags);
@@ -6274,7 +6285,7 @@ static inline void update_blocked_averages(int cpu)
6274 6285
6275 raw_spin_lock_irqsave(&rq->lock, flags); 6286 raw_spin_lock_irqsave(&rq->lock, flags);
6276 update_rq_clock(rq); 6287 update_rq_clock(rq);
6277 update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq); 6288 update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq, true);
6278 raw_spin_unlock_irqrestore(&rq->lock, flags); 6289 raw_spin_unlock_irqrestore(&rq->lock, flags);
6279} 6290}
6280 6291