Xenomai  3.0.5
clockobj.h
1 /*
2  * Copyright (C) 2008 Philippe Gerum <rpm@xenomai.org>.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13 
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18 
19 #ifndef _COPPERPLATE_CLOCKOBJ_H
20 #define _COPPERPLATE_CLOCKOBJ_H
21 
22 #include <pthread.h>
23 #include <xeno_config.h>
24 #include <boilerplate/time.h>
25 #include <boilerplate/list.h>
26 #include <boilerplate/lock.h>
27 #include <boilerplate/limits.h>
28 #include <copperplate/debug.h>
29 
30 /*
31  * We normally define the Copperplate clock as a monotonic,
32  * non-adjustable one, unless the threading library has restrictions
33  * to support this over Mercury.
34  *
35  * In the normal case, this means that ongoing delays and timeouts
36  * won't be affected when the host system date is changed. In the
37  * restricted case by contrast, ongoing delays and timeouts may be
38  * impacted by changes to the host system date.
39  *
40  * The implementation maintains a per-clock epoch value, so that
41  * different emulators can have different (virtual) system dates.
42  */
43 #ifndef CONFIG_XENO_COPPERPLATE_CLOCK_RESTRICTED
44 #ifdef CONFIG_XENO_RAW_CLOCK_ENABLED
45 #define CLOCK_COPPERPLATE CLOCK_MONOTONIC_RAW
46 #else
47 #define CLOCK_COPPERPLATE CLOCK_MONOTONIC
48 #endif
49 #else /* CONFIG_XENO_COPPERPLATE_CLOCK_RESTRICTED */
50 #define CLOCK_COPPERPLATE CLOCK_REALTIME
51 #endif /* CONFIG_XENO_COPPERPLATE_CLOCK_RESTRICTED */
52 
53 struct clockobj {
54  pthread_mutex_t lock;
55  struct timespec epoch;
56  struct timespec offset;
57 #ifndef CONFIG_XENO_LORES_CLOCK_DISABLED
58  unsigned int resolution;
59  unsigned int frequency;
60 #endif
61 };
62 
63 #define zero_time ((struct timespec){ .tv_sec = 0, .tv_nsec = 0 })
64 
65 #ifdef __cplusplus
66 extern "C" {
67 #endif
68 
69 void clockobj_set_date(struct clockobj *clkobj, ticks_t ticks);
70 
71 void clockobj_get_date(struct clockobj *clkobj, ticks_t *pticks);
72 
73 ticks_t clockobj_get_time(struct clockobj *clkobj);
74 
75 void clockobj_get_distance(struct clockobj *clkobj,
76  const struct itimerspec *itm,
77  struct timespec *delta);
78 
79 ticks_t clockobj_get_tsc(void);
80 
81 void clockobj_caltime_to_timeout(struct clockobj *clkobj, const struct tm *tm,
82  unsigned long rticks, struct timespec *ts);
83 
84 void clockobj_caltime_to_ticks(struct clockobj *clkobj, const struct tm *tm,
85  unsigned long rticks, ticks_t *pticks);
86 
87 void clockobj_ticks_to_caltime(struct clockobj *clkobj,
88  ticks_t ticks,
89  struct tm *tm,
90  unsigned long *rticks);
91 
92 void clockobj_convert_clocks(struct clockobj *clkobj,
93  const struct timespec *in,
94  clockid_t clk_id,
95  struct timespec *out);
96 
97 int clockobj_set_resolution(struct clockobj *clkobj,
98  unsigned int resolution_ns);
99 
100 int clockobj_init(struct clockobj *clkobj,
101  unsigned int resolution_ns);
102 
103 int clockobj_destroy(struct clockobj *clkobj);
104 
105 #ifndef CONFIG_XENO_LORES_CLOCK_DISABLED
106 
107 void __clockobj_ticks_to_timeout(struct clockobj *clkobj, clockid_t clk_id,
108  ticks_t ticks, struct timespec *ts);
109 
110 void __clockobj_ticks_to_timespec(struct clockobj *clkobj,
111  ticks_t ticks, struct timespec *ts);
112 #endif /* !CONFIG_XENO_LORES_CLOCK_DISABLED */
113 
114 #ifdef __cplusplus
115 }
116 #endif
117 
118 #ifdef CONFIG_XENO_COBALT
119 
120 #include <cobalt/ticks.h>
121 
122 /*
123  * The Cobalt core exclusively deals with aperiodic timings, so a
124  * Cobalt _tick_ is actually a _TSC_ unit. In contrast, Copperplate
125  * deals with _TSC_ units and periodic _ticks_ which duration depend
126  * on the clock resolution. Therefore, Cobalt ticks are strictly
127  * equivalent to Copperplate TSC units, and Copperplate ticks are
128  * periods of the reference clockobj which Cobalt does not know about.
129  */
130 static inline sticks_t clockobj_ns_to_tsc(sticks_t ns)
131 {
132  return cobalt_ns_to_ticks(ns);
133 }
134 
135 static inline sticks_t clockobj_tsc_to_ns(sticks_t tsc)
136 {
137  return cobalt_ticks_to_ns(tsc);
138 }
139 
140 static inline
141 void clockobj_ns_to_timespec(ticks_t ns, struct timespec *ts)
142 {
143  unsigned long rem;
144 
145  ts->tv_sec = cobalt_divrem_billion(ns, &rem);
146  ts->tv_nsec = rem;
147 }
148 
149 #else /* CONFIG_XENO_MERCURY */
150 
151 static inline sticks_t clockobj_ns_to_tsc(sticks_t ns)
152 {
153  return ns;
154 }
155 
156 static inline sticks_t clockobj_tsc_to_ns(sticks_t tsc)
157 {
158  return tsc;
159 }
160 
161 static inline
162 void clockobj_ns_to_timespec(ticks_t ns, struct timespec *ts)
163 {
164  ts->tv_sec = ns / 1000000000ULL;
165  ts->tv_nsec = ns - (ts->tv_sec * 1000000000ULL);
166 }
167 
168 #endif /* CONFIG_XENO_MERCURY */
169 
170 #ifdef CONFIG_XENO_LORES_CLOCK_DISABLED
171 
172 static inline
173 void __clockobj_ticks_to_timeout(struct clockobj *clkobj,
174  clockid_t clk_id,
175  ticks_t ticks, struct timespec *ts)
176 {
177  struct timespec now, delta;
178 
179  __RT(clock_gettime(clk_id, &now));
180  clockobj_ns_to_timespec(ticks, &delta);
181  timespec_add(ts, &now, &delta);
182 }
183 
184 static inline
185 void __clockobj_ticks_to_timespec(struct clockobj *clkobj,
186  ticks_t ticks, struct timespec *ts)
187 {
188  clockobj_ns_to_timespec(ticks, ts);
189 }
190 
191 static inline
192 void clockobj_ticks_to_timespec(struct clockobj *clkobj,
193  ticks_t ticks, struct timespec *ts)
194 {
195  __clockobj_ticks_to_timespec(clkobj, ticks, ts);
196 }
197 
198 static inline
199 unsigned int clockobj_get_resolution(struct clockobj *clkobj)
200 {
201  return 1;
202 }
203 
204 static inline
205 unsigned int clockobj_get_frequency(struct clockobj *clkobj)
206 {
207  return 1000000000;
208 }
209 
210 static inline sticks_t clockobj_ns_to_ticks(struct clockobj *clkobj,
211  sticks_t ns)
212 {
213  return ns;
214 }
215 
216 static inline sticks_t clockobj_ticks_to_ns(struct clockobj *clkobj,
217  sticks_t ticks)
218 {
219  return ticks;
220 }
221 
222 #else /* !CONFIG_XENO_LORES_CLOCK_DISABLED */
223 
224 static inline
225 void clockobj_ticks_to_timespec(struct clockobj *clkobj,
226  ticks_t ticks, struct timespec *ts)
227 {
228  __clockobj_ticks_to_timespec(clkobj, ticks, ts);
229 }
230 
231 static inline
232 unsigned int clockobj_get_resolution(struct clockobj *clkobj)
233 {
234  return clkobj->resolution;
235 }
236 
237 static inline
238 unsigned int clockobj_get_frequency(struct clockobj *clkobj)
239 {
240  return clkobj->frequency;
241 }
242 
243 sticks_t clockobj_ns_to_ticks(struct clockobj *clkobj,
244  sticks_t ns);
245 
246 static inline sticks_t clockobj_ticks_to_ns(struct clockobj *clkobj,
247  sticks_t ticks)
248 {
249  return ticks * clkobj->resolution;
250 }
251 
252 #endif /* !CONFIG_XENO_LORES_CLOCK_DISABLED */
253 
254 static inline
255 void clockobj_ticks_to_timeout(struct clockobj *clkobj,
256  ticks_t ticks, struct timespec *ts)
257 {
258  __clockobj_ticks_to_timeout(clkobj, CLOCK_COPPERPLATE, ticks, ts);
259 }
260 
261 #endif /* _COPPERPLATE_CLOCKOBJ_H */
int clock_gettime(clockid_t clock_id, struct timespec *tp)
Read the specified clock.
Definition: clock.c:181