Re: [PATCH] Improve clocksource unstable warning

From: john stultz
Date: Fri Nov 12 2010 - 19:59:42 EST


On Sat, 2010-11-13 at 00:22 +0000, john stultz wrote:
> On Fri, 2010-11-12 at 18:51 -0500, Andrew Lutomirski wrote:
> > Also wrong if cs_elapsed is just slightly less than wd_wrapping_time
> > but the wd clocksource runs enough faster that it wrapped.
>
> Ok. Good point, that's a problem. Hrmmmm. Too much math for Friday. :)

I have a hard time leaving things alone. :)

So this still has the issue of the u64%u64 won't work on 32bit systems,
but I think once I rework the modulo bit the following should be what
you were describing.

It is ugly, so let me know if you have a cleaner way.


Signed-off-by: John Stultz <johnstul@xxxxxxxxxx>

diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index c18d7ef..0afbcb5 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -247,6 +247,7 @@ static void clocksource_watchdog(unsigned long data)
struct clocksource *cs;
cycle_t csnow, wdnow;
int64_t wd_nsec, cs_nsec;
+ int64_t wd_max_nsec;
int next_cpu;

spin_lock(&watchdog_lock);
@@ -257,6 +258,8 @@ static void clocksource_watchdog(unsigned long data)
wd_nsec = clocksource_cyc2ns((wdnow - watchdog_last) & watchdog->mask,
watchdog->mult, watchdog->shift);
watchdog_last = wdnow;
+ wd_max_nsec = clocksource_cyc2ns(watchdog->mask, watchdog->mult,
+ watchdog->shift);

list_for_each_entry(cs, &watchdog_list, wd_list) {

@@ -280,6 +283,35 @@ static void clocksource_watchdog(unsigned long data)
cs_nsec = clocksource_cyc2ns((csnow - cs->wd_last) &
cs->mask, cs->mult, cs->shift);
cs->wd_last = csnow;
+
+ /*
+ * If the cs interval is greater then the wd wrap interval,
+ * we were somehow delayed. So check that modulo the wrap
+ * interval, the cs interval is close to the watchdog
+ * interval value.
+ */
+ if (cs_nsec > wd_max_nsec){
+ int64_t cs_modulo = cs_nsec % wd_max_nsec;
+
+ /* first check the easy case */
+ if(abs(cs_modulo - wd_nsec) < WATCHDOG_THRESHOLD) {
+ WARN_ONCE(1, "clocksource_watchdog:"
+ "watchdog delayed?\n");
+ continue;
+ }
+ /* could be split along the wd_max_nsec boundary*/
+ if (wd_nsec < cs_modulo)
+ wd_nsec += wd_max_nsec;
+ else
+ cs_modulo += wd_max_nsec;
+ /* check again */
+ if(abs(cs_modulo - wd_nsec) < WATCHDOG_THRESHOLD) {
+ WARN_ONCE(1, "clocksource_watchdog:"
+ "watchdog delayed?\n");
+ continue;
+ }
+ }
+
if (abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) {
clocksource_unstable(cs, cs_nsec - wd_nsec);
continue;


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/