Best wishes for 2008 to you all. I noticed the gettimeofday02 test from LTP fails as follows on both SS20 and SS10: gettimeofday02 0 INFO : checking if gettimeofday is monotonous, takes 30s gettimeofday02 1 FAIL : Time is going backwards: old 1197574068.852502 vs new 1197574068.842505! Changing the test a bit shows time decreasing 684 times in a 30 second period, while incrementing 6993105 times. The second count is always incrementing, it is the microsecond count that decreases sometimes. The microseconds are determined by: (xtime.tv_nsec / 1000) + (l10_counter >> 10) I dumped both variables with a simple kernel module (first 2 attachments), which shows that xtime is monotonous, but l10_counter looks random to me. I do not know the problem here, and cannot find details on the operation of this counter property on sun4m. Maybe this l10_counter needs to be callibrated? I understand from include/asm-sparc/timer.h that l10_counter should count down on sun4m, which makes the current code all the more puzzling. The 3rd attachment has a patch that ignores l10_counter in the calculation, and shows the old code. Not sure if this is the right solution, but at least it fixes the problem. Moreover, I only have sun4m machines so cannot test this on other sparc32 machine types. Cheers, -- Martin Signed-off-by: Martin Habets <errandir_news@xxxxxxxxxxxxxxxxx>
palantir9:/tmp# insmod ./mod.ko l10_limit = 10241024 10001 0 l10_counter shr(10) xtime 5350912 5225 1199657069.356481 2157306368 9592 1199657069.366483 6301184 6153 1199657069.396487 2148020736 524 1199657069.396487 2153432064 5809 1199657069.406489 2461184 2403 1199657069.416490 2154276864 6634 1199657069.426492 3438592 3358 1199657069.446495 7822336 7639 1199657069.456496 2065920 2017 1199657069.466497 2153841664 6209 1199657069.466497 2906112 2838 1199657069.486500 7368704 7196 1199657069.496502 1619968 1582 1199657069.506503 6078464 5936 1199657069.516505 328192 320 1199657069.526506 3745280 3657 1199657069.536508 2155530752 7858 1199657069.536508 4595200 4487 1199657069.556511 9043968 8832 1199657069.566512 3302912 3225 1199657069.576514 7769600 7587 1199657069.586515 2007552 1960 1199657069.596517 6480384 6328 1199657069.606518 689152 673 1199657069.616520 insmod: error inserting './mod.ko': -1 No such device
#include <linux/module.h> //#include <linux/moduleparam.h> #include <linux/time.h> #include <asm/timer.h> MODULE_AUTHOR("Martin Habets"); MODULE_LICENSE("GPL"); static int __init tmod_init(void) { int i, c; c = sun4m_timers->l10_timer_limit; printk(KERN_INFO "l10_limit = %u\t%u\n%x\n", c, c >> 10, sun4m_timers->cfg); printk(KERN_INFO "l10_counter\tshr(10)\txtime\n"); for (i=0; i<25; i++) { c = sun4m_timers->l10_cur_count; printk(KERN_INFO "%8u\t%u\t%lu.%lu\n", c, (c>>10)&0x1fffff, xtime.tv_sec, xtime.tv_nsec/1000); } return(-ENODEV); } static void __exit tmod_exit(void) { } module_init(tmod_init); module_exit(tmod_exit);
Index: 2.6/arch/sparc/kernel/time.c =================================================================== --- 2.6.orig/arch/sparc/kernel/time.c 2007-12-14 21:16:45.000000000 +0000 +++ 2.6/arch/sparc/kernel/time.c 2007-12-14 21:17:58.000000000 +0000 @@ -425,58 +425,57 @@ void __init time_init(void) { #ifdef CONFIG_PCI extern void pci_time_init(void); if (pcic_present()) { pci_time_init(); return; } #endif sbus_time_init(); } static inline unsigned long do_gettimeoffset(void) { - return (*master_l10_counter >> 10) & 0x1fffff; + return (xtime.tv_nsec / 1000); } /* Ok, my cute asm atomicity trick doesn't work anymore. * There are just too many variables that need to be protected * now (both members of xtime, et al.) */ void do_gettimeofday(struct timeval *tv) { unsigned long flags; unsigned long seq; unsigned long usec, sec; unsigned long max_ntp_tick = tick_usec - tickadj; do { seq = read_seqbegin_irqsave(&xtime_lock, flags); usec = do_gettimeoffset(); /* * If time_adjust is negative then NTP is slowing the clock * so make sure not to go into next possible interval. * Better to lose some accuracy than have time go backwards.. */ if (unlikely(time_adjust < 0)) usec = min(usec, max_ntp_tick); sec = xtime.tv_sec; - usec += (xtime.tv_nsec / 1000); } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); while (usec >= 1000000) { usec -= 1000000; sec++; } tv->tv_sec = sec; tv->tv_usec = usec; } EXPORT_SYMBOL(do_gettimeofday); int do_settimeofday(struct timespec *tv) {