tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
yet another WARNING: negative runtime; monotonic clock has gone backwards
My machine rather frequently warns that negative runtime on boot. The
reason was tc_delta() returns a bit larger value than usual and
th->th_scale * tc_delta() overflows. As a result, binuptime() returns
smaller time or the first tc_windup() after clock is enabled sets
smaller th_offset.
Appended patch tries to adjust th->th_counter_offset just before
enabling clock interrupt so that tc_delta() returns reasonably small
value before the first tc_windup() call after interrupt enabled.
Comments?
enami.
Index: kern/kern_clock.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_clock.c,v
retrieving revision 1.126
diff -u -r1.126 kern_clock.c
--- kern/kern_clock.c 5 Oct 2008 21:57:20 -0000 1.126
+++ kern/kern_clock.c 12 Feb 2009 14:22:15 -0000
@@ -168,6 +168,15 @@
*/
intr_timecounter.tc_frequency = hz;
tc_init(&intr_timecounter);
+
+ /*
+ * At this point, the selected counter may run far away.
+ * Reset the th->th_counter_offset so that tc_delta() to
+ * return a value small enough to keep the result of
+ * `th->th_scale * tc_delta()' fits in 64-bit.
+ */
+ tc_ticktock();
+
cpu_initclocks();
/*
@@ -183,7 +192,6 @@
if (hardscheddiv <= 0)
panic("hardscheddiv");
}
-
}
/*
Index: kern/kern_tc.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_tc.c,v
retrieving revision 1.38
diff -u -r1.38 kern_tc.c
--- kern/kern_tc.c 11 Jan 2009 02:45:52 -0000 1.38
+++ kern/kern_tc.c 12 Feb 2009 14:22:30 -0000
@@ -937,15 +937,15 @@
*/
static int tc_tick;
+static int tc_count;
void
tc_ticktock(void)
{
- static int count;
- if (++count < tc_tick)
+ if (--tc_count > 0)
return;
- count = 0;
+ tc_count = tc_tick;
mutex_spin_enter(&timecounter_lock);
if (timecounter_bad != 0) {
/* An existing timecounter has gone bad, pick a new one. */
@@ -980,6 +980,7 @@
p = (tc_tick * 1000000) / hz;
aprint_verbose("timecounter: Timecounters tick every %d.%03u msec\n",
p / 1000, p % 1000);
+ tc_count = tc_tick;
/* warm up new timecounter (again) and get rolling. */
(void)timecounter->tc_get_timecount(timecounter);
Home |
Main Index |
Thread Index |
Old Index