/contrib/ntp/ntpd/refclock_shm.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 312 lines · 240 code · 22 blank · 50 comment · 20 complexity · 5b9c01d3f4f2d9316ad5df2c6a866218 MD5 · raw file

  1. /*
  2. * refclock_shm - clock driver for utc via shared memory
  3. * - under construction -
  4. * To add new modes: Extend or union the shmTime-struct. Do not
  5. * extend/shrink size, because otherwise existing implementations
  6. * will specify wrong size of shared memory-segment
  7. * PB 18.3.97
  8. */
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. #if defined(REFCLOCK) && defined(CLOCK_SHM)
  13. #include "ntpd.h"
  14. #undef fileno
  15. #include "ntp_io.h"
  16. #undef fileno
  17. #include "ntp_refclock.h"
  18. #undef fileno
  19. #include "ntp_unixtime.h"
  20. #undef fileno
  21. #include "ntp_stdlib.h"
  22. #undef fileno
  23. #include <ctype.h>
  24. #undef fileno
  25. #ifndef SYS_WINNT
  26. # include <sys/ipc.h>
  27. # include <sys/shm.h>
  28. # include <assert.h>
  29. # include <unistd.h>
  30. # include <stdio.h>
  31. #endif
  32. /*
  33. * This driver supports a reference clock attached thru shared memory
  34. */
  35. /*
  36. * SHM interface definitions
  37. */
  38. #define PRECISION (-1) /* precision assumed (0.5 s) */
  39. #define REFID "SHM" /* reference ID */
  40. #define DESCRIPTION "SHM/Shared memory interface"
  41. #define NSAMPLES 3 /* stages of median filter */
  42. /*
  43. * Function prototypes
  44. */
  45. static int shm_start (int, struct peer *);
  46. static void shm_shutdown (int, struct peer *);
  47. static void shm_poll (int unit, struct peer *);
  48. /*
  49. * Transfer vector
  50. */
  51. struct refclock refclock_shm = {
  52. shm_start, /* start up driver */
  53. shm_shutdown, /* shut down driver */
  54. shm_poll, /* transmit poll message */
  55. noentry, /* not used */
  56. noentry, /* initialize driver (not used) */
  57. noentry, /* not used */
  58. NOFLAGS /* not used */
  59. };
  60. struct shmTime {
  61. int mode; /* 0 - if valid set
  62. * use values,
  63. * clear valid
  64. * 1 - if valid set
  65. * if count before and after read of values is equal,
  66. * use values
  67. * clear valid
  68. */
  69. int count;
  70. time_t clockTimeStampSec;
  71. int clockTimeStampUSec;
  72. time_t receiveTimeStampSec;
  73. int receiveTimeStampUSec;
  74. int leap;
  75. int precision;
  76. int nsamples;
  77. int valid;
  78. int dummy[10];
  79. };
  80. struct shmTime *getShmTime(int);
  81. struct shmTime *getShmTime (int unit) {
  82. #ifndef SYS_WINNT
  83. int shmid=0;
  84. assert (unit<10); /* MAXUNIT is 4, so should never happen */
  85. shmid=shmget (0x4e545030+unit, sizeof (struct shmTime),
  86. IPC_CREAT|(unit<2?0700:0777));
  87. if (shmid==-1) { /*error */
  88. msyslog(LOG_ERR,"SHM shmget (unit %d): %s",unit,strerror(errno));
  89. return 0;
  90. }
  91. else { /* no error */
  92. struct shmTime *p=(struct shmTime *)shmat (shmid, 0, 0);
  93. if ((int)(long)p==-1) { /* error */
  94. msyslog(LOG_ERR,"SHM shmat (unit %d): %s",unit,strerror(errno));
  95. return 0;
  96. }
  97. return p;
  98. }
  99. #else
  100. char buf[10];
  101. LPSECURITY_ATTRIBUTES psec=0;
  102. HANDLE shmid=0;
  103. SECURITY_DESCRIPTOR sd;
  104. SECURITY_ATTRIBUTES sa;
  105. sprintf (buf,"NTP%d",unit);
  106. if (unit>=2) { /* world access */
  107. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  108. msyslog(LOG_ERR,"SHM InitializeSecurityDescriptor (unit %d): %m",unit);
  109. return 0;
  110. }
  111. if (!SetSecurityDescriptorDacl(&sd,1,0,0)) {
  112. msyslog(LOG_ERR,"SHM SetSecurityDescriptorDacl (unit %d): %m",unit);
  113. return 0;
  114. }
  115. sa.nLength=sizeof (SECURITY_ATTRIBUTES);
  116. sa.lpSecurityDescriptor=&sd;
  117. sa.bInheritHandle=0;
  118. psec=&sa;
  119. }
  120. shmid=CreateFileMapping ((HANDLE)0xffffffff, psec, PAGE_READWRITE,
  121. 0, sizeof (struct shmTime),buf);
  122. if (!shmid) { /*error*/
  123. char buf[1000];
  124. FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
  125. 0, GetLastError (), 0, buf, sizeof (buf), 0);
  126. msyslog(LOG_ERR,"SHM CreateFileMapping (unit %d): %s",unit,buf);
  127. return 0;
  128. }
  129. else {
  130. struct shmTime *p=(struct shmTime *) MapViewOfFile (shmid,
  131. FILE_MAP_WRITE, 0, 0, sizeof (struct shmTime));
  132. if (p==0) { /*error*/
  133. char buf[1000];
  134. FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
  135. 0, GetLastError (), 0, buf, sizeof (buf), 0);
  136. msyslog(LOG_ERR,"SHM MapViewOfFile (unit %d): %s",unit,buf);
  137. return 0;
  138. }
  139. return p;
  140. }
  141. #endif
  142. }
  143. /*
  144. * shm_start - attach to shared memory
  145. */
  146. static int
  147. shm_start(
  148. int unit,
  149. struct peer *peer
  150. )
  151. {
  152. struct refclockproc *pp;
  153. pp = peer->procptr;
  154. pp->io.clock_recv = noentry;
  155. pp->io.srcclock = (caddr_t)peer;
  156. pp->io.datalen = 0;
  157. pp->io.fd = -1;
  158. pp->unitptr = (caddr_t)getShmTime(unit);
  159. /*
  160. * Initialize miscellaneous peer variables
  161. */
  162. memcpy((char *)&pp->refid, REFID, 4);
  163. if (pp->unitptr!=0) {
  164. ((struct shmTime*)pp->unitptr)->precision=PRECISION;
  165. peer->precision = ((struct shmTime*)pp->unitptr)->precision;
  166. ((struct shmTime*)pp->unitptr)->valid=0;
  167. ((struct shmTime*)pp->unitptr)->nsamples=NSAMPLES;
  168. pp->clockdesc = DESCRIPTION;
  169. return (1);
  170. }
  171. else {
  172. return 0;
  173. }
  174. }
  175. /*
  176. * shm_shutdown - shut down the clock
  177. */
  178. static void
  179. shm_shutdown(
  180. int unit,
  181. struct peer *peer
  182. )
  183. {
  184. register struct shmTime *up;
  185. struct refclockproc *pp;
  186. pp = peer->procptr;
  187. up = (struct shmTime *)pp->unitptr;
  188. #ifndef SYS_WINNT
  189. /* HMS: shmdt()wants char* or const void * */
  190. (void) shmdt (up);
  191. #else
  192. UnmapViewOfFile (up);
  193. #endif
  194. }
  195. /*
  196. * shm_poll - called by the transmit procedure
  197. */
  198. static void
  199. shm_poll(
  200. int unit,
  201. struct peer *peer
  202. )
  203. {
  204. register struct shmTime *up;
  205. struct refclockproc *pp;
  206. /*
  207. * This is the main routine. It snatches the time from the shm
  208. * board and tacks on a local timestamp.
  209. */
  210. pp = peer->procptr;
  211. up = (struct shmTime*)pp->unitptr;
  212. if (up==0) { /* try to map again - this may succeed if meanwhile some-
  213. body has ipcrm'ed the old (unaccessible) shared mem
  214. segment */
  215. pp->unitptr = (caddr_t)getShmTime(unit);
  216. up = (struct shmTime*)pp->unitptr;
  217. }
  218. if (up==0) {
  219. refclock_report(peer, CEVNT_FAULT);
  220. return;
  221. }
  222. if (up->valid) {
  223. struct timeval tvr;
  224. struct timeval tvt;
  225. struct tm *t;
  226. int ok=1;
  227. tvr.tv_sec = 0;
  228. tvr.tv_usec = 0;
  229. tvt.tv_sec = 0;
  230. tvt.tv_usec = 0;
  231. switch (up->mode) {
  232. case 0: {
  233. tvr.tv_sec=up->receiveTimeStampSec;
  234. tvr.tv_usec=up->receiveTimeStampUSec;
  235. tvt.tv_sec=up->clockTimeStampSec;
  236. tvt.tv_usec=up->clockTimeStampUSec;
  237. }
  238. break;
  239. case 1: {
  240. int cnt=up->count;
  241. tvr.tv_sec=up->receiveTimeStampSec;
  242. tvr.tv_usec=up->receiveTimeStampUSec;
  243. tvt.tv_sec=up->clockTimeStampSec;
  244. tvt.tv_usec=up->clockTimeStampUSec;
  245. ok=(cnt==up->count);
  246. }
  247. break;
  248. default:
  249. msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",up->mode);
  250. }
  251. up->valid=0;
  252. if (ok) {
  253. time_t help; /* XXX NetBSD has incompatible tv_sec */
  254. TVTOTS(&tvr,&pp->lastrec);
  255. pp->lastrec.l_ui += JAN_1970;
  256. /* pp->lasttime = current_time; */
  257. pp->polls++;
  258. help = tvt.tv_sec;
  259. t = gmtime (&help);
  260. pp->day=t->tm_yday+1;
  261. pp->hour=t->tm_hour;
  262. pp->minute=t->tm_min;
  263. pp->second=t->tm_sec;
  264. pp->nsec=tvt.tv_usec * 1000;
  265. peer->precision=up->precision;
  266. pp->leap=up->leap;
  267. }
  268. else {
  269. refclock_report(peer, CEVNT_FAULT);
  270. msyslog (LOG_NOTICE, "SHM: access clash in shared memory");
  271. return;
  272. }
  273. }
  274. else {
  275. refclock_report(peer, CEVNT_TIMEOUT);
  276. /*
  277. msyslog (LOG_NOTICE, "SHM: no new value found in shared memory");
  278. */
  279. return;
  280. }
  281. if (!refclock_process(pp)) {
  282. refclock_report(peer, CEVNT_BADTIME);
  283. return;
  284. }
  285. pp->lastref = pp->lastrec;
  286. refclock_receive(peer);
  287. }
  288. #else
  289. int refclock_shm_bs;
  290. #endif /* REFCLOCK */