diff options
Diffstat (limited to 'kernel/time/tick-sched.c')
-rw-r--r-- | kernel/time/tick-sched.c | 35 |
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 | } |
204 | EXPORT_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 | ||
649 | void tick_cancel_sched_timer(int cpu) | 664 | void 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 |