summaryrefslogtreecommitdiffstats
path: root/kernel/time
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2008-01-30 13:30:02 +0100
committerThomas Gleixner <tglx@linutronix.de>2008-04-17 12:22:31 +0200
commit6993fc5bbc5d63ccd55985b39c34417e430e75e9 (patch)
tree6a1ea13d3f27a8063a9375689b729479c4e63e22 /kernel/time
parent3833eecc183ce052e9ac96b39b45121a2d11ac16 (diff)
downloadlinux-6993fc5bbc5d63ccd55985b39c34417e430e75e9.tar.bz2
clocksource: make clocksource watchdog cycle through online CPUs
This way it checks if the clocks are synchronized between CPUs too. This might be able to detect slowly drifting TSCs which only go wrong over longer time. Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/time')
-rw-r--r--kernel/time/clocksource.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 7f60097d443a..912156dd6005 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -141,8 +141,16 @@ static void clocksource_watchdog(unsigned long data)
}
if (!list_empty(&watchdog_list)) {
- __mod_timer(&watchdog_timer,
- watchdog_timer.expires + WATCHDOG_INTERVAL);
+ /*
+ * Cycle through CPUs to check if the CPUs stay
+ * synchronized to each other.
+ */
+ int next_cpu = next_cpu(raw_smp_processor_id(), cpu_online_map);
+
+ if (next_cpu >= NR_CPUS)
+ next_cpu = first_cpu(cpu_online_map);
+ watchdog_timer.expires += WATCHDOG_INTERVAL;
+ add_timer_on(&watchdog_timer, next_cpu);
}
spin_unlock(&watchdog_lock);
}
@@ -164,7 +172,8 @@ static void clocksource_check_watchdog(struct clocksource *cs)
if (!started && watchdog) {
watchdog_last = watchdog->read();
watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL;
- add_timer(&watchdog_timer);
+ add_timer_on(&watchdog_timer,
+ first_cpu(cpu_online_map));
}
} else {
if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
@@ -185,7 +194,8 @@ static void clocksource_check_watchdog(struct clocksource *cs)
watchdog_last = watchdog->read();
watchdog_timer.expires =
jiffies + WATCHDOG_INTERVAL;
- add_timer(&watchdog_timer);
+ add_timer_on(&watchdog_timer,
+ first_cpu(cpu_online_map));
}
}
}