Re: 2.6.17-mm2 hrtimer code wedges at boot?
From: Roman Zippel
Date: Sun Jul 02 2006 - 21:16:22 EST
Hi,
On Fri, 30 Jun 2006, Valdis.Kletnieks@xxxxxx wrote:
> *AHA* I *found* the bugger, I think.
>
> In kernel/timer.c, we have:
>
> static void clocksource_adjust(struct clocksource *clock, s64 offset)
> (s64 used for offset in multiple places).
>
> However, in other places, offset is a 'cycle_t', which is:
>
> include/linux/clocksource.h:typedef u64 cycle_t;
>
> So it looks like a signed/unsigned screwage.
It's a possibility, but the signed/unsigned usage is pretty much
intentional. The assumptation is that time only goes forward so nothing
there should become negative, only adjustments happen in both directions.
It's really weird why it's getting completely so out of control early
during boot. It would be great if you could also test the patch below, it
should trigger closer to when it goes wrong and help to analyze the
problem (or at least rule out a number of possibilities).
bye, Roman
---
kernel/timer.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
Index: linux-2.6-mm/kernel/timer.c
===================================================================
--- linux-2.6-mm.orig/kernel/timer.c
+++ linux-2.6-mm/kernel/timer.c
@@ -1078,6 +1078,7 @@ static __always_inline int clocksource_b
*/
static void clocksource_adjust(struct clocksource *clock, s64 offset)
{
+ static int cnt = 16;
s64 error, interval = clock->cycle_interval;
int adj;
@@ -1091,6 +1092,13 @@ static void clocksource_adjust(struct cl
} else
return;
+ if ((adj > 10 || adj < -10 || (s32)clock->mult <= -adj) && cnt > 0) {
+ cnt--;
+ printk("big adj at %ld (%Lu,%d,%Ld,%Ld)\n", jiffies, current_tick_length(),
+ adj, interval, offset);
+ printk_clock_info();
+ }
+
clock->mult += adj;
clock->xtime_interval += interval;
clock->xtime_nsec -= offset;
@@ -1149,9 +1157,15 @@ static void update_wall_time(void)
/* check to see if there is a new clocksource to use */
if (change_clocksource()) {
+ static int cnt = 16;
clock->error = 0;
clock->xtime_nsec = 0;
clocksource_calculate_interval(clock, tick_nsec);
+ if (cnt > 0) {
+ cnt--;
+ printk("clock changed at %ld (%Lu)\n", jiffies, current_tick_length());
+ printk_clock_info();
+ }
}
}
-
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/