diff options
| author | Mel Gorman <mgorman@suse.de> | 2014-08-06 09:19:21 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-08-06 15:17:45 -0400 |
| commit | 372ba8cb46b271a7662b92cbefedee56725f6bd0 (patch) | |
| tree | 536013552cd845b4eb0559dc79c023ecc426c21e | |
| parent | 64b4ca5cb6e1a9f577588db5765dc996ddf595e1 (diff) | |
cpuidle: menu: Lookup CPU runqueues less
The menu governer makes separate lookups of the CPU runqueue to get
load and number of IO waiters but it can be done with a single lookup.
Signed-off-by: Mel Gorman <mgorman@suse.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
| -rw-r--r-- | drivers/cpuidle/governors/menu.c | 17 | ||||
| -rw-r--r-- | include/linux/sched.h | 3 | ||||
| -rw-r--r-- | kernel/sched/core.c | 7 | ||||
| -rw-r--r-- | kernel/sched/proc.c | 7 |
4 files changed, 15 insertions, 19 deletions
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index f55d8260ec43..27702742b319 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
| @@ -134,12 +134,9 @@ struct menu_device { | |||
| 134 | #define LOAD_INT(x) ((x) >> FSHIFT) | 134 | #define LOAD_INT(x) ((x) >> FSHIFT) |
| 135 | #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) | 135 | #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) |
| 136 | 136 | ||
| 137 | static int get_loadavg(void) | 137 | static inline int get_loadavg(unsigned long load) |
| 138 | { | 138 | { |
| 139 | unsigned long this = this_cpu_load(); | 139 | return LOAD_INT(load) * 10 + LOAD_FRAC(load) / 10; |
| 140 | |||
| 141 | |||
| 142 | return LOAD_INT(this) * 10 + LOAD_FRAC(this) / 10; | ||
| 143 | } | 140 | } |
| 144 | 141 | ||
| 145 | static inline int which_bucket(unsigned int duration, unsigned long nr_iowaiters) | 142 | static inline int which_bucket(unsigned int duration, unsigned long nr_iowaiters) |
| @@ -175,13 +172,13 @@ static inline int which_bucket(unsigned int duration, unsigned long nr_iowaiters | |||
| 175 | * to be, the higher this multiplier, and thus the higher | 172 | * to be, the higher this multiplier, and thus the higher |
| 176 | * the barrier to go to an expensive C state. | 173 | * the barrier to go to an expensive C state. |
| 177 | */ | 174 | */ |
| 178 | static inline int performance_multiplier(unsigned long nr_iowaiters) | 175 | static inline int performance_multiplier(unsigned long nr_iowaiters, unsigned long load) |
| 179 | { | 176 | { |
| 180 | int mult = 1; | 177 | int mult = 1; |
| 181 | 178 | ||
| 182 | /* for higher loadavg, we are more reluctant */ | 179 | /* for higher loadavg, we are more reluctant */ |
| 183 | 180 | ||
| 184 | mult += 2 * get_loadavg(); | 181 | mult += 2 * get_loadavg(load); |
| 185 | 182 | ||
| 186 | /* for IO wait tasks (per cpu!) we add 5x each */ | 183 | /* for IO wait tasks (per cpu!) we add 5x each */ |
| 187 | mult += 10 * nr_iowaiters; | 184 | mult += 10 * nr_iowaiters; |
| @@ -296,7 +293,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
| 296 | int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); | 293 | int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); |
| 297 | int i; | 294 | int i; |
| 298 | unsigned int interactivity_req; | 295 | unsigned int interactivity_req; |
| 299 | unsigned long nr_iowaiters; | 296 | unsigned long nr_iowaiters, cpu_load; |
| 300 | 297 | ||
| 301 | if (data->needs_update) { | 298 | if (data->needs_update) { |
| 302 | menu_update(drv, dev); | 299 | menu_update(drv, dev); |
| @@ -312,7 +309,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
| 312 | /* determine the expected residency time, round up */ | 309 | /* determine the expected residency time, round up */ |
| 313 | data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length()); | 310 | data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length()); |
| 314 | 311 | ||
| 315 | nr_iowaiters = nr_iowait_cpu(smp_processor_id()); | 312 | get_iowait_load(&nr_iowaiters, &cpu_load); |
| 316 | data->bucket = which_bucket(data->next_timer_us, nr_iowaiters); | 313 | data->bucket = which_bucket(data->next_timer_us, nr_iowaiters); |
| 317 | 314 | ||
| 318 | /* | 315 | /* |
| @@ -331,7 +328,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
| 331 | * duration / latency ratio. Adjust the latency limit if | 328 | * duration / latency ratio. Adjust the latency limit if |
| 332 | * necessary. | 329 | * necessary. |
| 333 | */ | 330 | */ |
| 334 | interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters); | 331 | interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load); |
| 335 | if (latency_req > interactivity_req) | 332 | if (latency_req > interactivity_req) |
| 336 | latency_req = interactivity_req; | 333 | latency_req = interactivity_req; |
| 337 | 334 | ||
diff --git a/include/linux/sched.h b/include/linux/sched.h index 306f4f0c987a..641bd954bb5d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -168,8 +168,7 @@ extern int nr_processes(void); | |||
| 168 | extern unsigned long nr_running(void); | 168 | extern unsigned long nr_running(void); |
| 169 | extern unsigned long nr_iowait(void); | 169 | extern unsigned long nr_iowait(void); |
| 170 | extern unsigned long nr_iowait_cpu(int cpu); | 170 | extern unsigned long nr_iowait_cpu(int cpu); |
| 171 | extern unsigned long this_cpu_load(void); | 171 | extern void get_iowait_load(unsigned long *nr_waiters, unsigned long *load); |
| 172 | |||
| 173 | 172 | ||
| 174 | extern void calc_global_load(unsigned long ticks); | 173 | extern void calc_global_load(unsigned long ticks); |
| 175 | extern void update_cpu_load_nohz(void); | 174 | extern void update_cpu_load_nohz(void); |
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 3bdf01b494fe..863ef1d19563 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
| @@ -2385,6 +2385,13 @@ unsigned long nr_iowait_cpu(int cpu) | |||
| 2385 | return atomic_read(&this->nr_iowait); | 2385 | return atomic_read(&this->nr_iowait); |
| 2386 | } | 2386 | } |
| 2387 | 2387 | ||
| 2388 | void get_iowait_load(unsigned long *nr_waiters, unsigned long *load) | ||
| 2389 | { | ||
| 2390 | struct rq *this = this_rq(); | ||
| 2391 | *nr_waiters = atomic_read(&this->nr_iowait); | ||
| 2392 | *load = this->cpu_load[0]; | ||
| 2393 | } | ||
| 2394 | |||
| 2388 | #ifdef CONFIG_SMP | 2395 | #ifdef CONFIG_SMP |
| 2389 | 2396 | ||
| 2390 | /* | 2397 | /* |
diff --git a/kernel/sched/proc.c b/kernel/sched/proc.c index 16f5a30f9c88..8ecd552fe4f2 100644 --- a/kernel/sched/proc.c +++ b/kernel/sched/proc.c | |||
| @@ -8,13 +8,6 @@ | |||
| 8 | 8 | ||
| 9 | #include "sched.h" | 9 | #include "sched.h" |
| 10 | 10 | ||
| 11 | unsigned long this_cpu_load(void) | ||
| 12 | { | ||
| 13 | struct rq *this = this_rq(); | ||
| 14 | return this->cpu_load[0]; | ||
| 15 | } | ||
| 16 | |||
| 17 | |||
| 18 | /* | 11 | /* |
| 19 | * Global load-average calculations | 12 | * Global load-average calculations |
| 20 | * | 13 | * |
