Hello, On Monday, September 24, 2007 at 6:06:17 -0400, A. Costa wrote:
> It seems 'adjtimex' is quite clock & CPU dependent; Yes, of course: adjtimex --adjust operation (and some others) does read the CMOS clock. On a system busy doing other things, the timings can be degraded, possibly very much. > it could check if the CPU was busy before making tests; And there could be some words about good conditions for such calibration in the install docs. It may not be completely obvious for everybody. > or a maximum adjustment, if exceeded, generates an error or else > triggers some appropriate response. The NTP community often presents ±500 PPM as the maximum for a sane motherboard. That would be ±43.2 secs/day. However machines over that do exist. And can be supported by adjtimex, provided this high rate is stable. The adjustement of --tick can even help such wild clocks to become disciplinable by the NTP daemon. What about a simple warning? We can also try to make adjtimex less sensible to system load. The first step on this path would be to timestamp more closely the RTC clock beat. The attached close-timestamping.2.patch does this. On my old and slow test machine, this reduced from around 80 µs to zero the timestamping delay. Both for /dev/rtc with interrupt, and the UIP polling method. This also reduced a little bit the variability of measures. And marginaly reduced the sensibility to system load. It's only a first step, though. James: Could you please also apply the 2nd attached email-free.patch, which updates my email address in adjtimex.c and ChangeLog. Thanks! BTW I suspect that in cmos_read_time() the case where we are using /dev/rtc but ioctl(RTC_UIE_ON) fails, just can't work: It will block forever in read() later. Can't verify for sure, because on my machines the ioctl(RTC_UIE_ON) succeeds. Alain.
Timestamp the tick of the CMOS clock at the closest possible, for better accuracy and lower dispersion of measures. Signed-off-by: Alain Guibert <[EMAIL PROTECTED]> diff -prud adjtimex-1.22/adjtimex.c adjtimex-1.22.mod/adjtimex.c --- adjtimex-1.22/adjtimex.c Mon Oct 1 00:15:15 2007 +++ adjtimex-1.22.mod/adjtimex.c Mon Oct 1 00:56:41 2007 @@ -151,7 +151,7 @@ static inline unsigned char inb (short p static void cmos_init (); static inline int cmos_read_bcd (int addr); static void cmos_read_time (time_t *cmos_timep, double *sysp); -static void busy_wait(void); +static void busy_wait(struct timeval *timestamp); static void compare(void); static void failntpdate(); static void reset_time_status(void); @@ -607,7 +607,7 @@ cmos_read_time (time_t *cmos_timep, doub fprintf(stdout, "/dev/rtc doesn't allow user access to update interrupts\n" " - using busy wait instead\n"); - busy_wait(); + busy_wait(&now); } { unsigned long dummy; @@ -615,7 +615,8 @@ cmos_read_time (time_t *cmos_timep, doub do { rc = read(cmos_fd, &dummy, sizeof(dummy)); - + gettimeofday(&now, NULL); + if (rc == -1) { perror("read() from /dev/rtc to wait for clock tick failed"); @@ -638,11 +639,11 @@ cmos_read_time (time_t *cmos_timep, doub } else { - busy_wait(); /* The "do" loop is "low-risk programming" */ /* In theory it should never run more than once */ do { + busy_wait(&now); tm.tm_sec = cmos_read_bcd (0); tm.tm_min = cmos_read_bcd (2); tm.tm_hour = cmos_read_bcd (4); @@ -661,9 +662,6 @@ cmos_read_time (time_t *cmos_timep, doub } tm.tm_isdst = -1; /* don't know whether it's summer time */ - - /* fetch system time immediately */ - gettimeofday (&now, NULL); if (universal) cmos_time = mkgmtime(&tm); @@ -742,8 +740,10 @@ cmos_read_time (time_t *cmos_timep, doub *sysp = now.tv_sec + .000001*now.tv_usec; } + +/* busywait for UIP fall and timestamp this event */ static void -busy_wait() +busy_wait(struct timeval *timestamp) { long i; @@ -757,8 +757,10 @@ busy_wait() /* Wait for fall.... (must try at least 2.228 ms) */ for (i = 0; i < 1000000; i++) - if (!(CMOS_READ (10) & 0x80)) + if (!(CMOS_READ (10) & 0x80)) { + gettimeofday(timestamp, NULL); break; + } } static inline void
Update Alain Guibert's email address in code and ChangeLog. Signed-off-by: Alain Guibert <[EMAIL PROTECTED]> diff -prud adjtimex-1.22.orig/ChangeLog adjtimex-1.22/ChangeLog --- adjtimex-1.22.orig/ChangeLog Sun Sep 23 18:27:04 2007 +++ adjtimex-1.22/ChangeLog Mon Oct 1 14:37:09 2007 @@ -72,7 +72,7 @@ * adjtimex.c (compare): Adjust CMOS times by + or - 60 min, if that brings them closer to the system time. If they still differ by more than 6 min, then print a warning and suppress logging. - (Thanks to Alain Guibert <derogaton at oreka.com> for noting that + (Thanks to Alain Guibert <alguibert at free.fr> for noting that summer time start/end can impact the log.) 2006-05-21 James R. Van Zandt <jrv at debian.org> @@ -92,8 +92,8 @@ * adjtimex.c (compare): in "compare" or "adjust", return immediately after printing last result (instead of sleeping an - extra $interval seconds) (Thanks to Alain Guibert <derogaton at - oreka.com>) + extra $interval seconds) (Thanks to Alain Guibert <alguibert at + free.fr>) 2004-09-11 James R. Van Zandt <jrv at debian.org> @@ -119,12 +119,12 @@ * adjtimex.c (usage): Don't split strings across lines. (main): --reset switch enables resetting of status (no longer default action, because it's not needed by recent kernels) (thanks - to Alain Guibert <derogaton at oreka.com>) + to Alain Guibert <alguibert at free.fr>) 2004-04-09 James R. Van Zandt <jrv at debian.org> * adjtimex.c (longopt): --status switch sets clock status - (courtesy of Alain Guibert <derogaton at oreka.com> + (courtesy of Alain Guibert <alguibert at free.fr> 2004-04-04 James R. Van Zandt <jrv at debian.org> diff -prud adjtimex-1.22.orig/adjtimex.c adjtimex-1.22/adjtimex.c --- adjtimex-1.22.orig/adjtimex.c Sun Sep 23 18:49:10 2007 +++ adjtimex-1.22/adjtimex.c Mon Oct 1 14:34:11 2007 @@ -677,7 +677,7 @@ cmos_read_time (time_t *cmos_timep, doub { /* There are clues to whether the CMOS clock is set to summer time, which could be used as suggested by Alain - Guibert <derogaton at oreka.com>: + Guibert <alguibert at free.fr>: Since version 2.5, hwclock records CMOS timezone UTC or LOCAL as 1st item of 3rd line of /etc/adjtime. If it's