19
24
# include <utmpx.h>
20
25
#endif /* HAVE_UTMPX_H */
22
int systime_10ms_ticks = 0; /* adj sysclock in 10ms increments */
25
* These routines (init_systime, get_systime, step_systime, adj_systime)
26
* implement an interface between the (more or less) system independent
27
* bits of NTP and the peculiarities of dealing with the Unix system
28
* These routines (get_systime, step_systime, adj_systime) implement an
29
* interface between the system independent NTP clock and the Unix
30
* system clock in various architectures and operating systems.
32
* Time is a precious quantity in these routines and every effort is
33
* made to minimize errors by always rounding toward zero and amortizing
34
* adjustment residues. By default the adjustment quantum is 1 us for
35
* the usual Unix tickadj() system call, but this can be increased if
36
* necessary by a configuration command. For instance, when the
37
* adjtime() quantum is a clock tick for a 100-Hz clock, the quantum
30
double sys_residual = 0; /* residual from previous adjustment */
40
double sys_tick = 1e-6; /* tickadj() quantum (s) */
41
double sys_residual = 0; /* adjustment residue (s) */
34
* get_systime - return the system time in timestamp format biased by
35
* the current time offset.
46
* get_systime - return system time in NTP timestamp format.
50
l_fp *now /* system time */
42
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
55
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
56
struct timespec ts; /* seconds and nanoseconds */
50
* We use nanosecond time if we can get it. Watch out for
51
* rounding wiggles, which may overflow the fraction.
59
* Convert Unix clock from seconds and nanoseconds to seconds.
53
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
54
61
# ifdef HAVE_CLOCK_GETTIME
55
(void) clock_gettime(CLOCK_REALTIME, &ts);
62
clock_gettime(CLOCK_REALTIME, &ts);
57
(void) getclock(TIMEOFDAY, &ts);
64
getclock(TIMEOFDAY, &ts);
59
66
now->l_i = ts.tv_sec + JAN_1970;
60
dtemp = ts.tv_nsec * FRAC / 1e9;
63
now->l_uf = (u_int32)dtemp;
64
#else /* HAVE_CLOCK_GETTIME */
65
(void) GETTIMEOFDAY(&tv, (struct timezone *)0);
67
dtemp = ts.tv_nsec / 1e9;
69
#else /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */
70
struct timeval tv; /* seconds and microseconds */
73
* Convert Unix clock from seconds and microseconds to seconds.
75
GETTIMEOFDAY(&tv, NULL);
66
76
now->l_i = tv.tv_sec + JAN_1970;
68
#if defined RELIANTUNIX_CLOCK || defined SCO5_CLOCK
69
if (systime_10ms_ticks) {
70
/* fake better than 10ms resolution by interpolating
71
accumulated residual (in adj_systime(), see below) */
72
dtemp = tv.tv_usec / 1e6;
73
if (sys_residual < 5000e-6 && sys_residual > -5000e-6) {
74
dtemp += sys_residual;
84
dtemp = tv.tv_usec * FRAC / 1e6;
77
dtemp = tv.tv_usec / 1e6;
79
#endif /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */
82
* Renormalize to seconds past 1900 and fraction.
84
dtemp += sys_residual;
88
} else if (dtemp < -1) {
88
93
now->l_uf = (u_int32)dtemp;
89
#endif /* HAVE_CLOCK_GETTIME */
95
* adj_systime - called once every second to make system time adjustments.
96
* Returns 1 if okay, 0 if trouble.
98
* adj_systime - adjust system time by the argument.
98
100
#if !defined SYS_WINNT
101
int /* 0 okay, 1 error */
103
double now /* adjustment (s) */
105
struct timeval adjtv;
107
struct timeval oadjtv;
106
struct timeval adjtv; /* new adjustment */
107
struct timeval oadjtv; /* residual adjustment */
110
* Add the residual from the previous adjustment to the new
111
* adjustment, bound and round.
113
* Most Unix adjtime() implementations adjust the system clock
114
* in microsecond quanta, but some adjust in 10-ms quanta. We
115
* carefully round the adjustment to the nearest quantum, then
116
* adjust in quanta and keep the residue for later.
113
dtemp = sys_residual + now;
118
dtemp = now + sys_residual;
120
#if defined RELIANTUNIX_CLOCK || defined SCO5_CLOCK
121
if (systime_10ms_ticks) {
122
/* accumulate changes until we have enough to adjust a tick */
123
if (dtemp < 5000e-6) {
124
if (isneg) sys_residual = -dtemp;
125
else sys_residual = dtemp;
128
if (isneg) sys_residual = 10000e-6 - dtemp;
129
else sys_residual = dtemp - 10000e-6;
134
if (dtemp > NTP_MAXFREQ)
137
dtemp = dtemp * 1e6 + .5;
142
adjtv.tv_usec = (int32)dtemp;
123
adjtv.tv_sec = (long)dtemp;
124
dtemp -= adjtv.tv_sec;
125
ticks = (long)(dtemp / sys_tick + .5);
126
adjtv.tv_usec = (long)(ticks * sys_tick * 1e6);
127
dtemp -= adjtv.tv_usec / 1e6;
128
sys_residual = dtemp;
145
* Here we do the actual adjustment. If for some reason the adjtime()
146
* call fails, like it is not implemented or something like that,
147
* we honk to the log. If the previous adjustment did not complete,
148
* we correct the residual offset.
131
* Convert to signed seconds and microseconds for the Unix
132
* adjtime() system call. Note we purposely lose the adjtime()
150
/* casey - we need a posix type thang here */
151
if (adjtime(&adjtv, &oadjtv) < 0)
153
msyslog(LOG_ERR, "Can't adjust time (%ld sec, %ld usec): %m",
154
(long)adjtv.tv_sec, (long)adjtv.tv_usec);
158
sys_residual += oadjtv.tv_usec / 1e6;
162
printf("adj_systime: adj %.9f -> remaining residual %.9f\n", now, sys_residual);
136
adjtv.tv_sec = -adjtv.tv_sec;
137
adjtv.tv_usec = -adjtv.tv_usec;
139
if (adjtime(&adjtv, &oadjtv) < 0) {
140
msyslog(LOG_ERR, "adj_systime: %m");
343
* Clock routines for the simulator - Harish Nair, with help
346
* get_systime - return the system time in NTP timestamp format
350
l_fp *now /* current system time in l_fp */ )
353
* To fool the code that determines the local clock precision,
354
* we advance the clock a minimum of 200 nanoseconds on every
355
* clock read. This is appropriate for a typical modern machine
356
* with nanosecond clocks. Note we make no attempt here to
357
* simulate reading error, since the error is so small. This may
358
* change when the need comes to implement picosecond clocks.
360
if (ntp_node.ntp_time == ntp_node.last_time)
361
ntp_node.ntp_time += 200e-9;
362
ntp_node.last_time = ntp_node.ntp_time;
363
DTOLFP(ntp_node.ntp_time, now);
368
* adj_systime - advance or retard the system clock exactly like the
371
int /* always succeeds */
373
double now /* time adjustment (s) */
376
struct timeval adjtv; /* new adjustment */
382
* Most Unix adjtime() implementations adjust the system clock
383
* in microsecond quanta, but some adjust in 10-ms quanta. We
384
* carefully round the adjustment to the nearest quantum, then
385
* adjust in quanta and keep the residue for later.
387
dtemp = now + sys_residual;
392
adjtv.tv_sec = (long)dtemp;
393
dtemp -= adjtv.tv_sec;
394
ticks = (long)(dtemp / sys_tick + .5);
395
adjtv.tv_usec = (long)(ticks * sys_tick * 1e6);
396
dtemp -= adjtv.tv_usec / 1e6;
397
sys_residual = dtemp;
400
* Convert to signed seconds and microseconds for the Unix
401
* adjtime() system call. Note we purposely lose the adjtime()
405
adjtv.tv_sec = -adjtv.tv_sec;
406
adjtv.tv_usec = -adjtv.tv_usec;
407
sys_residual = -sys_residual;
411
* We went to all the trouble just to be sure the emulation is
412
* precise. We now return to our regularly scheduled concert.
414
ntp_node.clk_time -= adjtv.tv_sec + adjtv.tv_usec / 1e6;
420
* step_systime - step the system clock. We are religious here.
422
int /* always succeeds */
424
double now /* step adjustment (s) */
429
printf("step_systime: time %.6f adj %.6f\n",
430
ntp_node.ntp_time, now);
432
ntp_node.ntp_time += now;
437
* node_clock - update the clocks
439
int /* always succeeds */
441
Node *n, /* global node pointer */
442
double t /* node time */
448
* Advance client clock (ntp_time). Advance server clock
449
* (clk_time) adjusted for systematic and random frequency
450
* errors. The random error is a random walk computed as the
451
* integral of samples from a Gaussian distribution.
453
dtemp = t - n->ntp_time;
455
n->ntp_time += dtemp;
456
n->ferr += gauss(0, dtemp * n->fnse);
457
n->clk_time += dtemp * (1 + n->ferr);
460
* Perform the adjtime() function. If the adjustment completed
461
* in the previous interval, amortize the entire amount; if not,
462
* carry the leftover to the next interval.
465
if (dtemp < fabs(n->adj)) {
468
n->ntp_time -= dtemp;
471
n->ntp_time += dtemp;
474
n->ntp_time += n->adj;
482
* gauss() - returns samples from a gaussion distribution
484
double /* Gaussian sample */
486
double m, /* sample mean */
487
double s /* sample standard deviation (sigma) */
493
* Roll a sample from a Gaussian distribution with mean m and
494
* standard deviation s. For m = 0, s = 1, mean(y) = 0,
499
while ((q1 = drand48()) == 0);
501
return (m + s * sqrt(-2. * log(q1)) * cos(2. * PI * q2));
506
* poisson() - returns samples from a network delay distribution
508
double /* delay sample (s) */
510
double m, /* fixed propagation delay (s) */
511
double s /* exponential parameter (mu) */
517
* Roll a sample from a composite distribution with propagation
518
* delay m and exponential distribution time with parameter s.
519
* For m = 0, s = 1, mean(y) = std(y) = 1.
523
while ((q1 = drand48()) == 0);
524
return (m - s * log(q1 * s));