]>
Commit | Line | Data |
---|---|---|
75330fdf ML |
1 | /* |
2 | chronyd/chronyc - Programs for keeping computer clocks accurate. | |
3 | ||
4 | ********************************************************************** | |
f7e08d0c | 5 | * Copyright (C) Miroslav Lichvar 2009 |
75330fdf ML |
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., | |
8e23110a | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
75330fdf ML |
19 | * |
20 | ********************************************************************** | |
21 | ||
22 | ======================================================================= | |
23 | ||
24 | SHM refclock driver. | |
25 | ||
26 | */ | |
27 | ||
da2c8d90 ML |
28 | #include "config.h" |
29 | ||
6ca73bf6 ML |
30 | #include "sysincl.h" |
31 | ||
75330fdf ML |
32 | #include "refclock.h" |
33 | #include "logging.h" | |
34 | #include "util.h" | |
35 | ||
75330fdf ML |
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 | */ | |
bbbb3633 | 47 | volatile int count; |
75330fdf ML |
48 | time_t clockTimeStampSec; |
49 | int clockTimeStampUSec; | |
50 | time_t receiveTimeStampSec; | |
51 | int receiveTimeStampUSec; | |
52 | int leap; | |
53 | int precision; | |
54 | int nsamples; | |
bbbb3633 ML |
55 | volatile int valid; |
56 | int clockTimeStampNSec; | |
57 | int receiveTimeStampNSec; | |
58 | int dummy[8]; | |
75330fdf ML |
59 | }; |
60 | ||
61 | static int shm_initialise(RCL_Instance instance) { | |
a78031ce | 62 | const char *options[] = {"perm", NULL}; |
f261251a ML |
63 | int id, param, perm; |
64 | char *s; | |
75330fdf ML |
65 | struct shmTime *shm; |
66 | ||
a78031ce ML |
67 | RCL_CheckDriverOptions(instance, options); |
68 | ||
67c0f1c0 | 69 | param = atoi(RCL_GetDriverParameter(instance)); |
f261251a | 70 | s = RCL_GetDriverOption(instance, "perm"); |
a123a12f | 71 | perm = s ? strtol(s, NULL, 8) & 0777 : 0600; |
75330fdf | 72 | |
f261251a | 73 | id = shmget(SHMKEY + param, sizeof (struct shmTime), IPC_CREAT | perm); |
75330fdf | 74 | if (id == -1) { |
eea343b9 | 75 | LOG_FATAL("shmget() failed : %s", strerror(errno)); |
75330fdf ML |
76 | return 0; |
77 | } | |
78 | ||
79 | shm = (struct shmTime *)shmat(id, 0, 0); | |
80 | if ((long)shm == -1) { | |
eea343b9 | 81 | LOG_FATAL("shmat() failed : %s", strerror(errno)); |
75330fdf ML |
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 | { | |
d0dfa1de | 96 | struct timespec receive_ts, clock_ts; |
75330fdf ML |
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) { | |
f282856c | 106 | DEBUG_LOG("SHM sample ignored mode=%d count=%d valid=%d", |
c00d93a8 | 107 | t.mode, t.count, t.valid); |
75330fdf ML |
108 | return 0; |
109 | } | |
110 | ||
111 | shm->valid = 0; | |
112 | ||
d0dfa1de ML |
113 | receive_ts.tv_sec = t.receiveTimeStampSec; |
114 | clock_ts.tv_sec = t.clockTimeStampSec; | |
75330fdf | 115 | |
bbbb3633 | 116 | if (t.clockTimeStampNSec / 1000 == t.clockTimeStampUSec && |
d0dfa1de ML |
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); | |
cfe706f0 | 127 | offset = UTI_DiffTimespecsToDouble(&clock_ts, &receive_ts); |
bbbb3633 | 128 | |
d0dfa1de | 129 | return RCL_AddSample(instance, &receive_ts, offset, t.leap); |
75330fdf ML |
130 | } |
131 | ||
132 | RefclockDriver RCL_SHM_driver = { | |
133 | shm_initialise, | |
134 | shm_finalise, | |
135 | shm_poll | |
136 | }; |