]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/libntp/systime.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / ntp / libntp / systime.c
1 /*
2  * systime -- routines to fiddle a UNIX clock.
3  *
4  * ATTENTION: Get approval from Dave Mills on all changes to this file!
5  *
6  */
7 #include <config.h>
8
9 #include "ntp.h"
10 #include "ntp_syslog.h"
11 #include "ntp_stdlib.h"
12 #include "ntp_random.h"
13 #include "iosignal.h"
14 #include "timevalops.h"
15 #include "timespecops.h"
16 #include "ntp_calendar.h"
17
18 #ifdef HAVE_SYS_PARAM_H
19 # include <sys/param.h>
20 #endif
21 #ifdef HAVE_UTMP_H
22 # include <utmp.h>
23 #endif /* HAVE_UTMP_H */
24 #ifdef HAVE_UTMPX_H
25 # include <utmpx.h>
26 #endif /* HAVE_UTMPX_H */
27
28
29 #ifndef USE_COMPILETIME_PIVOT
30 # define USE_COMPILETIME_PIVOT 1
31 #endif
32
33 /*
34  * These routines (get_systime, step_systime, adj_systime) implement an
35  * interface between the system independent NTP clock and the Unix
36  * system clock in various architectures and operating systems. Time is
37  * a precious quantity in these routines and every effort is made to
38  * minimize errors by unbiased rounding and amortizing adjustment
39  * residues.
40  *
41  * In order to improve the apparent resolution, provide unbiased
42  * rounding and most importantly ensure that the readings cannot be
43  * predicted, the low-order unused portion of the time below the minimum
44  * time to read the clock is filled with an unbiased random fuzz.
45  *
46  * The sys_tick variable specifies the system clock tick interval in
47  * seconds, for stepping clocks, defined as those which return times
48  * less than MINSTEP greater than the previous reading. For systems that
49  * use a high-resolution counter such that each clock reading is always
50  * at least MINSTEP greater than the prior, sys_tick is the time to read
51  * the system clock.
52  *
53  * The sys_fuzz variable measures the minimum time to read the system
54  * clock, regardless of its precision.  When reading the system clock
55  * using get_systime() after sys_tick and sys_fuzz have been determined,
56  * ntpd ensures each unprocessed clock reading is no less than sys_fuzz
57  * later than the prior unprocessed reading, and then fuzzes the bits
58  * below sys_fuzz in the timestamp returned, ensuring each of its
59  * resulting readings is strictly later than the previous.
60  *
61  * When slewing the system clock using adj_systime() (with the kernel
62  * loop discipline unavailable or disabled), adjtime() offsets are
63  * quantized to sys_tick, if sys_tick is greater than sys_fuzz, which
64  * is to say if the OS presents a stepping clock.  Otherwise, offsets
65  * are quantized to the microsecond resolution of adjtime()'s timeval
66  * input.  The remaining correction sys_residual is carried into the
67  * next adjtime() and meanwhile is also factored into get_systime()
68  * readings.
69  */
70 double  sys_tick = 0;           /* tick size or time to read (s) */
71 double  sys_fuzz = 0;           /* min. time to read the clock (s) */
72 long    sys_fuzz_nsec = 0;      /* min. time to read the clock (ns) */
73 double  measured_tick;          /* non-overridable sys_tick (s) */
74 double  sys_residual = 0;       /* adjustment residue (s) */
75 int     trunc_os_clock;         /* sys_tick > measured_tick */
76 time_stepped_callback   step_callback;
77
78 #ifndef SIM
79 /* perlinger@ntp.org: As 'get_sysime()' does it's own check for clock
80  * backstepping, this could probably become a local variable in
81  * 'get_systime()' and the cruft associated with communicating via a
82  * static value could be removed after the v4.2.8 release.
83  */
84 static int lamport_violated;    /* clock was stepped back */
85 #endif  /* !SIM */
86
87 #ifdef DEBUG
88 static int systime_init_done;
89 # define DONE_SYSTIME_INIT()    systime_init_done = TRUE
90 #else
91 # define DONE_SYSTIME_INIT()    do {} while (FALSE)
92 #endif
93
94 #ifdef HAVE_SIGNALED_IO
95 int using_sigio;
96 #endif
97
98 #ifdef SYS_WINNT
99 CRITICAL_SECTION get_systime_cs;
100 #endif
101
102
103 void
104 set_sys_fuzz(
105         double  fuzz_val
106         )
107 {
108         sys_fuzz = fuzz_val;
109         INSIST(sys_fuzz >= 0);
110         INSIST(sys_fuzz <= 1.0);
111         sys_fuzz_nsec = (long)(sys_fuzz * 1e9 + 0.5);
112 }
113
114
115 void
116 init_systime(void)
117 {
118         INIT_GET_SYSTIME_CRITSEC();
119         INIT_WIN_PRECISE_TIME();
120         DONE_SYSTIME_INIT();
121 }
122
123
124 #ifndef SIM     /* ntpsim.c has get_systime() and friends for sim */
125
126 static inline void
127 get_ostime(
128         struct timespec *       tsp
129         )
130 {
131         int     rc;
132         long    ticks;
133
134 #if defined(HAVE_CLOCK_GETTIME)
135         rc = clock_gettime(CLOCK_REALTIME, tsp);
136 #elif defined(HAVE_GETCLOCK)
137         rc = getclock(TIMEOFDAY, tsp);
138 #else
139         struct timeval          tv;
140
141         rc = GETTIMEOFDAY(&tv, NULL);
142         tsp->tv_sec = tv.tv_sec;
143         tsp->tv_nsec = tv.tv_usec * 1000;
144 #endif
145         if (rc < 0) {
146                 msyslog(LOG_ERR, "read system clock failed: %m (%d)",
147                         errno);
148                 exit(1);
149         }
150
151         if (trunc_os_clock) {
152                 ticks = (long)((tsp->tv_nsec * 1e-9) / sys_tick);
153                 tsp->tv_nsec = (long)(ticks * 1e9 * sys_tick);
154         }
155 }
156
157
158 /*
159  * get_systime - return system time in NTP timestamp format.
160  */
161 void
162 get_systime(
163         l_fp *now               /* system time */
164         )
165 {
166         static struct timespec  ts_last;        /* last sampled os time */
167         static struct timespec  ts_prev;        /* prior os time */
168         static l_fp             lfp_prev;       /* prior result */
169         static double           dfuzz_prev;     /* prior fuzz */
170         struct timespec ts;     /* seconds and nanoseconds */
171         struct timespec ts_min; /* earliest permissible */
172         struct timespec ts_lam; /* lamport fictional increment */
173         struct timespec ts_prev_log;    /* for msyslog only */
174         double  dfuzz;
175         double  ddelta;
176         l_fp    result;
177         l_fp    lfpfuzz;
178         l_fp    lfpdelta;
179
180         get_ostime(&ts);
181         DEBUG_REQUIRE(systime_init_done);
182         ENTER_GET_SYSTIME_CRITSEC();
183
184         /* First check if here was a Lamport violation, that is, two
185          * successive calls to 'get_ostime()' resulted in negative
186          * time difference. Use a few milliseconds of permissible
187          * tolerance -- being too sharp can hurt here. (This is intented
188          * for the Win32 target, where the HPC interpolation might
189          * introduce small steps backward. It should not be an issue on
190          * systems where get_ostime() results in a true syscall.)
191          */
192         if (cmp_tspec(add_tspec_ns(ts, 50000000), ts_last) < 0)
193                 lamport_violated = 1;
194         ts_last = ts;
195
196         /*
197          * After default_get_precision() has set a nonzero sys_fuzz,
198          * ensure every reading of the OS clock advances by at least
199          * sys_fuzz over the prior reading, thereby assuring each
200          * fuzzed result is strictly later than the prior.  Limit the
201          * necessary fiction to 1 second.
202          */
203         if (!USING_SIGIO()) {
204                 ts_min = add_tspec_ns(ts_prev, sys_fuzz_nsec);
205                 if (cmp_tspec(ts, ts_min) < 0) {
206                         ts_lam = sub_tspec(ts_min, ts);
207                         if (ts_lam.tv_sec > 0 && !lamport_violated) {
208                                 msyslog(LOG_ERR,
209                                         "get_systime Lamport advance exceeds one second (%.9f)",
210                                         ts_lam.tv_sec +
211                                             1e-9 * ts_lam.tv_nsec);
212                                 exit(1);
213                         }
214                         if (!lamport_violated)
215                                 ts = ts_min;
216                 }
217                 ts_prev_log = ts_prev;
218                 ts_prev = ts;
219         } else {
220                 /*
221                  * Quiet "ts_prev_log.tv_sec may be used uninitialized"
222                  * warning from x86 gcc 4.5.2.
223                  */
224                 ZERO(ts_prev_log);
225         }
226
227         /* convert from timespec to l_fp fixed-point */
228         result = tspec_stamp_to_lfp(ts);
229
230         /*
231          * Add in the fuzz.
232          */
233         dfuzz = ntp_random() * 2. / FRAC * sys_fuzz;
234         DTOLFP(dfuzz, &lfpfuzz);
235         L_ADD(&result, &lfpfuzz);
236
237         /*
238          * Ensure result is strictly greater than prior result (ignoring
239          * sys_residual's effect for now) once sys_fuzz has been
240          * determined.
241          */
242         if (!USING_SIGIO()) {
243                 if (!L_ISZERO(&lfp_prev) && !lamport_violated) {
244                         if (!L_ISGTU(&result, &lfp_prev) &&
245                             sys_fuzz > 0.) {
246                                 msyslog(LOG_ERR, "ts_prev %s ts_min %s",
247                                         tspectoa(ts_prev_log),
248                                         tspectoa(ts_min));
249                                 msyslog(LOG_ERR, "ts %s", tspectoa(ts));
250                                 msyslog(LOG_ERR, "sys_fuzz %ld nsec, prior fuzz %.9f",
251                                         sys_fuzz_nsec, dfuzz_prev);
252                                 msyslog(LOG_ERR, "this fuzz %.9f",
253                                         dfuzz);
254                                 lfpdelta = lfp_prev;
255                                 L_SUB(&lfpdelta, &result);
256                                 LFPTOD(&lfpdelta, ddelta);
257                                 msyslog(LOG_ERR,
258                                         "prev get_systime 0x%x.%08x is %.9f later than 0x%x.%08x",
259                                         lfp_prev.l_ui, lfp_prev.l_uf,
260                                         ddelta, result.l_ui, result.l_uf);
261                         }
262                 }
263                 lfp_prev = result;
264                 dfuzz_prev = dfuzz;
265                 if (lamport_violated) 
266                         lamport_violated = FALSE;
267         }
268         LEAVE_GET_SYSTIME_CRITSEC();
269         *now = result;
270 }
271
272
273 /*
274  * adj_systime - adjust system time by the argument.
275  */
276 #if !defined SYS_WINNT
277 int                             /* 0 okay, 1 error */
278 adj_systime(
279         double now              /* adjustment (s) */
280         )
281 {
282         struct timeval adjtv;   /* new adjustment */
283         struct timeval oadjtv;  /* residual adjustment */
284         double  quant;          /* quantize to multiples of */
285         double  dtemp;
286         long    ticks;
287         int     isneg = 0;
288
289         /*
290          * The Windows port adj_systime() depends on being called each
291          * second even when there's no additional correction, to allow
292          * emulation of adjtime() behavior on top of an API that simply
293          * sets the current rate.  This POSIX implementation needs to
294          * ignore invocations with zero correction, otherwise ongoing
295          * EVNT_NSET adjtime() can be aborted by a tiny adjtime()
296          * triggered by sys_residual.
297          */
298         if (0. == now)
299                 return TRUE;
300
301         /*
302          * Most Unix adjtime() implementations adjust the system clock
303          * in microsecond quanta, but some adjust in 10-ms quanta. We
304          * carefully round the adjustment to the nearest quantum, then
305          * adjust in quanta and keep the residue for later.
306          */
307         dtemp = now + sys_residual;
308         if (dtemp < 0) {
309                 isneg = 1;
310                 dtemp = -dtemp;
311         }
312         adjtv.tv_sec = (long)dtemp;
313         dtemp -= adjtv.tv_sec;
314         if (sys_tick > sys_fuzz)
315                 quant = sys_tick;
316         else
317                 quant = 1e-6;
318         ticks = (long)(dtemp / quant + .5);
319         adjtv.tv_usec = (long)(ticks * quant * 1e6);
320         dtemp -= adjtv.tv_usec / 1e6;
321         sys_residual = dtemp;
322
323         /*
324          * Convert to signed seconds and microseconds for the Unix
325          * adjtime() system call. Note we purposely lose the adjtime()
326          * leftover.
327          */
328         if (isneg) {
329                 adjtv.tv_sec = -adjtv.tv_sec;
330                 adjtv.tv_usec = -adjtv.tv_usec;
331                 sys_residual = -sys_residual;
332         }
333         if (adjtv.tv_sec != 0 || adjtv.tv_usec != 0) {
334                 if (adjtime(&adjtv, &oadjtv) < 0) {
335                         msyslog(LOG_ERR, "adj_systime: %m");
336                         return FALSE;
337                 }
338         }
339         return TRUE;
340 }
341 #endif
342
343
344 /*
345  * step_systime - step the system clock.
346  */
347
348 int
349 step_systime(
350         double step
351         )
352 {
353         time_t pivot; /* for ntp era unfolding */
354         struct timeval timetv, tvlast, tvdiff;
355         struct timespec timets;
356         struct calendar jd;
357         l_fp fp_ofs, fp_sys; /* offset and target system time in FP */
358
359         /*
360          * Get pivot time for NTP era unfolding. Since we don't step
361          * very often, we can afford to do the whole calculation from
362          * scratch. And we're not in the time-critical path yet.
363          */
364 #if SIZEOF_TIME_T > 4
365         /*
366          * This code makes sure the resulting time stamp for the new
367          * system time is in the 2^32 seconds starting at 1970-01-01,
368          * 00:00:00 UTC.
369          */
370         pivot = 0x80000000;
371 #if USE_COMPILETIME_PIVOT
372         /*
373          * Add the compile time minus 10 years to get a possible target
374          * area of (compile time - 10 years) to (compile time + 126
375          * years).  This should be sufficient for a given binary of
376          * NTPD.
377          */
378         if (ntpcal_get_build_date(&jd)) {
379                 jd.year -= 10;
380                 pivot += ntpcal_date_to_time(&jd);
381         } else {
382                 msyslog(LOG_ERR,
383                         "step-systime: assume 1970-01-01 as build date");
384         }
385 #else
386         UNUSED_LOCAL(jd);
387 #endif /* USE_COMPILETIME_PIVOT */
388 #else
389         UNUSED_LOCAL(jd);
390         /* This makes sure the resulting time stamp is on or after
391          * 1969-12-31/23:59:59 UTC and gives us additional two years,
392          * from the change of NTP era in 2036 to the UNIX rollover in
393          * 2038. (Minus one second, but that won't hurt.) We *really*
394          * need a longer 'time_t' after that!  Or a different baseline,
395          * but that would cause other serious trouble, too.
396          */
397         pivot = 0x7FFFFFFF;
398 #endif
399
400         /* get the complete jump distance as l_fp */
401         DTOLFP(sys_residual, &fp_sys);
402         DTOLFP(step,         &fp_ofs);
403         L_ADD(&fp_ofs, &fp_sys);
404
405         /* ---> time-critical path starts ---> */
406
407         /* get the current time as l_fp (without fuzz) and as struct timeval */
408         get_ostime(&timets);
409         fp_sys = tspec_stamp_to_lfp(timets);
410         tvlast.tv_sec = timets.tv_sec;
411         tvlast.tv_usec = (timets.tv_nsec + 500) / 1000;
412
413         /* get the target time as l_fp */
414         L_ADD(&fp_sys, &fp_ofs);
415
416         /* unfold the new system time */
417         timetv = lfp_stamp_to_tval(fp_sys, &pivot);
418
419         /* now set new system time */
420         if (ntp_set_tod(&timetv, NULL) != 0) {
421                 msyslog(LOG_ERR, "step-systime: %m");
422                 return FALSE;
423         }
424
425         /* <--- time-critical path ended with 'ntp_set_tod()' <--- */
426
427         sys_residual = 0;
428         lamport_violated = (step < 0);
429         if (step_callback)
430                 (*step_callback)();
431
432 #ifdef NEED_HPUX_ADJTIME
433         /*
434          * CHECKME: is this correct when called by ntpdate?????
435          */
436         _clear_adjtime();
437 #endif
438
439         /*
440          * FreeBSD, for example, has:
441          * struct utmp {
442          *         char    ut_line[UT_LINESIZE];
443          *         char    ut_name[UT_NAMESIZE];
444          *         char    ut_host[UT_HOSTSIZE];
445          *         long    ut_time;
446          * };
447          * and appends line="|", name="date", host="", time for the OLD
448          * and appends line="{", name="date", host="", time for the NEW
449          * to _PATH_WTMP .
450          *
451          * Some OSes have utmp, some have utmpx.
452          */
453
454         /*
455          * Write old and new time entries in utmp and wtmp if step
456          * adjustment is greater than one second.
457          *
458          * This might become even Uglier...
459          */
460         tvdiff = abs_tval(sub_tval(timetv, tvlast));
461         if (tvdiff.tv_sec > 0) {
462 #ifdef HAVE_UTMP_H
463                 struct utmp ut;
464 #endif
465 #ifdef HAVE_UTMPX_H
466                 struct utmpx utx;
467 #endif
468
469 #ifdef HAVE_UTMP_H
470                 ZERO(ut);
471 #endif
472 #ifdef HAVE_UTMPX_H
473                 ZERO(utx);
474 #endif
475
476                 /* UTMP */
477
478 #ifdef UPDATE_UTMP
479 # ifdef HAVE_PUTUTLINE
480 #  ifndef _PATH_UTMP
481 #   define _PATH_UTMP UTMP_FILE
482 #  endif
483                 utmpname(_PATH_UTMP);
484                 ut.ut_type = OLD_TIME;
485                 strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line));
486                 ut.ut_time = tvlast.tv_sec;
487                 setutent();
488                 pututline(&ut);
489                 ut.ut_type = NEW_TIME;
490                 strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line));
491                 ut.ut_time = timetv.tv_sec;
492                 setutent();
493                 pututline(&ut);
494                 endutent();
495 # else /* not HAVE_PUTUTLINE */
496 # endif /* not HAVE_PUTUTLINE */
497 #endif /* UPDATE_UTMP */
498
499                 /* UTMPX */
500
501 #ifdef UPDATE_UTMPX
502 # ifdef HAVE_PUTUTXLINE
503                 utx.ut_type = OLD_TIME;
504                 strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line));
505                 utx.ut_tv = tvlast;
506                 setutxent();
507                 pututxline(&utx);
508                 utx.ut_type = NEW_TIME;
509                 strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line));
510                 utx.ut_tv = timetv;
511                 setutxent();
512                 pututxline(&utx);
513                 endutxent();
514 # else /* not HAVE_PUTUTXLINE */
515 # endif /* not HAVE_PUTUTXLINE */
516 #endif /* UPDATE_UTMPX */
517
518                 /* WTMP */
519
520 #ifdef UPDATE_WTMP
521 # ifdef HAVE_PUTUTLINE
522 #  ifndef _PATH_WTMP
523 #   define _PATH_WTMP WTMP_FILE
524 #  endif
525                 utmpname(_PATH_WTMP);
526                 ut.ut_type = OLD_TIME;
527                 strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line));
528                 ut.ut_time = tvlast.tv_sec;
529                 setutent();
530                 pututline(&ut);
531                 ut.ut_type = NEW_TIME;
532                 strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line));
533                 ut.ut_time = timetv.tv_sec;
534                 setutent();
535                 pututline(&ut);
536                 endutent();
537 # else /* not HAVE_PUTUTLINE */
538 # endif /* not HAVE_PUTUTLINE */
539 #endif /* UPDATE_WTMP */
540
541                 /* WTMPX */
542
543 #ifdef UPDATE_WTMPX
544 # ifdef HAVE_PUTUTXLINE
545                 utx.ut_type = OLD_TIME;
546                 utx.ut_tv = tvlast;
547                 strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line));
548 #  ifdef HAVE_UPDWTMPX
549                 updwtmpx(WTMPX_FILE, &utx);
550 #  else /* not HAVE_UPDWTMPX */
551 #  endif /* not HAVE_UPDWTMPX */
552 # else /* not HAVE_PUTUTXLINE */
553 # endif /* not HAVE_PUTUTXLINE */
554 # ifdef HAVE_PUTUTXLINE
555                 utx.ut_type = NEW_TIME;
556                 utx.ut_tv = timetv;
557                 strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line));
558 #  ifdef HAVE_UPDWTMPX
559                 updwtmpx(WTMPX_FILE, &utx);
560 #  else /* not HAVE_UPDWTMPX */
561 #  endif /* not HAVE_UPDWTMPX */
562 # else /* not HAVE_PUTUTXLINE */
563 # endif /* not HAVE_PUTUTXLINE */
564 #endif /* UPDATE_WTMPX */
565
566         }
567         return TRUE;
568 }
569
570 #endif  /* !SIM */