lkml.org 
[lkml]   [1999]   [Mar]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Date
SubjectSuppressing Pentium timeoffset jitter in 2.0.36
Hi!

I found out that Linux 2.0.36 has 200us and above jitter when
reading the time. Interestingly this is not that much caused by
system load (Emacs C-U 8 M-x hanoi almost had no effect), but by
the schduling of timer events (itimer). At least in xntpd the jitter
was present when it ran.

I merged my old "madtime patch" with the code found in 2.2 and made
the following patch, possibly a good candidate for 2.0. If anyone
cares for a 2.0.37...

Regards,
Ulrich
P.S. The patch is part of PPSkit-0.3.9
P.P.S. Our mail system is down since Friday 22:00 MET, and they are
still "working on the problem". See when the message will leave...


--- linux/arch/i386/kernel/time.c~ Sat Mar 13 21:45:27 1999
+++ linux/arch/i386/kernel/time.c Sun Mar 14 18:14:23 1999
@@ -45,6 +45,9 @@
unsigned long high;
} init_timer_cc, last_timer_cc;

+/* Number of usecs that the last interrupt was delayed (only for TSC) */
+static int delay_at_last_interrupt;
+
/*
* This is more assembly than C, but it's also rather
* timing-critical and we have to use assembler to get
@@ -66,7 +69,32 @@
tmp = jiffies;
quotient = cached_quotient;
low_timer = last_timer_cc.low;
- missing_time = 0;
+ /* Read the time counter */
+ __asm__(".byte 0x0f,0x31"
+ :"=a" (eax), "=d" (edx));
+
+ /* .. relative to previous jiffy (32 bits is enough) */
+ edx = 0;
+ eax -= low_timer;
+
+ /*
+ * Time offset = (1000020/HZ * time_low) / quotient.
+ */
+
+ __asm__("mull %2"
+ :"=a" (eax), "=d" (edx)
+ :"r" (quotient),
+ "0" (eax), "1" (edx));
+
+ /*
+ * Due to rounding errors (and jiffies inconsistencies),
+ * we need to check the result so that we'll get a timer
+ * that is monotonic.
+ */
+ if (edx >= 1000020/HZ)
+ edx = 1000020/HZ-1;
+
+ missing_time = edx + delay_at_last_interrupt;
if (last_jiffies != tmp) {
last_jiffies = tmp;
/*
@@ -75,7 +103,7 @@
*/
if (test_bit(TIMER_BH, &bh_active) )
{
- missing_time = 1000020/HZ;
+ missing_time += 1000020/HZ;
}

/* Get last timer tick in absolute kernel time */
@@ -106,36 +134,9 @@
:"r" (tmp),
"0" (eax), "1" (edx));
cached_quotient = eax;
- quotient = eax;
}

- /* Read the time counter */
- __asm__(".byte 0x0f,0x31"
- :"=a" (eax), "=d" (edx));
-
- /* .. relative to previous jiffy (32 bits is enough) */
- edx = 0;
- eax -= low_timer;
-
- /*
- * Time offset = (1000020/HZ * time_low) / quotient.
- */
-
- __asm__("mull %2"
- :"=a" (eax), "=d" (edx)
- :"r" (quotient),
- "0" (eax), "1" (edx));
-
- /*
- * Due to rounding errors (and jiffies inconsistencies),
- * we need to check the result so that we'll get a timer
- * that is monotonic.
- */
- if (edx >= 1000020/HZ)
- edx = 1000020/HZ-1;
-
- eax = edx + missing_time;
- return eax;
+ return missing_time;
}
#endif

@@ -387,10 +388,22 @@
*/
static void pentium_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
+ int count;
+
/* read Pentium cycle counter */
__asm__(".byte 0x0f,0x31"
:"=a" (last_timer_cc.low),
"=d" (last_timer_cc.high));
+
+ /* estimate the delay to avoid jitter when reading the time */
+ outb_p(0x00, 0x43); /* latch the count ASAP */
+
+ count = inb_p(0x40); /* read the latched count */
+ count |= inb(0x40) << 8;
+
+ count = ((LATCH-1) - count) * TICK_SIZE;
+ delay_at_last_interrupt = (count + LATCH/2) / LATCH;
+
timer_interrupt(irq, NULL, regs);
}
#endif

-
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/

\
 
 \ /
  Last update: 2005-03-22 13:50    [W:0.027 / U:1.492 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site