Sync usage with man page.
[netbsd-mini2440.git] / dist / ntp / libntp / systime.c
blobdf255019b61d6560f26e38caaf626f2d478baa15
1 /* $NetBSD: systime.c,v 1.4 2003/12/04 17:22:31 drochner Exp $ */
3 /*
4 * systime -- routines to fiddle a UNIX clock.
6 * ATTENTION: Get approval from Dave Mills on all changes to this file!
8 */
9 #include "ntp_machine.h"
10 #include "ntp_fp.h"
11 #include "ntp_syslog.h"
12 #include "ntp_unixtime.h"
13 #include "ntp_stdlib.h"
14 #include "ntp_random.h"
15 #include "ntpd.h" /* for sys_precision */
17 #ifdef SIM
18 # include "ntpsim.h"
19 #endif /*SIM */
21 #ifdef HAVE_SYS_PARAM_H
22 # include <sys/param.h>
23 #endif
24 #ifdef HAVE_UTMP_H
25 # include <utmp.h>
26 #endif /* HAVE_UTMP_H */
27 #ifdef HAVE_UTMPX_H
28 # include <utmpx.h>
29 #endif /* HAVE_UTMPX_H */
32 * These routines (get_systime, step_systime, adj_systime) implement an
33 * interface between the system independent NTP clock and the Unix
34 * system clock in various architectures and operating systems.
36 * Time is a precious quantity in these routines and every effort is
37 * made to minimize errors by always rounding toward zero and amortizing
38 * adjustment residues. By default the adjustment quantum is 1 us for
39 * the usual Unix tickadj() system call, but this can be increased if
40 * necessary by the tick configuration command. For instance, when the
41 * adjtime() quantum is a clock tick for a 100-Hz clock, the quantum
42 * should be 10 ms.
44 #if defined RELIANTUNIX_CLOCK || defined SCO5_CLOCK
45 double sys_tick = 10e-3; /* 10 ms tickadj() */
46 #else
47 double sys_tick = 1e-6; /* 1 us tickadj() */
48 #endif
49 double sys_residual = 0; /* adjustment residue (s) */
51 #ifndef SIM
54 * get_systime - return system time in NTP timestamp format.
56 void
57 get_systime(
58 l_fp *now /* system time */
61 double dtemp;
63 #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
64 struct timespec ts; /* seconds and nanoseconds */
67 * Convert Unix clock from seconds and nanoseconds to seconds.
68 * The bottom is only two bits down, so no need for fuzz.
69 * Some systems don't have that level of precision, however...
71 # ifdef HAVE_CLOCK_GETTIME
72 clock_gettime(CLOCK_REALTIME, &ts);
73 # else
74 getclock(TIMEOFDAY, &ts);
75 # endif
76 now->l_i = ts.tv_sec + JAN_1970;
77 dtemp = ts.tv_nsec / 1e9;
79 #else /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */
80 struct timeval tv; /* seconds and microseconds */
83 * Convert Unix clock from seconds and microseconds to seconds.
84 * Add in unbiased random fuzz beneath the microsecond.
86 GETTIMEOFDAY(&tv, NULL);
87 now->l_i = tv.tv_sec + JAN_1970;
88 dtemp = tv.tv_usec / 1e6;
90 #endif /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */
93 * ntp_random() produces 31 bits (always nonnegative).
94 * This bit is done only after the precision has been
95 * determined.
97 if (sys_precision != 0)
98 dtemp += (ntp_random() / FRAC - .5) / (1 <<
99 -sys_precision);
102 * Renormalize to seconds past 1900 and fraction.
104 dtemp += sys_residual;
105 if (dtemp >= 1) {
106 dtemp -= 1;
107 now->l_i++;
108 } else if (dtemp < 0) {
109 dtemp += 1;
110 now->l_i--;
112 dtemp *= FRAC;
113 now->l_uf = (u_int32)dtemp;
118 * adj_systime - adjust system time by the argument.
120 #if !defined SYS_WINNT
121 int /* 0 okay, 1 error */
122 adj_systime(
123 double now /* adjustment (s) */
126 struct timeval adjtv; /* new adjustment */
127 struct timeval oadjtv; /* residual adjustment */
128 double dtemp;
129 long ticks;
130 int isneg = 0;
133 * Most Unix adjtime() implementations adjust the system clock
134 * in microsecond quanta, but some adjust in 10-ms quanta. We
135 * carefully round the adjustment to the nearest quantum, then
136 * adjust in quanta and keep the residue for later.
138 dtemp = now + sys_residual;
139 if (dtemp < 0) {
140 isneg = 1;
141 dtemp = -dtemp;
143 adjtv.tv_sec = (long)dtemp;
144 dtemp -= adjtv.tv_sec;
145 ticks = (long)(dtemp / sys_tick + .5);
146 adjtv.tv_usec = (long)(ticks * sys_tick * 1e6);
147 dtemp -= adjtv.tv_usec / 1e6;
148 sys_residual = dtemp;
151 * Convert to signed seconds and microseconds for the Unix
152 * adjtime() system call. Note we purposely lose the adjtime()
153 * leftover.
155 if (isneg) {
156 adjtv.tv_sec = -adjtv.tv_sec;
157 adjtv.tv_usec = -adjtv.tv_usec;
158 sys_residual = -sys_residual;
160 if (adjtv.tv_sec != 0 || adjtv.tv_usec != 0) {
161 if (adjtime(&adjtv, &oadjtv) < 0) {
162 msyslog(LOG_ERR, "adj_systime: %m");
163 return (0);
166 return (1);
168 #endif
172 * step_systime - step the system clock.
175 step_systime(
176 double now
179 struct timeval timetv, adjtv, oldtimetv;
180 int isneg = 0;
181 double dtemp;
182 #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
183 struct timespec ts;
184 #endif
186 dtemp = sys_residual + now;
187 if (dtemp < 0) {
188 isneg = 1;
189 dtemp = - dtemp;
190 adjtv.tv_sec = (int32)dtemp;
191 adjtv.tv_usec = (u_int32)((dtemp -
192 (double)adjtv.tv_sec) * 1e6 + .5);
193 } else {
194 adjtv.tv_sec = (int32)dtemp;
195 adjtv.tv_usec = (u_int32)((dtemp -
196 (double)adjtv.tv_sec) * 1e6 + .5);
198 #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
199 # ifdef HAVE_CLOCK_GETTIME
200 (void) clock_gettime(CLOCK_REALTIME, &ts);
201 # else
202 (void) getclock(TIMEOFDAY, &ts);
203 # endif
204 timetv.tv_sec = ts.tv_sec;
205 timetv.tv_usec = ts.tv_nsec / 1000;
206 #else /* not HAVE_GETCLOCK */
207 (void) GETTIMEOFDAY(&timetv, (struct timezone *)0);
208 #endif /* not HAVE_GETCLOCK */
210 oldtimetv = timetv;
212 #ifdef DEBUG
213 if (debug)
214 printf("step_systime: step %.6f residual %.6f\n", now, sys_residual);
215 #endif
216 if (isneg) {
217 timetv.tv_sec -= adjtv.tv_sec;
218 timetv.tv_usec -= adjtv.tv_usec;
219 if (timetv.tv_usec < 0) {
220 timetv.tv_sec--;
221 timetv.tv_usec += 1000000;
223 } else {
224 timetv.tv_sec += adjtv.tv_sec;
225 timetv.tv_usec += adjtv.tv_usec;
226 if (timetv.tv_usec >= 1000000) {
227 timetv.tv_sec++;
228 timetv.tv_usec -= 1000000;
231 if (ntp_set_tod(&timetv, NULL) != 0) {
232 msyslog(LOG_ERR, "step-systime: %m");
233 return (0);
235 sys_residual = 0;
237 #ifdef NEED_HPUX_ADJTIME
239 * CHECKME: is this correct when called by ntpdate?????
241 _clear_adjtime();
242 #endif
245 * FreeBSD, for example, has:
246 * struct utmp {
247 * char ut_line[UT_LINESIZE];
248 * char ut_name[UT_NAMESIZE];
249 * char ut_host[UT_HOSTSIZE];
250 * long ut_time;
251 * };
252 * and appends line="|", name="date", host="", time for the OLD
253 * and appends line="{", name="date", host="", time for the NEW
254 * to _PATH_WTMP .
256 * Some OSes have utmp, some have utmpx.
260 * Write old and new time entries in utmp and wtmp if step
261 * adjustment is greater than one second.
263 * This might become even Uglier...
265 if (oldtimetv.tv_sec != timetv.tv_sec)
267 #ifdef HAVE_UTMP_H
268 struct utmp ut;
269 #endif
270 #ifdef HAVE_UTMPX_H
271 struct utmpx utx;
272 #endif
274 #ifdef HAVE_UTMP_H
275 memset((char *)&ut, 0, sizeof(ut));
276 #endif
277 #ifdef HAVE_UTMPX_H
278 memset((char *)&utx, 0, sizeof(utx));
279 #endif
281 /* UTMP */
283 #ifdef UPDATE_UTMP
284 # ifdef HAVE_PUTUTLINE
285 ut.ut_type = OLD_TIME;
286 (void)strcpy(ut.ut_line, OTIME_MSG);
287 ut.ut_time = oldtimetv.tv_sec;
288 pututline(&ut);
289 setutent();
290 ut.ut_type = NEW_TIME;
291 (void)strcpy(ut.ut_line, NTIME_MSG);
292 ut.ut_time = timetv.tv_sec;
293 pututline(&ut);
294 endutent();
295 # else /* not HAVE_PUTUTLINE */
296 # endif /* not HAVE_PUTUTLINE */
297 #endif /* UPDATE_UTMP */
299 /* UTMPX */
301 #ifdef UPDATE_UTMPX
302 # ifdef HAVE_PUTUTXLINE
303 utx.ut_type = OLD_TIME;
304 (void)strcpy(utx.ut_line, OTIME_MSG);
305 utx.ut_tv = oldtimetv;
306 pututxline(&utx);
307 setutxent();
308 utx.ut_type = NEW_TIME;
309 (void)strcpy(utx.ut_line, NTIME_MSG);
310 utx.ut_tv = timetv;
311 pututxline(&utx);
312 endutxent();
313 # else /* not HAVE_PUTUTXLINE */
314 # endif /* not HAVE_PUTUTXLINE */
315 #endif /* UPDATE_UTMPX */
317 /* WTMP */
319 #ifdef UPDATE_WTMP
320 # ifdef HAVE_PUTUTLINE
321 utmpname(WTMP_FILE);
322 ut.ut_type = OLD_TIME;
323 (void)strcpy(ut.ut_line, OTIME_MSG);
324 ut.ut_time = oldtimetv.tv_sec;
325 pututline(&ut);
326 ut.ut_type = NEW_TIME;
327 (void)strcpy(ut.ut_line, NTIME_MSG);
328 ut.ut_time = timetv.tv_sec;
329 pututline(&ut);
330 endutent();
331 # else /* not HAVE_PUTUTLINE */
332 # endif /* not HAVE_PUTUTLINE */
333 #endif /* UPDATE_WTMP */
335 /* WTMPX */
337 #ifdef UPDATE_WTMPX
338 # ifdef HAVE_PUTUTXLINE
339 utx.ut_type = OLD_TIME;
340 utx.ut_tv = oldtimetv;
341 (void)strcpy(utx.ut_line, OTIME_MSG);
342 # ifdef HAVE_UPDWTMPX
343 updwtmpx(WTMPX_FILE, &utx);
344 # else /* not HAVE_UPDWTMPX */
345 # endif /* not HAVE_UPDWTMPX */
346 # else /* not HAVE_PUTUTXLINE */
347 # endif /* not HAVE_PUTUTXLINE */
348 # ifdef HAVE_PUTUTXLINE
349 utx.ut_type = NEW_TIME;
350 utx.ut_tv = timetv;
351 (void)strcpy(utx.ut_line, NTIME_MSG);
352 # ifdef HAVE_UPDWTMPX
353 updwtmpx(WTMPX_FILE, &utx);
354 # else /* not HAVE_UPDWTMPX */
355 # endif /* not HAVE_UPDWTMPX */
356 # else /* not HAVE_PUTUTXLINE */
357 # endif /* not HAVE_PUTUTXLINE */
358 #endif /* UPDATE_WTMPX */
361 return (1);
364 #else /* SIM */
366 * Clock routines for the simulator - Harish Nair, with help
369 * get_systime - return the system time in NTP timestamp format
371 void
372 get_systime(
373 l_fp *now /* current system time in l_fp */ )
376 * To fool the code that determines the local clock precision,
377 * we advance the clock a minimum of 200 nanoseconds on every
378 * clock read. This is appropriate for a typical modern machine
379 * with nanosecond clocks. Note we make no attempt here to
380 * simulate reading error, since the error is so small. This may
381 * change when the need comes to implement picosecond clocks.
383 if (ntp_node.ntp_time == ntp_node.last_time)
384 ntp_node.ntp_time += 200e-9;
385 ntp_node.last_time = ntp_node.ntp_time;
386 DTOLFP(ntp_node.ntp_time, now);
391 * adj_systime - advance or retard the system clock exactly like the
392 * real thng.
394 int /* always succeeds */
395 adj_systime(
396 double now /* time adjustment (s) */
399 struct timeval adjtv; /* new adjustment */
400 double dtemp;
401 long ticks;
402 int isneg = 0;
405 * Most Unix adjtime() implementations adjust the system clock
406 * in microsecond quanta, but some adjust in 10-ms quanta. We
407 * carefully round the adjustment to the nearest quantum, then
408 * adjust in quanta and keep the residue for later.
410 dtemp = now + sys_residual;
411 if (dtemp < 0) {
412 isneg = 1;
413 dtemp = -dtemp;
415 adjtv.tv_sec = (long)dtemp;
416 dtemp -= adjtv.tv_sec;
417 ticks = (long)(dtemp / sys_tick + .5);
418 adjtv.tv_usec = (long)(ticks * sys_tick * 1e6);
419 dtemp -= adjtv.tv_usec / 1e6;
420 sys_residual = dtemp;
423 * Convert to signed seconds and microseconds for the Unix
424 * adjtime() system call. Note we purposely lose the adjtime()
425 * leftover.
427 if (isneg) {
428 adjtv.tv_sec = -adjtv.tv_sec;
429 adjtv.tv_usec = -adjtv.tv_usec;
430 sys_residual = -sys_residual;
432 ntp_node.adj = now;
433 return (1);
438 * step_systime - step the system clock. We are religious here.
440 int /* always succeeds */
441 step_systime(
442 double now /* step adjustment (s) */
445 #ifdef DEBUG
446 if (debug)
447 printf("step_systime: time %.6f adj %.6f\n",
448 ntp_node.ntp_time, now);
449 #endif
450 ntp_node.ntp_time += now;
451 return (1);
455 * node_clock - update the clocks
457 int /* always succeeds */
458 node_clock(
459 Node *n, /* global node pointer */
460 double t /* node time */
463 double dtemp;
466 * Advance client clock (ntp_time). Advance server clock
467 * (clk_time) adjusted for systematic and random frequency
468 * errors. The random error is a random walk computed as the
469 * integral of samples from a Gaussian distribution.
471 dtemp = t - n->ntp_time;
472 n->time = t;
473 n->ntp_time += dtemp;
474 n->ferr += gauss(0, dtemp * n->fnse);
475 n->clk_time += dtemp * (1 + n->ferr);
478 * Perform the adjtime() function. If the adjustment completed
479 * in the previous interval, amortize the entire amount; if not,
480 * carry the leftover to the next interval.
482 dtemp *= n->slew;
483 if (dtemp < fabs(n->adj)) {
484 if (n->adj < 0) {
485 n->adj += dtemp;
486 n->ntp_time -= dtemp;
487 } else {
488 n->adj -= dtemp;
489 n->ntp_time += dtemp;
491 } else {
492 n->ntp_time += n->adj;
493 n->adj = 0;
495 return (0);
500 * gauss() - returns samples from a gaussion distribution
502 double /* Gaussian sample */
503 gauss(
504 double m, /* sample mean */
505 double s /* sample standard deviation (sigma) */
508 double q1, q2;
511 * Roll a sample from a Gaussian distribution with mean m and
512 * standard deviation s. For m = 0, s = 1, mean(y) = 0,
513 * std(y) = 1.
515 if (s == 0)
516 return (m);
517 while ((q1 = drand48()) == 0);
518 q2 = drand48();
519 return (m + s * sqrt(-2. * log(q1)) * cos(2. * PI * q2));
524 * poisson() - returns samples from a network delay distribution
526 double /* delay sample (s) */
527 poisson(
528 double m, /* fixed propagation delay (s) */
529 double s /* exponential parameter (mu) */
532 double q1;
535 * Roll a sample from a composite distribution with propagation
536 * delay m and exponential distribution time with parameter s.
537 * For m = 0, s = 1, mean(y) = std(y) = 1.
539 if (s == 0)
540 return (m);
541 while ((q1 = drand48()) == 0);
542 return (m - s * log(q1 * s));
544 #endif /* SIM */