~ubuntu-branches/debian/squeeze/ntp/squeeze-201010051545

« back to all changes in this revision

Viewing changes to libntp/systime.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-10-11 16:10:27 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20041011161027-icyjbji8ujym633o
Tags: 1:4.2.0a-10ubuntu2
Use ntp.ubuntulinux.org instead of pool.ntp.org

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * systime -- routines to fiddle a UNIX clock.
 
3
 *
 
4
 * ATTENTION: Get approval from Dave Mills on all changes to this file!
 
5
 *
3
6
 */
4
 
 
5
 
#include "ntp_proto.h"          /* for MAX_FREQ */
6
7
#include "ntp_machine.h"
7
8
#include "ntp_fp.h"
8
9
#include "ntp_syslog.h"
9
10
#include "ntp_unixtime.h"
10
11
#include "ntp_stdlib.h"
11
12
 
 
13
#ifdef SIM
 
14
#include "ntpsim.h"
 
15
#endif /*SIM */
 
16
 
12
17
#ifdef HAVE_SYS_PARAM_H
13
18
# include <sys/param.h>
14
19
#endif
19
24
# include <utmpx.h>
20
25
#endif /* HAVE_UTMPX_H */
21
26
 
22
 
int     systime_10ms_ticks = 0; /* adj sysclock in 10ms increments */
23
 
 
24
27
/*
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
 
 * clock.
 
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.
 
31
 *
 
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
 
38
 * should be 10 ms.
29
39
 */
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) */
31
42
 
 
43
#ifndef SIM
32
44
 
33
45
/*
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.
36
47
 */
37
48
void
38
49
get_systime(
39
 
        l_fp *now
 
50
        l_fp *now               /* system time */
40
51
        )
41
52
{
42
 
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
43
 
        struct timespec ts;
44
 
#else
45
 
        struct timeval tv;
46
 
#endif
47
53
        double dtemp;
48
54
 
 
55
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
 
56
        struct timespec ts;     /* seconds and nanoseconds */
 
57
 
49
58
        /*
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.
52
60
         */
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);
56
63
# else
57
 
        (void) getclock(TIMEOFDAY, &ts);
 
64
        getclock(TIMEOFDAY, &ts);
58
65
# endif
59
66
        now->l_i = ts.tv_sec + JAN_1970;
60
 
        dtemp = ts.tv_nsec * FRAC / 1e9;
61
 
        if (dtemp >= FRAC)
62
 
                now->l_i++;
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;
 
68
 
 
69
#else /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */
 
70
        struct timeval tv;      /* seconds and microseconds */
 
71
 
 
72
        /*
 
73
         * Convert Unix clock from seconds and microseconds to seconds.
 
74
         */
 
75
        GETTIMEOFDAY(&tv, NULL);
66
76
        now->l_i = tv.tv_sec + JAN_1970;
67
 
 
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;
75
 
                        if (dtemp < 0) {
76
 
                                now->l_i--;
77
 
                                dtemp++;
78
 
                        }
79
 
                }
80
 
                dtemp *= FRAC;
81
 
        } else
82
 
#endif
83
 
 
84
 
        dtemp = tv.tv_usec * FRAC / 1e6;
85
 
 
86
 
        if (dtemp >= FRAC)
 
77
        dtemp = tv.tv_usec / 1e6;
 
78
 
 
79
#endif /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */
 
80
 
 
81
        /*
 
82
         * Renormalize to seconds past 1900 and fraction.
 
83
         */
 
84
        dtemp += sys_residual;
 
85
        if (dtemp >= 1) {
 
86
                dtemp -= 1;
87
87
                now->l_i++;
 
88
        } else if (dtemp < -1) {
 
89
                dtemp += 1;
 
90
                now->l_i--;
 
91
        }
 
92
        dtemp *= FRAC;
88
93
        now->l_uf = (u_int32)dtemp;
89
 
#endif /* HAVE_CLOCK_GETTIME */
90
 
 
91
94
}
92
95
 
93
96
 
94
97
/*
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.
97
99
 */
98
100
#if !defined SYS_WINNT
99
 
int
 
101
int                             /* 0 okay, 1 error */
100
102
adj_systime(
101
 
        double now
 
103
        double now              /* adjustment (s) */
102
104
        )
103
105
{
104
 
        double dtemp;
105
 
        struct timeval adjtv;
106
 
        u_char isneg = 0;
107
 
        struct timeval oadjtv;
 
106
        struct timeval adjtv;   /* new adjustment */
 
107
        struct timeval oadjtv;  /* residual adjustment */
 
108
        double  dtemp;
 
109
        long    ticks;
 
110
        int     isneg = 0;
108
111
 
109
112
        /*
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.
112
117
         */
113
 
        dtemp = sys_residual + now;
114
 
        sys_residual = 0;
 
118
        dtemp = now + sys_residual;
115
119
        if (dtemp < 0) {
116
120
                isneg = 1;
117
121
                dtemp = -dtemp;
118
122
        }
119
 
 
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;
126
 
                        dtemp = 0;
127
 
                } else {
128
 
                        if (isneg) sys_residual = 10000e-6 - dtemp;
129
 
                        else sys_residual = dtemp - 10000e-6;
130
 
                        dtemp = 10000e-6;
131
 
                }
132
 
        } else 
133
 
#endif
134
 
                if (dtemp > NTP_MAXFREQ)
135
 
                        dtemp = NTP_MAXFREQ;
136
 
 
137
 
        dtemp = dtemp * 1e6 + .5;
138
 
 
139
 
        if (isneg)
140
 
                dtemp = -dtemp;
141
 
        adjtv.tv_sec = 0;
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;
143
129
 
144
130
        /*
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()
 
133
         * leftover.
149
134
         */
150
 
        /* casey - we need a posix type thang here */
151
 
        if (adjtime(&adjtv, &oadjtv) < 0)
152
 
        {
153
 
                msyslog(LOG_ERR, "Can't adjust time (%ld sec, %ld usec): %m",
154
 
                        (long)adjtv.tv_sec, (long)adjtv.tv_usec);
155
 
                return 0;
156
 
        } 
157
 
        else {
158
 
        sys_residual += oadjtv.tv_usec / 1e6;
159
 
        }
160
 
#ifdef DEBUG
161
 
        if (debug > 6)
162
 
                printf("adj_systime: adj %.9f -> remaining residual %.9f\n", now, sys_residual);
163
 
#endif
164
 
        return 1;
 
135
        if (isneg) {
 
136
                adjtv.tv_sec = -adjtv.tv_sec;
 
137
                adjtv.tv_usec = -adjtv.tv_usec;
 
138
        }
 
139
        if (adjtime(&adjtv, &oadjtv) < 0) {
 
140
                msyslog(LOG_ERR, "adj_systime: %m");
 
141
                return (0);
 
142
        }
 
143
        return (1);
165
144
}
166
145
#endif
167
146
 
186
165
                isneg = 1;
187
166
                dtemp = - dtemp;
188
167
                adjtv.tv_sec = (int32)dtemp;
189
 
                adjtv.tv_usec = (u_int32)((dtemp - (double)adjtv.tv_sec) *
190
 
                                          1e6 + .5);
 
168
                adjtv.tv_usec = (u_int32)((dtemp -
 
169
                    (double)adjtv.tv_sec) * 1e6 + .5);
191
170
        } else {
192
171
                adjtv.tv_sec = (int32)dtemp;
193
 
                adjtv.tv_usec = (u_int32)((dtemp - (double)adjtv.tv_sec) *
194
 
                                          1e6 + .5);
 
172
                adjtv.tv_usec = (u_int32)((dtemp -
 
173
                    (double)adjtv.tv_sec) * 1e6 + .5);
195
174
        }
196
175
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
197
176
#ifdef HAVE_CLOCK_GETTIME
226
205
                        timetv.tv_usec -= 1000000;
227
206
                }
228
207
        }
229
 
        if (ntp_set_tod(&timetv, (struct timezone *)0) != 0) {
230
 
                msyslog(LOG_ERR, "Can't set time of day: %m");
 
208
        if (ntp_set_tod(&timetv, NULL) != 0) {
 
209
                msyslog(LOG_ERR, "step-systime: %m");
231
210
                return (0);
232
211
        }
233
212
        sys_residual = 0;
255
234
         */
256
235
 
257
236
        /*
258
 
         * Write old and new time entries in utmp and wtmp if step adjustment
259
 
         * is greater than one second.
 
237
         * Write old and new time entries in utmp and wtmp if step
 
238
         * adjustment is greater than one second.
260
239
         *
261
240
         * This might become even Uglier...
262
241
         */
358
337
        }
359
338
        return (1);
360
339
}
 
340
 
 
341
#else /* SIM */
 
342
/*
 
343
 * Clock routines for the simulator - Harish Nair, with help
 
344
 */
 
345
/*
 
346
 * get_systime - return the system time in NTP timestamp format 
 
347
 */
 
348
void
 
349
get_systime(
 
350
        l_fp *now               /* current system time in l_fp */        )
 
351
{
 
352
        /*
 
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.
 
359
         */
 
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);
 
364
}
 
365
 
 
366
 
 
367
/*
 
368
 * adj_systime - advance or retard the system clock exactly like the
 
369
 * real thng.
 
370
 */
 
371
int                             /* always succeeds */
 
372
adj_systime(
 
373
        double now              /* time adjustment (s) */
 
374
        )
 
375
{
 
376
        struct timeval adjtv;   /* new adjustment */
 
377
        double  dtemp;
 
378
        long    ticks;
 
379
        int     isneg = 0;
 
380
 
 
381
        /*
 
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.
 
386
         */
 
387
        dtemp = now + sys_residual;
 
388
        if (dtemp < 0) {
 
389
                isneg = 1;
 
390
                dtemp = -dtemp;
 
391
        }
 
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;
 
398
 
 
399
        /*
 
400
         * Convert to signed seconds and microseconds for the Unix
 
401
         * adjtime() system call. Note we purposely lose the adjtime()
 
402
         * leftover.
 
403
         */
 
404
        if (isneg) {
 
405
                adjtv.tv_sec = -adjtv.tv_sec;
 
406
                adjtv.tv_usec = -adjtv.tv_usec;
 
407
                sys_residual = -sys_residual;
 
408
        }
 
409
 
 
410
        /*
 
411
         * We went to all the trouble just to be sure the emulation is
 
412
         * precise. We now return to our regularly scheduled concert.
 
413
         */
 
414
        ntp_node.clk_time -= adjtv.tv_sec + adjtv.tv_usec / 1e6;
 
415
        return (1);
 
416
}
 
417
 
 
418
 
 
419
/*
 
420
 * step_systime - step the system clock. We are religious here.
 
421
 */
 
422
int                             /* always succeeds */
 
423
step_systime(
 
424
        double now              /* step adjustment (s) */
 
425
        )
 
426
{
 
427
#ifdef DEBUG
 
428
        if (debug)
 
429
                printf("step_systime: time %.6f adj %.6f\n",
 
430
                   ntp_node.ntp_time, now);
 
431
#endif
 
432
        ntp_node.ntp_time += now;
 
433
        return (1);
 
434
}
 
435
 
 
436
/*
 
437
 * node_clock - update the clocks
 
438
 */
 
439
int                             /* always succeeds */
 
440
node_clock(
 
441
        Node *n,                /* global node pointer */
 
442
        double t                /* node time */
 
443
        )
 
444
{
 
445
        double  dtemp;
 
446
 
 
447
        /*
 
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.
 
452
         */
 
453
        dtemp = t - n->ntp_time;
 
454
        n->time = t;
 
455
        n->ntp_time += dtemp;
 
456
        n->ferr += gauss(0, dtemp * n->fnse);
 
457
        n->clk_time += dtemp * (1 + n->ferr);
 
458
 
 
459
        /*
 
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.
 
463
         */
 
464
        dtemp *= n->slew;
 
465
        if (dtemp < fabs(n->adj)) {
 
466
                if (n->adj < 0) {
 
467
                        n->adj += dtemp;
 
468
                        n->ntp_time -= dtemp;
 
469
                } else {
 
470
                        n->adj -= dtemp;
 
471
                        n->ntp_time += dtemp;
 
472
                }
 
473
        } else {
 
474
                n->ntp_time += n->adj;
 
475
                n->adj = 0;
 
476
        }
 
477
        return (0);
 
478
}
 
479
 
 
480
 
 
481
/*
 
482
 * gauss() - returns samples from a gaussion distribution
 
483
 */
 
484
double                          /* Gaussian sample */
 
485
gauss(
 
486
        double m,               /* sample mean */
 
487
        double s                /* sample standard deviation (sigma) */
 
488
        )
 
489
{
 
490
        double q1, q2;
 
491
 
 
492
        /*
 
493
         * Roll a sample from a Gaussian distribution with mean m and
 
494
         * standard deviation s. For m = 0, s = 1, mean(y) = 0,
 
495
         * std(y) = 1.
 
496
         */
 
497
        if (s == 0)
 
498
                return (m);
 
499
        while ((q1 = drand48()) == 0);
 
500
        q2 = drand48();
 
501
        return (m + s * sqrt(-2. * log(q1)) * cos(2. * PI * q2));
 
502
}
 
503
 
 
504
 
 
505
/*
 
506
 * poisson() - returns samples from a network delay distribution
 
507
 */
 
508
double                          /* delay sample (s) */
 
509
poisson(
 
510
        double m,               /* fixed propagation delay (s) */
 
511
        double s                /* exponential parameter (mu) */
 
512
        )
 
513
{
 
514
        double q1;
 
515
 
 
516
        /*
 
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.
 
520
         */
 
521
        if (s == 0)
 
522
                return (m);
 
523
        while ((q1 = drand48()) == 0);
 
524
        return (m - s * log(q1 * s));
 
525
}
 
526
#endif /* SIM */