Date: Sun, 28 Jun 1998 20:14:48 +0200 (SAT) From: John Hay <jhay@mikom.csir.co.za> To: phk@critter.freebsd.dk (Poul-Henning Kamp) Cc: freebsd-smp@FreeBSD.ORG Subject: Re: time problem? Message-ID: <199806281814.UAA09849@zibbi.mikom.csir.co.za> In-Reply-To: <2720.899034051@critter.freebsd.dk> from Poul-Henning Kamp at "Jun 28, 98 01:40:51 pm"
next in thread | previous in thread | raw e-mail | index | archive | help
> >I have found that my dual P5 100MHz machine will gain +- 0.85 seconds > >every now and again. [...] > >so it looks like it has something > >to do with the SMP code. It also does not seem to have anything to do > >with how busy the machine is, it has happened on a totally idle machine > >and also during a make world. > > > >Anybody have any ideas how I can look for this? I don't understand all > >the low level time stuff yet (especially the SMP side of it), but if > >given a little direction I'm willing to try a few things. > > It is really very simple, and there is nothing SMP specific about the > code. > > .85 seconds sounds suspiciosly like 2^20 cycles at 1193182 Hz. Ok, it is possible that I just haven't waited long enough with the UP kernel, but I can try again. > > Unfortunately that doesn't really make any kind of sense to me... > > How do you detect this jump ? what is the exact sequnce of events ? Well, it is actually the one that you gave me to test the new pps api with, which I modified a little. I'll attach it at the end. I have an 1 pps signal connected to DCD of my serial port. With sysctl kern.timecounter.frequency I tune the frequency until it runs as accurately as possible. Then I use "ntpdate -b <timeserver>" a few times to get the offset small. Then I run my little program and wait until it shows a jump. Then I use "ntpdate -d <timeserver>" to make sure that it was really a jump. Basically what the program does is to fetch the timestamp from the kernel and if it is within bounds, printf("...\r") it. If it is out of bounds, it add a printf("\n") before and after it. The values that it print is the timestamp (sec.nanosec), the sequence number and the time difference between this and the previous timestamp/. Here is the output of a piece of it: ---------------- A: 899000790.981073054 #29011 D: 1.000004191 A: 899000792.826104370 #29012 D: 1.845031316 A: 899016109.813482765 #44329 D: 0.999940488 A: 899016111.668519664 #44330 D: 1.855036899 ---------- So on sequence numbers 29012 and 44330, I have gained .85 seconds in the space of a second. For the 15000 seconds between 29012 and 44329 there were no glitches or jumps. > > The only possibly weak spot I know is this test in i386/isa/clock.c, > you can try out this patch, but I doubt it will fix it. Ok, I'll try it. I do also get glitches where the time will jump forward or backward by 1 tick (10ms), but it will correct itself on the next sample, so it does not have a long term effect. I thought its source was also this piece of code. I get about 30-50 of these per day, using my test program. Is this function, i8254_get_timecount(), used by something that can have a permanent effect on time? I thought it was only used by nanotime() and microtime() to get the offset from the previous tick, but that it wasn't used to calculate the next tick? > > Index: clock.c > =================================================================== > RCS file: /home/ncvs/src/sys/i386/isa/clock.c,v > retrieving revision 1.124 > diff -u -r1.124 clock.c > --- clock.c 1998/06/09 13:10:46 1.124 > +++ clock.c 1998/06/28 11:39:03 > @@ -1148,7 +1148,7 @@ > high = inb(TIMER_CNTR0); > > count = hardclock_max_count - ((high << 8) | low); > - if (count < i8254_lastcount) { > + if (count <= i8254_lastcount) { > i8254_ticked = 1; > i8254_offset += hardclock_max_count; > } John -- John Hay -- John.Hay@mikom.csir.co.za ----------------------------- ppstst2.c ----------------------------- #include <stdio.h> #include <errno.h> #include <fcntl.h> #include <err.h> #include <sys/types.h> #include <time.h> #include <timepps.h> #if 1 #define DEVNAME "/dev/gps0" #else #define DEVNAME "/dev/lppps0" #endif int main(int argc, char **argv) { int fd; struct timespec dts; pps_info_t pi, opi; pps_params_t pp; pps_handle_t ph; int i, mode; float df; fd = open(DEVNAME, O_RDONLY); if (fd < 0) err(1, DEVNAME); i = time_pps_create(fd, &ph); if (i < 0) err(1, "time_pps_create"); i = time_pps_getcap(ph, &mode); if (i < 0) err(1, "time_pps_getcap"); printf("getcap says %x\n", mode); pp.mode = PPS_CAPTUREASSERT; i = time_pps_setparams(ph, &pp); if (i < 0) err(1, "time_pps_setparams"); i = time_pps_fetch(ph, &pi); if (i < 0) err(1, "time_pps_fetch"); opi = pi; while (1) { i = time_pps_fetch(ph, &pi); if (i < 0) err(1, "time_pps_fetch"); if (opi.assert_sequence != pi.assert_sequence) { dts.tv_sec = pi.assert_timestamp.tv_sec - opi.assert_timestamp.tv_sec; dts.tv_nsec = pi.assert_timestamp.tv_nsec - opi.assert_timestamp.tv_nsec; if (dts.tv_nsec < 0) { dts.tv_sec--; dts.tv_nsec += 1000000000; } df = (float)dts.tv_sec; df += (float)dts.tv_nsec / 1000000000.0; if (df > 1.001 || df < 0.999) printf("\n"); printf("A: %d.%09d #%d D: %d.%09d\r", pi.assert_timestamp.tv_sec, pi.assert_timestamp.tv_nsec, pi.assert_sequence, dts.tv_sec, dts.tv_nsec); if (df > 1.001 || df < 0.999) printf("\n"); else fflush(NULL); opi = pi; } #if 0 printf("A: %d.%09d #%d C: %d.%09d #%d\n", pi.assert_timestamp.tv_sec, pi.assert_timestamp.tv_nsec, pi.assert_sequence, pi.clear_timestamp.tv_sec, pi.clear_timestamp.tv_nsec, pi.clear_sequence); #endif usleep(250000); } return(0); } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-smp" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199806281814.UAA09849>