diff options
Diffstat (limited to 'kernel/time/tick-sched.c')
-rw-r--r-- | kernel/time/tick-sched.c | 61 |
1 files changed, 40 insertions, 21 deletions
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index d5097c44b407..40420644d0ba 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -139,7 +139,6 @@ static void tick_nohz_update_jiffies(ktime_t now) | |||
139 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | 139 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); |
140 | unsigned long flags; | 140 | unsigned long flags; |
141 | 141 | ||
142 | cpumask_clear_cpu(cpu, nohz_cpu_mask); | ||
143 | ts->idle_waketime = now; | 142 | ts->idle_waketime = now; |
144 | 143 | ||
145 | local_irq_save(flags); | 144 | local_irq_save(flags); |
@@ -159,9 +158,10 @@ update_ts_time_stats(int cpu, struct tick_sched *ts, ktime_t now, u64 *last_upda | |||
159 | 158 | ||
160 | if (ts->idle_active) { | 159 | if (ts->idle_active) { |
161 | delta = ktime_sub(now, ts->idle_entrytime); | 160 | delta = ktime_sub(now, ts->idle_entrytime); |
162 | ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); | ||
163 | if (nr_iowait_cpu(cpu) > 0) | 161 | if (nr_iowait_cpu(cpu) > 0) |
164 | ts->iowait_sleeptime = ktime_add(ts->iowait_sleeptime, delta); | 162 | ts->iowait_sleeptime = ktime_add(ts->iowait_sleeptime, delta); |
163 | else | ||
164 | ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); | ||
165 | ts->idle_entrytime = now; | 165 | ts->idle_entrytime = now; |
166 | } | 166 | } |
167 | 167 | ||
@@ -197,11 +197,11 @@ static ktime_t tick_nohz_start_idle(int cpu, struct tick_sched *ts) | |||
197 | /** | 197 | /** |
198 | * get_cpu_idle_time_us - get the total idle time of a cpu | 198 | * get_cpu_idle_time_us - get the total idle time of a cpu |
199 | * @cpu: CPU number to query | 199 | * @cpu: CPU number to query |
200 | * @last_update_time: variable to store update time in | 200 | * @last_update_time: variable to store update time in. Do not update |
201 | * counters if NULL. | ||
201 | * | 202 | * |
202 | * Return the cummulative idle time (since boot) for a given | 203 | * Return the cummulative idle time (since boot) for a given |
203 | * CPU, in microseconds. The idle time returned includes | 204 | * CPU, in microseconds. |
204 | * the iowait time (unlike what "top" and co report). | ||
205 | * | 205 | * |
206 | * This time is measured via accounting rather than sampling, | 206 | * This time is measured via accounting rather than sampling, |
207 | * and is as accurate as ktime_get() is. | 207 | * and is as accurate as ktime_get() is. |
@@ -211,20 +211,35 @@ static ktime_t tick_nohz_start_idle(int cpu, struct tick_sched *ts) | |||
211 | u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time) | 211 | u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time) |
212 | { | 212 | { |
213 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | 213 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); |
214 | ktime_t now, idle; | ||
214 | 215 | ||
215 | if (!tick_nohz_enabled) | 216 | if (!tick_nohz_enabled) |
216 | return -1; | 217 | return -1; |
217 | 218 | ||
218 | update_ts_time_stats(cpu, ts, ktime_get(), last_update_time); | 219 | now = ktime_get(); |
220 | if (last_update_time) { | ||
221 | update_ts_time_stats(cpu, ts, now, last_update_time); | ||
222 | idle = ts->idle_sleeptime; | ||
223 | } else { | ||
224 | if (ts->idle_active && !nr_iowait_cpu(cpu)) { | ||
225 | ktime_t delta = ktime_sub(now, ts->idle_entrytime); | ||
226 | |||
227 | idle = ktime_add(ts->idle_sleeptime, delta); | ||
228 | } else { | ||
229 | idle = ts->idle_sleeptime; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | return ktime_to_us(idle); | ||
219 | 234 | ||
220 | return ktime_to_us(ts->idle_sleeptime); | ||
221 | } | 235 | } |
222 | EXPORT_SYMBOL_GPL(get_cpu_idle_time_us); | 236 | EXPORT_SYMBOL_GPL(get_cpu_idle_time_us); |
223 | 237 | ||
224 | /* | 238 | /** |
225 | * get_cpu_iowait_time_us - get the total iowait time of a cpu | 239 | * get_cpu_iowait_time_us - get the total iowait time of a cpu |
226 | * @cpu: CPU number to query | 240 | * @cpu: CPU number to query |
227 | * @last_update_time: variable to store update time in | 241 | * @last_update_time: variable to store update time in. Do not update |
242 | * counters if NULL. | ||
228 | * | 243 | * |
229 | * Return the cummulative iowait time (since boot) for a given | 244 | * Return the cummulative iowait time (since boot) for a given |
230 | * CPU, in microseconds. | 245 | * CPU, in microseconds. |
@@ -237,13 +252,26 @@ EXPORT_SYMBOL_GPL(get_cpu_idle_time_us); | |||
237 | u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time) | 252 | u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time) |
238 | { | 253 | { |
239 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | 254 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); |
255 | ktime_t now, iowait; | ||
240 | 256 | ||
241 | if (!tick_nohz_enabled) | 257 | if (!tick_nohz_enabled) |
242 | return -1; | 258 | return -1; |
243 | 259 | ||
244 | update_ts_time_stats(cpu, ts, ktime_get(), last_update_time); | 260 | now = ktime_get(); |
261 | if (last_update_time) { | ||
262 | update_ts_time_stats(cpu, ts, now, last_update_time); | ||
263 | iowait = ts->iowait_sleeptime; | ||
264 | } else { | ||
265 | if (ts->idle_active && nr_iowait_cpu(cpu) > 0) { | ||
266 | ktime_t delta = ktime_sub(now, ts->idle_entrytime); | ||
267 | |||
268 | iowait = ktime_add(ts->iowait_sleeptime, delta); | ||
269 | } else { | ||
270 | iowait = ts->iowait_sleeptime; | ||
271 | } | ||
272 | } | ||
245 | 273 | ||
246 | return ktime_to_us(ts->iowait_sleeptime); | 274 | return ktime_to_us(iowait); |
247 | } | 275 | } |
248 | EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us); | 276 | EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us); |
249 | 277 | ||
@@ -389,9 +417,6 @@ void tick_nohz_stop_sched_tick(int inidle) | |||
389 | else | 417 | else |
390 | expires.tv64 = KTIME_MAX; | 418 | expires.tv64 = KTIME_MAX; |
391 | 419 | ||
392 | if (delta_jiffies > 1) | ||
393 | cpumask_set_cpu(cpu, nohz_cpu_mask); | ||
394 | |||
395 | /* Skip reprogram of event if its not changed */ | 420 | /* Skip reprogram of event if its not changed */ |
396 | if (ts->tick_stopped && ktime_equal(expires, dev->next_event)) | 421 | if (ts->tick_stopped && ktime_equal(expires, dev->next_event)) |
397 | goto out; | 422 | goto out; |
@@ -441,7 +466,6 @@ void tick_nohz_stop_sched_tick(int inidle) | |||
441 | * softirq. | 466 | * softirq. |
442 | */ | 467 | */ |
443 | tick_do_update_jiffies64(ktime_get()); | 468 | tick_do_update_jiffies64(ktime_get()); |
444 | cpumask_clear_cpu(cpu, nohz_cpu_mask); | ||
445 | } | 469 | } |
446 | raise_softirq_irqoff(TIMER_SOFTIRQ); | 470 | raise_softirq_irqoff(TIMER_SOFTIRQ); |
447 | out: | 471 | out: |
@@ -524,7 +548,6 @@ void tick_nohz_restart_sched_tick(void) | |||
524 | /* Update jiffies first */ | 548 | /* Update jiffies first */ |
525 | select_nohz_load_balancer(0); | 549 | select_nohz_load_balancer(0); |
526 | tick_do_update_jiffies64(now); | 550 | tick_do_update_jiffies64(now); |
527 | cpumask_clear_cpu(cpu, nohz_cpu_mask); | ||
528 | 551 | ||
529 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING | 552 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING |
530 | /* | 553 | /* |
@@ -640,8 +663,6 @@ static void tick_nohz_switch_to_nohz(void) | |||
640 | next = ktime_add(next, tick_period); | 663 | next = ktime_add(next, tick_period); |
641 | } | 664 | } |
642 | local_irq_enable(); | 665 | local_irq_enable(); |
643 | |||
644 | printk(KERN_INFO "Switched to NOHz mode on CPU #%d\n", smp_processor_id()); | ||
645 | } | 666 | } |
646 | 667 | ||
647 | /* | 668 | /* |
@@ -793,10 +814,8 @@ void tick_setup_sched_timer(void) | |||
793 | } | 814 | } |
794 | 815 | ||
795 | #ifdef CONFIG_NO_HZ | 816 | #ifdef CONFIG_NO_HZ |
796 | if (tick_nohz_enabled) { | 817 | if (tick_nohz_enabled) |
797 | ts->nohz_mode = NOHZ_MODE_HIGHRES; | 818 | ts->nohz_mode = NOHZ_MODE_HIGHRES; |
798 | printk(KERN_INFO "Switched to NOHz mode on CPU #%d\n", smp_processor_id()); | ||
799 | } | ||
800 | #endif | 819 | #endif |
801 | } | 820 | } |
802 | #endif /* HIGH_RES_TIMERS */ | 821 | #endif /* HIGH_RES_TIMERS */ |