ntpshmwrite.c 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * ntpshmwrite.c - put time information in SHM segment for ntpd
  3. *
  4. * This file is Copyright (c)2010-2018 by the GPSD project
  5. * SPDX-License-Identifier: BSD-2-clause
  6. */
  7. #include "gpsd_config.h" /* must be before all includes */
  8. #include <errno.h>
  9. #include <libgen.h>
  10. #include <math.h>
  11. #include <stdbool.h>
  12. #include <string.h>
  13. #include <sys/socket.h>
  14. #include <sys/stat.h>
  15. #include <sys/types.h>
  16. #include <sys/wait.h>
  17. #include <unistd.h>
  18. #include "ntpshm.h"
  19. #include "compiler.h"
  20. #include "timespec.h"
  21. #define LEAP_NOWARNING 0x0 /* normal, no leap second warning */
  22. void ntp_write(volatile struct shmTime *shmseg,
  23. struct timedelta_t *td, int precision, int leap_notify)
  24. /* put a received fix time into shared memory for NTP */
  25. {
  26. struct tm tm;
  27. /*
  28. * insist that leap seconds only happen in june and december
  29. * GPS emits leap pending for 3 months prior to insertion
  30. * NTP expects leap pending for only 1 month prior to insertion
  31. * Per http://bugs.ntp.org/1090
  32. *
  33. * ITU-R TF.460-6, Section 2.1, says laep seconds can be primarily
  34. * in Jun/Dec but may be in March or September
  35. */
  36. (void)gmtime_r( &(td->real.tv_sec), &tm);
  37. if ( 5 != tm.tm_mon && 11 != tm.tm_mon ) {
  38. /* Not june, not December, no way */
  39. leap_notify = LEAP_NOWARNING;
  40. }
  41. /* we use the shmTime mode 1 protocol
  42. *
  43. * ntpd does this:
  44. *
  45. * reads valid.
  46. * IFF valid is 1
  47. * reads count
  48. * reads values
  49. * reads count
  50. * IFF count unchanged
  51. * use values
  52. * clear valid
  53. *
  54. */
  55. // should not be needed, but sometimes is...
  56. TS_NORM(&td->real);
  57. TS_NORM(&td->clock);
  58. shmseg->valid = 0;
  59. shmseg->count++;
  60. /* We need a memory barrier here to prevent write reordering by
  61. * the compiler or CPU cache */
  62. memory_barrier();
  63. shmseg->clockTimeStampSec = (time_t)td->real.tv_sec;
  64. shmseg->clockTimeStampUSec = (int)(td->real.tv_nsec/1000);
  65. shmseg->clockTimeStampNSec = (unsigned)td->real.tv_nsec;
  66. shmseg->receiveTimeStampSec = (time_t)td->clock.tv_sec;
  67. shmseg->receiveTimeStampUSec = (int)(td->clock.tv_nsec/1000);
  68. shmseg->receiveTimeStampNSec = (unsigned)td->clock.tv_nsec;
  69. shmseg->leap = leap_notify;
  70. shmseg->precision = precision;
  71. memory_barrier();
  72. shmseg->count++;
  73. shmseg->valid = 1;
  74. }
  75. /* end */