aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/tick-sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/tick-sched.c')
-rw-r--r--kernel/time/tick-sched.c61
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)
211u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time) 211u64 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}
222EXPORT_SYMBOL_GPL(get_cpu_idle_time_us); 236EXPORT_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);
237u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time) 252u64 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}
248EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us); 276EXPORT_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);
447out: 471out:
@@ -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 */