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