xref: /freebsd/contrib/ntp/libntp/systime.c (revision 6ae1554a5d9b318f8ad53ccc39fa5a961403da73)
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 */
571