1 #include "ntp_unixtime.h"
5 #define DEFAULT_SYS_PRECISION -99
7 int default_get_resolution();
8 int default_get_precision();
16 printf("log2(resolution) = %d, log2(precision) = %d\n",
17 default_get_resolution(),
18 default_get_precision());
22 /* Find the resolution of the system clock by watching how the current time
23 * changes as we read it repeatedly.
25 * struct timeval is only good to 1us, which may cause problems as machines
26 * get faster, but until then the logic goes:
28 * If a machine has resolution (i.e. accurate timing info) > 1us, then it will
29 * probably use the "unused" low order bits as a counter (to force time to be
30 * a strictly increaing variable), incrementing it each time any process
31 * requests the time [[ or maybe time will stand still ? ]].
35 * IF the difference from the last time is "small" (< MINSTEP)
36 * THEN this machine is "counting" with the low order bits
37 * ELIF this is not the first time round the loop
38 * THEN this machine *WAS* counting, and has now stepped
39 * ELSE this machine has resolution < time to read clock
41 * SO: if it exits on the first loop, assume "full accuracy" (1us)
42 * otherwise, take the log2(observered difference, rounded UP)
44 * MINLOOPS > 1 ensures that even if there is a STEP between the initial call
45 * and the first loop, it doesn't stop too early.
46 * Making it even greater allows MINSTEP to be reduced, assuming that the
47 * chance of MINSTEP-1 other processes getting in and calling gettimeofday
48 * between this processes's calls.
49 * Reducing MINSTEP may be necessary as this sets an upper bound for the time
50 * to actually call gettimeofday.
53 #define DUSECS 1000000
54 #define HUSECS (1024 * 1024)
55 #define MINSTEP 5 /* some systems increment uS on each call */
56 /* Don't use "1" as some *other* process may read too*/
57 /*We assume no system actually *ANSWERS* in this time*/
58 #define MAXSTEP 20000 /* maximum clock increment (us) */
59 #define MINLOOPS 5 /* minimum number of step samples */
60 #define MAXLOOPS HUSECS /* Assume precision < .1s ! */
63 default_get_resolution(void)
71 int minsteps = MINLOOPS; /* need at least this many steps */
73 gettimeofday(&tp, &tzp);
75 for (i = - --minsteps; i< MAXLOOPS; i++) {
76 gettimeofday(&tp, &tzp);
77 diff = tp.tv_usec - last;
78 if (diff < 0) diff += DUSECS;
79 if (diff > MINSTEP) if (minsteps-- <= 0) break;
83 printf("resolution = %ld usec after %d loop%s\n",
84 diff, i, (i==1) ? "" : "s");
89 " (Boy this machine is fast ! %d loops without a step)\n",
91 diff = 1; /* No STEP, so FAST machine */
95 " (The resolution is less than the time to read the clock -- Assume 1us)\n");
96 diff = 1; /* time to read clock >= resolution */
98 for (i=0, val=HUSECS; val>0; i--, val >>= 1) if (diff >= val) return i;
99 printf(" (Oh dear -- that wasn't expected ! I'll guess !)\n");
100 return DEFAULT_SYS_PRECISION /* Something's BUST, so lie ! */;
103 /* ===== Rest of this code lifted straight from xntpd/ntp_proto.c ! ===== */
106 * This routine calculates the differences between successive calls to
107 * gettimeofday(). If a difference is less than zero, the us field
108 * has rolled over to the next second, so we add a second in us. If
109 * the difference is greater than zero and less than MINSTEP, the
110 * clock has been advanced by a small amount to avoid standing still.
111 * If the clock has advanced by a greater amount, then a timer interrupt
112 * has occurred and this amount represents the precision of the clock.
113 * In order to guard against spurious values, which could occur if we
114 * happen to hit a fat interrupt, we do this for MINLOOPS times and
115 * keep the minimum value obtained.
118 default_get_precision(void)
134 (void) getclock(TIMEOFDAY, &ts);
135 tp.tv_sec = ts.tv_sec;
136 tp.tv_usec = ts.tv_nsec / 1000;
137 #else /* not HAVE_GETCLOCK */
138 GETTIMEOFDAY(&tp, &tzp);
139 #endif /* not HAVE_GETCLOCK */
141 for (i = 0; i < MINLOOPS && usec < HUSECS;) {
143 (void) getclock(TIMEOFDAY, &ts);
144 tp.tv_sec = ts.tv_sec;
145 tp.tv_usec = ts.tv_nsec / 1000;
146 #else /* not HAVE_GETCLOCK */
147 GETTIMEOFDAY(&tp, &tzp);
148 #endif /* not HAVE_GETCLOCK */
149 diff = tp.tv_usec - last;
154 if (diff > MINSTEP) {
160 printf("precision = %ld usec after %d loop%s\n",
161 val, i, (i == 1) ? "" : "s");
162 if (usec >= HUSECS) {
163 printf(" (Boy this machine is fast ! usec was %ld)\n",
165 val = MINSTEP; /* val <= MINSTEP; fast machine */
168 for (i = 0; diff > val; i--)