]> git.ipfire.org Git - thirdparty/chrony.git/blob - refclock_shm.c
examples: harden systemd services
[thirdparty/chrony.git] / refclock_shm.c
1 /*
2 chronyd/chronyc - Programs for keeping computer clocks accurate.
3
4 **********************************************************************
5 * Copyright (C) Miroslav Lichvar 2009
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 **********************************************************************
21
22 =======================================================================
23
24 SHM refclock driver.
25
26 */
27
28 #include "config.h"
29
30 #include "sysincl.h"
31
32 #include "refclock.h"
33 #include "logging.h"
34 #include "util.h"
35
36 #define SHMKEY 0x4e545030
37
38 struct shmTime {
39 int mode; /* 0 - if valid set
40 * use values,
41 * clear valid
42 * 1 - if valid set
43 * if count before and after read of values is equal,
44 * use values
45 * clear valid
46 */
47 volatile int count;
48 time_t clockTimeStampSec;
49 int clockTimeStampUSec;
50 time_t receiveTimeStampSec;
51 int receiveTimeStampUSec;
52 int leap;
53 int precision;
54 int nsamples;
55 volatile int valid;
56 int clockTimeStampNSec;
57 int receiveTimeStampNSec;
58 int dummy[8];
59 };
60
61 static int shm_initialise(RCL_Instance instance) {
62 const char *options[] = {"perm", NULL};
63 int id, param, perm;
64 char *s;
65 struct shmTime *shm;
66
67 RCL_CheckDriverOptions(instance, options);
68
69 param = atoi(RCL_GetDriverParameter(instance));
70 s = RCL_GetDriverOption(instance, "perm");
71 perm = s ? strtol(s, NULL, 8) & 0777 : 0600;
72
73 id = shmget(SHMKEY + param, sizeof (struct shmTime), IPC_CREAT | perm);
74 if (id == -1) {
75 LOG_FATAL("shmget() failed : %s", strerror(errno));
76 return 0;
77 }
78
79 shm = (struct shmTime *)shmat(id, 0, 0);
80 if ((long)shm == -1) {
81 LOG_FATAL("shmat() failed : %s", strerror(errno));
82 return 0;
83 }
84
85 RCL_SetDriverData(instance, shm);
86 return 1;
87 }
88
89 static void shm_finalise(RCL_Instance instance)
90 {
91 shmdt(RCL_GetDriverData(instance));
92 }
93
94 static int shm_poll(RCL_Instance instance)
95 {
96 struct timespec receive_ts, clock_ts;
97 struct shmTime t, *shm;
98 double offset;
99
100 shm = (struct shmTime *)RCL_GetDriverData(instance);
101
102 t = *shm;
103
104 if ((t.mode == 1 && t.count != shm->count) ||
105 !(t.mode == 0 || t.mode == 1) || !t.valid) {
106 DEBUG_LOG("SHM sample ignored mode=%d count=%d valid=%d",
107 t.mode, t.count, t.valid);
108 return 0;
109 }
110
111 shm->valid = 0;
112
113 receive_ts.tv_sec = t.receiveTimeStampSec;
114 clock_ts.tv_sec = t.clockTimeStampSec;
115
116 if (t.clockTimeStampNSec / 1000 == t.clockTimeStampUSec &&
117 t.receiveTimeStampNSec / 1000 == t.receiveTimeStampUSec) {
118 receive_ts.tv_nsec = t.receiveTimeStampNSec;
119 clock_ts.tv_nsec = t.clockTimeStampNSec;
120 } else {
121 receive_ts.tv_nsec = 1000 * t.receiveTimeStampUSec;
122 clock_ts.tv_nsec = 1000 * t.clockTimeStampUSec;
123 }
124
125 UTI_NormaliseTimespec(&clock_ts);
126 UTI_NormaliseTimespec(&receive_ts);
127 offset = UTI_DiffTimespecsToDouble(&clock_ts, &receive_ts);
128
129 return RCL_AddSample(instance, &receive_ts, offset, t.leap);
130 }
131
132 RefclockDriver RCL_SHM_driver = {
133 shm_initialise,
134 shm_finalise,
135 shm_poll
136 };