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.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index c13d4f182370..b711ffcb106c 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -20,6 +20,7 @@
20#include <linux/profile.h> 20#include <linux/profile.h>
21#include <linux/sched.h> 21#include <linux/sched.h>
22#include <linux/tick.h> 22#include <linux/tick.h>
23#include <linux/module.h>
23 24
24#include <asm/irq_regs.h> 25#include <asm/irq_regs.h>
25 26
@@ -75,6 +76,9 @@ static void tick_do_update_jiffies64(ktime_t now)
75 incr * ticks); 76 incr * ticks);
76 } 77 }
77 do_timer(++ticks); 78 do_timer(++ticks);
79
80 /* Keep the tick_next_period variable up to date */
81 tick_next_period = ktime_add(last_jiffies_update, tick_period);
78 } 82 }
79 write_sequnlock(&xtime_lock); 83 write_sequnlock(&xtime_lock);
80} 84}
@@ -162,6 +166,8 @@ void tick_nohz_stop_idle(int cpu)
162 ts->idle_lastupdate = now; 166 ts->idle_lastupdate = now;
163 ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); 167 ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);
164 ts->idle_active = 0; 168 ts->idle_active = 0;
169
170 sched_clock_idle_wakeup_event(0);
165 } 171 }
166} 172}
167 173
@@ -177,6 +183,7 @@ static ktime_t tick_nohz_start_idle(struct tick_sched *ts)
177 } 183 }
178 ts->idle_entrytime = now; 184 ts->idle_entrytime = now;
179 ts->idle_active = 1; 185 ts->idle_active = 1;
186 sched_clock_idle_sleep_event();
180 return now; 187 return now;
181} 188}
182 189
@@ -184,9 +191,17 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
184{ 191{
185 struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); 192 struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
186 193
187 *last_update_time = ktime_to_us(ts->idle_lastupdate); 194 if (!tick_nohz_enabled)
195 return -1;
196
197 if (ts->idle_active)
198 *last_update_time = ktime_to_us(ts->idle_lastupdate);
199 else
200 *last_update_time = ktime_to_us(ktime_get());
201
188 return ktime_to_us(ts->idle_sleeptime); 202 return ktime_to_us(ts->idle_sleeptime);
189} 203}
204EXPORT_SYMBOL_GPL(get_cpu_idle_time_us);
190 205
191/** 206/**
192 * tick_nohz_stop_sched_tick - stop the idle tick from the idle task 207 * tick_nohz_stop_sched_tick - stop the idle tick from the idle task
@@ -218,7 +233,7 @@ void tick_nohz_stop_sched_tick(int inidle)
218 */ 233 */
219 if (unlikely(!cpu_online(cpu))) { 234 if (unlikely(!cpu_online(cpu))) {
220 if (cpu == tick_do_timer_cpu) 235 if (cpu == tick_do_timer_cpu)
221 tick_do_timer_cpu = -1; 236 tick_do_timer_cpu = TICK_DO_TIMER_NONE;
222 } 237 }
223 238
224 if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE)) 239 if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
@@ -289,7 +304,6 @@ void tick_nohz_stop_sched_tick(int inidle)
289 ts->tick_stopped = 1; 304 ts->tick_stopped = 1;
290 ts->idle_jiffies = last_jiffies; 305 ts->idle_jiffies = last_jiffies;
291 rcu_enter_nohz(); 306 rcu_enter_nohz();
292 sched_clock_tick_stop(cpu);
293 } 307 }
294 308
295 /* 309 /*
@@ -301,7 +315,7 @@ void tick_nohz_stop_sched_tick(int inidle)
301 * invoked. 315 * invoked.
302 */ 316 */
303 if (cpu == tick_do_timer_cpu) 317 if (cpu == tick_do_timer_cpu)
304 tick_do_timer_cpu = -1; 318 tick_do_timer_cpu = TICK_DO_TIMER_NONE;
305 319
306 ts->idle_sleeps++; 320 ts->idle_sleeps++;
307 321
@@ -392,7 +406,6 @@ void tick_nohz_restart_sched_tick(void)
392 select_nohz_load_balancer(0); 406 select_nohz_load_balancer(0);
393 now = ktime_get(); 407 now = ktime_get();
394 tick_do_update_jiffies64(now); 408 tick_do_update_jiffies64(now);
395 sched_clock_tick_start(cpu);
396 cpu_clear(cpu, nohz_cpu_mask); 409 cpu_clear(cpu, nohz_cpu_mask);
397 410
398 /* 411 /*
@@ -467,7 +480,7 @@ static void tick_nohz_handler(struct clock_event_device *dev)
467 * this duty, then the jiffies update is still serialized by 480 * this duty, then the jiffies update is still serialized by
468 * xtime_lock. 481 * xtime_lock.
469 */ 482 */
470 if (unlikely(tick_do_timer_cpu == -1)) 483 if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE))
471 tick_do_timer_cpu = cpu; 484 tick_do_timer_cpu = cpu;
472 485
473 /* Check, if the jiffies need an update */ 486 /* Check, if the jiffies need an update */
@@ -569,7 +582,7 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
569 * this duty, then the jiffies update is still serialized by 582 * this duty, then the jiffies update is still serialized by
570 * xtime_lock. 583 * xtime_lock.
571 */ 584 */
572 if (unlikely(tick_do_timer_cpu == -1)) 585 if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE))
573 tick_do_timer_cpu = cpu; 586 tick_do_timer_cpu = cpu;
574#endif 587#endif
575 588
@@ -621,7 +634,7 @@ void tick_setup_sched_timer(void)
621 */ 634 */
622 hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); 635 hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
623 ts->sched_timer.function = tick_sched_timer; 636 ts->sched_timer.function = tick_sched_timer;
624 ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ; 637 ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_PERCPU;
625 638
626 /* Get the next period (per cpu) */ 639 /* Get the next period (per cpu) */
627 ts->sched_timer.expires = tick_init_jiffy_update(); 640 ts->sched_timer.expires = tick_init_jiffy_update();
@@ -645,17 +658,21 @@ void tick_setup_sched_timer(void)
645 ts->nohz_mode = NOHZ_MODE_HIGHRES; 658 ts->nohz_mode = NOHZ_MODE_HIGHRES;
646#endif 659#endif
647} 660}
661#endif /* HIGH_RES_TIMERS */
648 662
663#if defined CONFIG_NO_HZ || defined CONFIG_HIGH_RES_TIMERS
649void tick_cancel_sched_timer(int cpu) 664void tick_cancel_sched_timer(int cpu)
650{ 665{
651 struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); 666 struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
652 667
668# ifdef CONFIG_HIGH_RES_TIMERS
653 if (ts->sched_timer.base) 669 if (ts->sched_timer.base)
654 hrtimer_cancel(&ts->sched_timer); 670 hrtimer_cancel(&ts->sched_timer);
671# endif
655 672
656 ts->nohz_mode = NOHZ_MODE_INACTIVE; 673 ts->nohz_mode = NOHZ_MODE_INACTIVE;
657} 674}
658#endif /* HIGH_RES_TIMERS */ 675#endif
659 676
660/** 677/**
661 * Async notification about clocksource changes 678 * Async notification about clocksource changes