Xenomai  3.1
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 
29 /*
30  * The Copperplate clock shall be monotonic unless the threading
31  * library has restrictions to support this over Mercury.
32  *
33  * In the normal case, this means that ongoing delays and timeouts
34  * won't be affected when the host system date is changed. In the
35  * restricted case by contrast, ongoing delays and timeouts may be
36  * impacted by changes to the host system date.
37  *
38  * The implementation maintains a per-clock epoch value, so that
39  * different emulators can have different (virtual) system dates.
40  */
41 #ifdef CONFIG_XENO_COPPERPLATE_CLOCK_RESTRICTED
42 #define CLOCK_COPPERPLATE CLOCK_REALTIME
43 #else
44 #define CLOCK_COPPERPLATE CLOCK_MONOTONIC
45 #endif
46 
47 struct clockobj {
48  pthread_mutex_t lock;
49  struct timespec epoch;
50  struct timespec offset;
51 #ifndef CONFIG_XENO_LORES_CLOCK_DISABLED
52  unsigned int resolution;
53  unsigned int frequency;
54 #endif
55 };
56 
57 #define zero_time ((struct timespec){ .tv_sec = 0, .tv_nsec = 0 })
58 
59 #ifdef __cplusplus
60 extern "C" {
61 #endif
62 
63 void clockobj_set_date(struct clockobj *clkobj, ticks_t ticks);
64 
65 void clockobj_get_date(struct clockobj *clkobj, ticks_t *pticks);
66 
67 ticks_t clockobj_get_time(struct clockobj *clkobj);
68 
69 void clockobj_get_distance(struct clockobj *clkobj,
70  const struct itimerspec *itm,
71  struct timespec *delta);
72 
73 ticks_t clockobj_get_tsc(void);
74 
75 void clockobj_caltime_to_timeout(struct clockobj *clkobj, const struct tm *tm,
76  unsigned long rticks, struct timespec *ts);
77 
78 void clockobj_caltime_to_ticks(struct clockobj *clkobj, const struct tm *tm,
79  unsigned long rticks, ticks_t *pticks);
80 
81 void clockobj_ticks_to_caltime(struct clockobj *clkobj,
82  ticks_t ticks,
83  struct tm *tm,
84  unsigned long *rticks);
85 
86 void clockobj_convert_clocks(struct clockobj *clkobj,
87  const struct timespec *in,
88  clockid_t clk_id,
89  struct timespec *out);
90 
91 int clockobj_set_resolution(struct clockobj *clkobj,
92  unsigned int resolution_ns);
93 
94 int clockobj_init(struct clockobj *clkobj,
95  unsigned int resolution_ns);
96 
97 int clockobj_destroy(struct clockobj *clkobj);
98 
99 #ifndef CONFIG_XENO_LORES_CLOCK_DISABLED
100 
101 void __clockobj_ticks_to_timeout(struct clockobj *clkobj, clockid_t clk_id,
102  ticks_t ticks, struct timespec *ts);
103 
104 void __clockobj_ticks_to_timespec(struct clockobj *clkobj,
105  ticks_t ticks, struct timespec *ts);
106 #endif /* !CONFIG_XENO_LORES_CLOCK_DISABLED */
107 
108 #ifdef __cplusplus
109 }
110 #endif
111 
112 #ifdef CONFIG_XENO_COBALT
113 
114 #include <cobalt/ticks.h>
115 
116 /*
117  * The Cobalt core exclusively deals with aperiodic timings, so a
118  * Cobalt _tick_ is actually a _TSC_ unit. In contrast, Copperplate
119  * deals with _TSC_ units and periodic _ticks_ which duration depend
120  * on the clock resolution. Therefore, Cobalt ticks are strictly
121  * equivalent to Copperplate TSC units, and Copperplate ticks are
122  * periods of the reference clockobj which Cobalt does not know about.
123  */
124 static inline sticks_t clockobj_ns_to_tsc(sticks_t ns)
125 {
126  return cobalt_ns_to_ticks(ns);
127 }
128 
129 static inline sticks_t clockobj_tsc_to_ns(sticks_t tsc)
130 {
131  return cobalt_ticks_to_ns(tsc);
132 }
133 
134 static inline
135 void clockobj_ns_to_timespec(ticks_t ns, struct timespec *ts)
136 {
137  unsigned long rem;
138 
139  ts->tv_sec = (time_t)cobalt_divrem_billion(ns, &rem);
140  ts->tv_nsec = rem;
141 }
142 
143 #else /* CONFIG_XENO_MERCURY */
144 
145 static inline sticks_t clockobj_ns_to_tsc(sticks_t ns)
146 {
147  return ns;
148 }
149 
150 static inline sticks_t clockobj_tsc_to_ns(sticks_t tsc)
151 {
152  return tsc;
153 }
154 
155 static inline
156 void clockobj_ns_to_timespec(ticks_t ns, struct timespec *ts)
157 {
158  ts->tv_sec = ns / 1000000000ULL;
159  ts->tv_nsec = ns - (ts->tv_sec * 1000000000ULL);
160 }
161 
162 #endif /* CONFIG_XENO_MERCURY */
163 
164 #ifdef CONFIG_XENO_LORES_CLOCK_DISABLED
165 
166 static inline
167 void __clockobj_ticks_to_timeout(struct clockobj *clkobj,
168  clockid_t clk_id,
169  ticks_t ticks, struct timespec *ts)
170 {
171  struct timespec now, delta;
172 
173  __RT(clock_gettime(clk_id, &now));
174  clockobj_ns_to_timespec(ticks, &delta);
175  timespec_add(ts, &now, &delta);
176 }
177 
178 static inline
179 void __clockobj_ticks_to_timespec(struct clockobj *clkobj,
180  ticks_t ticks, struct timespec *ts)
181 {
182  clockobj_ns_to_timespec(ticks, ts);
183 }
184 
185 static inline
186 void clockobj_ticks_to_timespec(struct clockobj *clkobj,
187  ticks_t ticks, struct timespec *ts)
188 {
189  __clockobj_ticks_to_timespec(clkobj, ticks, ts);
190 }
191 
192 static inline
193 unsigned int clockobj_get_resolution(struct clockobj *clkobj)
194 {
195  return 1;
196 }
197 
198 static inline
199 unsigned int clockobj_get_frequency(struct clockobj *clkobj)
200 {
201  return 1000000000;
202 }
203 
204 static inline sticks_t clockobj_ns_to_ticks(struct clockobj *clkobj,
205  sticks_t ns)
206 {
207  return ns;
208 }
209 
210 static inline sticks_t clockobj_ticks_to_ns(struct clockobj *clkobj,
211  sticks_t ticks)
212 {
213  return ticks;
214 }
215 
216 #else /* !CONFIG_XENO_LORES_CLOCK_DISABLED */
217 
218 static inline
219 void clockobj_ticks_to_timespec(struct clockobj *clkobj,
220  ticks_t ticks, struct timespec *ts)
221 {
222  __clockobj_ticks_to_timespec(clkobj, ticks, ts);
223 }
224 
225 static inline
226 unsigned int clockobj_get_resolution(struct clockobj *clkobj)
227 {
228  return clkobj->resolution;
229 }
230 
231 static inline
232 unsigned int clockobj_get_frequency(struct clockobj *clkobj)
233 {
234  return clkobj->frequency;
235 }
236 
237 sticks_t clockobj_ns_to_ticks(struct clockobj *clkobj,
238  sticks_t ns);
239 
240 static inline sticks_t clockobj_ticks_to_ns(struct clockobj *clkobj,
241  sticks_t ticks)
242 {
243  return ticks * clkobj->resolution;
244 }
245 
246 #endif /* !CONFIG_XENO_LORES_CLOCK_DISABLED */
247 
248 static inline
249 void clockobj_ticks_to_timeout(struct clockobj *clkobj,
250  ticks_t ticks, struct timespec *ts)
251 {
252  __clockobj_ticks_to_timeout(clkobj, CLOCK_COPPERPLATE, ticks, ts);
253 }
254 
255 #endif /* _COPPERPLATE_CLOCKOBJ_H */
int clock_gettime(clockid_t clock_id, struct timespec *tp)
Read the specified clock.
Definition: clock.c:183