>+		prev_high = last_tsc_high;
>+		prev_low = last_tsc_low;
> 
> 		/*
>-		 * Interrupts are just disabled locally since the timer irq
>-		 * has the SA_INTERRUPT flag set. -arca
>+		 * It is important that these two operations happen almost at
>+		 * the same time. We do the RDTSC stuff first, since it's
>+		 * faster.
> 		 */
>-	
>-		/* read Pentium cycle counter */
>-		__asm__("rdtsc" : "=a" (last_tsc_low) : : "edx");
>-
>-		outb_p(0x00, 0x43);     /* latch the count ASAP */
>-
>-		count = inb_p(0x40);    /* read the latched count */
>-		count |= inb(0x40) << 8;
>+		__asm__("rdtsc" : "=a" (last_tsc_low), "=d" (last_tsc_high));
		^^^^^^^ this is a bug: it has to be declared __volatile__
>+		count = get_8254_timer_count();
> 
> 		count = ((LATCH-1) - count) * TICK_SIZE;
> 		delay_at_last_interrupt = (count + LATCH/2) / LATCH;
>+
>+		delta_low = last_tsc_low - prev_low;
>+		delta_high = last_tsc_high - prev_high;
>+		if (last_tsc_low < prev_low)
>+			delta_high--;
>+
>+		/*
>+		 * did we have a too big timer IRQ delay? The limit is
>+		 * 1.5*1/HZ. This detects big delays too, not just
>+		 * max 4G*1cycle ones, but breaks together with cpu_hz
>+		 * at the 4GHz barrier.
>+		 */
>+		if (delta_high || (delta_low > cpu_hz/HZ*3/2))
>+			printk("bug: %08x%08x cycles timer IRQ delay from %p\n",
>+				delta_high, delta_low, (void *)regs->eip);
Agreed, printing regs->eip is a good idea. I'll do that here too.
>+extern inline unsigned int get_8254_timer_count(void)
I' don't like this because I want to do other useful things between the
two inb_p. If you look at my patches you'll notice I am doing things in
the middle.
And btw I am _far_ from silenty recover the system time. If you look
closely at my last and current patch (-B) you'll notice that I printk
always how many irqs are been lost.
Andrea Arcangeli
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/