/contrib/ntp/libntp/systime.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 542 lines · 347 code · 50 blank · 145 comment · 51 complexity · b3f2dd5d51f2a68f9f3468fe465afa3d MD5 · raw file

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