Description of problem: gettimeofday() on linux-ia64 tries to provide a microsecond resolution on base kernels (2.4, 2.6). However with RHEL3 release kernel, the resolution is only milliseconds. Version-Release number of selected component (if applicable): 2.4.21-4.EL How reproducible: Run this program: #include <stdio.h> #include <sys/time.h> int main() { struct timeval tv1, tv2; gettimeofday( & tv1, 0 ); gettimeofday( & tv2, 0 ); while (tv2.tv_usec - tv1.tv_usec == 0) { gettimeofday( & tv2, 0 ); } printf("Minimum measurable time: %d seconds, %d usecs\n", tv2.tv_sec - tv1.tv_sec, tv2.tv_usec - tv1.tv_usec); } The problem seems to be coming from a machine independent patch being maintained in the linux-ia64-2.4, accessible here: http://lia64.bkbits.net:8080/linux-ia64-2.4/diffs/kernel/timer.c@1.8?nav=index.html|src/|src/kernel|hist/kernel/timer.c This patch is missing from RHEL3. Because last_time_offset doesn't reset to zero after a timer tick, it's monotonically increasing. gettimeofday always returns xtime + last_time_offset. As a result the return value of gettimeofday doesn't change between timer ticks.
Apart from the timer resolution issues, this bug could also result in unsynchronized clocks on a cluster of NTP synchronized machines.
ok, here is the patch i'm proposing for RHEL 3. i haven't included the timer bit in sys_nanosleep, b/c i don't consider that essetial. --- linux-2.4.21/kernel/timer.c.bak 2003-11-12 14:44:56.000000000 -0500 +++ linux-2.4.21/kernel/timer.c 2003-11-12 14:45:54.000000000 -0500 @@ -1206,7 +1206,7 @@ asmlinkage long sys_nanosleep(struct tim return 0; } - +unsigned long last_time_offset; static inline void update_times(void) { @@ -1226,6 +1226,7 @@ static inline void update_times(void) update_wall_time(ticks); } vxtime_unlock(); + last_time_offset = 0; br_write_unlock_irq(BR_XTIME_LOCK); calc_load(ticks); } --- linux-2.4.21/arch/ia64/kernel/time.c.bak 2003-11-12 14:44:33.000000000 -0500 +++ linux-2.4.21/arch/ia64/kernel/time.c 2003-11-12 14:44:44.000000000 -0500 @@ -27,7 +27,7 @@ extern unsigned long wall_jiffies; -unsigned long last_time_offset; +extern unsigned long last_time_offset; #ifdef CONFIG_IA64_DEBUG_IRQ unsigned long last_cli_ip;
ok, i'm proposing just the first part of this patch for RHEL 3, as the remainder is not critical, imo: --- linux-2.4.21/kernel/timer.c.bak 2003-11-12 14:44:56.000000000 -0500 +++ linux-2.4.21/kernel/timer.c 2003-11-12 14:45:54.000000000 -0500 @@ -1206,7 +1206,7 @@ asmlinkage long sys_nanosleep(struct tim return 0; } - +unsigned long last_time_offset; static inline void update_times(void) { @@ -1226,6 +1226,7 @@ static inline void update_times(void) update_wall_time(ticks); } vxtime_unlock(); + last_time_offset = 0; br_write_unlock_irq(BR_XTIME_LOCK); calc_load(ticks); } --- linux-2.4.21/arch/ia64/kernel/time.c.bak 2003-11-12 14:44:33.000000000 -0500 +++ linux-2.4.21/arch/ia64/kernel/time.c 2003-11-12 14:44:44.000000000 -0500 @@ -27,7 +27,7 @@ extern unsigned long wall_jiffies; -unsigned long last_time_offset; +extern unsigned long last_time_offset; #ifdef CONFIG_IA64_DEBUG_IRQ unsigned long last_cli_ip;
The patch looks good to me.
A variant of this fix was committed to RHEL 3 U1 on 14-Nov-2003 (kernel versions 2.4.21-4.15.EL and later).
An errata has been issued which should help the problem described in this bug report. This report is therefore being closed with a resolution of ERRATA. For more information on the solution and/or where to find the updated files, please follow the link below. You may reopen this bug report if the solution does not work for you. http://rhn.redhat.com/errata/RHSA-2004-017.html