aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/hrtimer.c
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@citrix.com>2013-06-27 06:35:44 -0400
committerThomas Gleixner <tglx@linutronix.de>2013-06-28 17:15:06 -0400
commit7c4c3a0f18ba57ea2a2985034532303d2929902a (patch)
tree553f2901ae4fd0fede367ece9ec9c30106ff744f /kernel/hrtimer.c
parent9e04d3804d3ac97d8c03a41d78d0f0674b5d01e1 (diff)
hrtimers: Support resuming with two or more CPUs online (but stopped)
hrtimers_resume() only reprograms the timers for the current CPU as it assumes that all other CPUs are offline at this point in the resume process. If other CPUs are online then their timers will not be corrected and they may fire at the wrong time. When running as a Xen guest, this assumption is not true. Non-boot CPUs are only stopped with IRQs disabled instead of offlining them. This is a performance optimization as disabling the CPUs would add an unacceptable amount of additional downtime during a live migration (> 200 ms for a 4 VCPU guest). hrtimers_resume() cannot call on_each_cpu(retrigger_next_event,...) as the other CPUs will be stopped with IRQs disabled. Instead, defer the call to the next softirq. [ tglx: Separated the xen change out ] Signed-off-by: David Vrabel <david.vrabel@citrix.com> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: John Stultz <john.stultz@linaro.org> Cc: <xen-devel@lists.xen.org> Link: http://lkml.kernel.org/r/1372329348-20841-2-git-send-email-david.vrabel@citrix.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r--kernel/hrtimer.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index fd4b13b131f8..e86827e94c9a 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -773,15 +773,24 @@ void clock_was_set(void)
773 773
774/* 774/*
775 * During resume we might have to reprogram the high resolution timer 775 * During resume we might have to reprogram the high resolution timer
776 * interrupt (on the local CPU): 776 * interrupt on all online CPUs. However, all other CPUs will be
777 * stopped with IRQs interrupts disabled so the clock_was_set() call
778 * must be deferred to the softirq.
779 *
780 * The one-shot timer has already been programmed to fire immediately
781 * (see tick_resume_oneshot()) and this interrupt will trigger the
782 * softirq to run early enough to correctly reprogram the timers on
783 * all CPUs.
777 */ 784 */
778void hrtimers_resume(void) 785void hrtimers_resume(void)
779{ 786{
787 struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
788
780 WARN_ONCE(!irqs_disabled(), 789 WARN_ONCE(!irqs_disabled(),
781 KERN_INFO "hrtimers_resume() called with IRQs enabled!"); 790 KERN_INFO "hrtimers_resume() called with IRQs enabled!");
782 791
783 retrigger_next_event(NULL); 792 cpu_base->clock_was_set = 1;
784 timerfd_clock_was_set(); 793 __raise_softirq_irqoff(HRTIMER_SOFTIRQ);
785} 794}
786 795
787static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) 796static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer)