Xenomai  3.0-rc3
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  const char *name; /* __ref FIXME */
62 };
63 
64 #define zero_time ((struct timespec){ .tv_sec = 0, .tv_nsec = 0 })
65 
66 #ifdef __cplusplus
67 extern "C" {
68 #endif
69 
70 void clockobj_set_date(struct clockobj *clkobj, ticks_t ticks);
71 
72 void clockobj_get_date(struct clockobj *clkobj, ticks_t *pticks);
73 
74 ticks_t clockobj_get_time(struct clockobj *clkobj);
75 
76 void clockobj_get_distance(struct clockobj *clkobj,
77  const struct itimerspec *itm,
78  struct timespec *delta);
79 
80 ticks_t clockobj_get_tsc(void);
81 
82 void clockobj_caltime_to_timeout(struct clockobj *clkobj, const struct tm *tm,
83  unsigned long rticks, struct timespec *ts);
84 
85 void clockobj_caltime_to_ticks(struct clockobj *clkobj, const struct tm *tm,
86  unsigned long rticks, ticks_t *pticks);
87 
88 void clockobj_ticks_to_caltime(struct clockobj *clkobj,
89  ticks_t ticks,
90  struct tm *tm,
91  unsigned long *rticks);
92 
93 void clockobj_convert_clocks(struct clockobj *clkobj,
94  const struct timespec *in,
95  clockid_t clk_id,
96  struct timespec *out);
97 
98 int clockobj_set_resolution(struct clockobj *clkobj,
99  unsigned int resolution_ns);
100 
101 int clockobj_init(struct clockobj *clkobj,
102  const char *name, unsigned int resolution_ns);
103 
104 int clockobj_destroy(struct clockobj *clkobj);
105 
106 #ifdef __cplusplus
107 }
108 #endif
109 
110 #ifdef CONFIG_XENO_COBALT
111 
112 #include <cobalt/ticks.h>
113 
114 /*
115  * The Cobalt core exclusively deals with aperiodic timings, so a
116  * Cobalt _tick_ is actually a _TSC_ unit. In contrast, Copperplate
117  * deals with _TSC_ units and periodic _ticks_ which duration depend
118  * on the clock resolution. Therefore, Cobalt ticks are strictly
119  * equivalent to Copperplate TSC units, and Copperplate ticks are
120  * periods of the reference clockobj which Cobalt does not know about.
121  */
122 static inline sticks_t clockobj_ns_to_tsc(sticks_t ns)
123 {
124  return cobalt_ns_to_ticks(ns);
125 }
126 
127 static inline sticks_t clockobj_tsc_to_ns(sticks_t tsc)
128 {
129  return cobalt_ticks_to_ns(tsc);
130 }
131 
132 static inline
133 void clockobj_ns_to_timespec(ticks_t ns, struct timespec *ts)
134 {
135  unsigned long rem;
136 
137  ts->tv_sec = cobalt_divrem_billion(ns, &rem);
138  ts->tv_nsec = rem;
139 }
140 
141 #else /* CONFIG_XENO_MERCURY */
142 
143 static inline sticks_t clockobj_ns_to_tsc(sticks_t ns)
144 {
145  return ns;
146 }
147 
148 static inline sticks_t clockobj_tsc_to_ns(sticks_t tsc)
149 {
150  return tsc;
151 }
152 
153 static inline
154 void clockobj_ns_to_timespec(ticks_t ns, struct timespec *ts)
155 {
156  ts->tv_sec = ns / 1000000000ULL;
157  ts->tv_nsec = ns - (ts->tv_sec * 1000000000ULL);
158 }
159 
160 #endif /* CONFIG_XENO_MERCURY */
161 
162 #ifdef CONFIG_XENO_LORES_CLOCK_DISABLED
163 
164 static inline
165 void __clockobj_ticks_to_timeout(struct clockobj *clkobj,
166  clockid_t clk_id,
167  ticks_t ticks, struct timespec *ts)
168 {
169  struct timespec now, delta;
170 
171  __RT(clock_gettime(clk_id, &now));
172  clockobj_ns_to_timespec(ticks, &delta);
173  timespec_add(ts, &now, &delta);
174 }
175 
176 static inline
177 void __clockobj_ticks_to_timespec(struct clockobj *clkobj,
178  ticks_t ticks, struct timespec *ts)
179 {
180  clockobj_ns_to_timespec(ticks, ts);
181 }
182 
183 static inline
184 void clockobj_ticks_to_timespec(struct clockobj *clkobj,
185  ticks_t ticks, struct timespec *ts)
186 {
187  __clockobj_ticks_to_timespec(clkobj, ticks, ts);
188 }
189 
190 static inline
191 unsigned int clockobj_get_resolution(struct clockobj *clkobj)
192 {
193  return 1;
194 }
195 
196 static inline
197 unsigned int clockobj_get_frequency(struct clockobj *clkobj)
198 {
199  return 1000000000;
200 }
201 
202 static inline sticks_t clockobj_ns_to_ticks(struct clockobj *clkobj,
203  sticks_t ns)
204 {
205  return ns;
206 }
207 
208 static inline sticks_t clockobj_ticks_to_ns(struct clockobj *clkobj,
209  sticks_t ticks)
210 {
211  return ticks;
212 }
213 
214 #else /* !CONFIG_XENO_LORES_CLOCK_DISABLED */
215 
216 void __clockobj_ticks_to_timeout(struct clockobj *clkobj, clockid_t clk_id,
217  ticks_t ticks, struct timespec *ts);
218 
219 void __clockobj_ticks_to_timespec(struct clockobj *clkobj,
220  ticks_t ticks, struct timespec *ts);
221 
222 static inline
223 void clockobj_ticks_to_timespec(struct clockobj *clkobj,
224  ticks_t ticks, struct timespec *ts)
225 {
226  __clockobj_ticks_to_timespec(clkobj, ticks, ts);
227 }
228 
229 static inline
230 unsigned int clockobj_get_resolution(struct clockobj *clkobj)
231 {
232  return clkobj->resolution;
233 }
234 
235 static inline
236 unsigned int clockobj_get_frequency(struct clockobj *clkobj)
237 {
238  return clkobj->frequency;
239 }
240 
241 sticks_t clockobj_ns_to_ticks(struct clockobj *clkobj,
242  sticks_t ns);
243 
244 static inline sticks_t clockobj_ticks_to_ns(struct clockobj *clkobj,
245  sticks_t ticks)
246 {
247  return ticks * clkobj->resolution;
248 }
249 
250 #endif /* !CONFIG_XENO_LORES_CLOCK_DISABLED */
251 
252 static inline
253 void clockobj_ticks_to_timeout(struct clockobj *clkobj,
254  ticks_t ticks, struct timespec *ts)
255 {
256  __clockobj_ticks_to_timeout(clkobj, CLOCK_COPPERPLATE, ticks, ts);
257 }
258 
259 #endif /* _COPPERPLATE_CLOCKOBJ_H */
int clock_gettime(clockid_t clock_id, struct timespec *tp)
Read the specified clock.
Definition: clock.c:179