ntpshmwrite.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /*
  2. * ntpshmwrite.c - put time information in SHM segment for ntpd
  3. *
  4. * This file is Copyright 2010 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. /* put a received fix time into shared memory for NTP */
  23. void ntp_write(volatile struct shmTime *shmseg,
  24. struct timedelta_t *td, int precision, int leap_notify)
  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 */
  76. // vim: set expandtab shiftwidth=4