clocksource: make clocksource watchdog cycle through online CPUs
authorAndi Kleen <ak@suse.de>
Wed, 30 Jan 2008 12:30:02 +0000 (13:30 +0100)
committerIngo Molnar <mingo@elte.hu>
Wed, 30 Jan 2008 12:30:02 +0000 (13:30 +0100)
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>
kernel/time/clocksource.c

index cabfa193efb34ea436dcf04618824236a6f8c450..edd5ef8e1765800c8cdce8ed369e6392f371511f 100644 (file)
@@ -142,8 +142,13 @@ 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);
 }
@@ -165,7 +170,7 @@ 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)
@@ -186,7 +191,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));
                        }
                }
        }