2 * Copyright © 2014 - 2015 Collabora, Ltd.
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 * Helpers to deal with timespec structures.
40 #define NSEC_PER_SEC 1000000000
45 * \param r[out] result: a + b
46 * \param a[in] operand
47 * \param b[in] operand
50 timespec_add(struct timespec
*r
,
51 const struct timespec
*a
, const struct timespec
*b
)
53 r
->tv_sec
= a
->tv_sec
+ b
->tv_sec
;
54 r
->tv_nsec
= a
->tv_nsec
+ b
->tv_nsec
;
55 if (r
->tv_nsec
> NSEC_PER_SEC
) {
57 r
->tv_nsec
-= NSEC_PER_SEC
;
64 * \param r[out] result: a - b
65 * \param a[in] operand
66 * \param b[in] operand
69 timespec_sub(struct timespec
*r
,
70 const struct timespec
*a
, const struct timespec
*b
)
72 r
->tv_sec
= a
->tv_sec
- b
->tv_sec
;
73 r
->tv_nsec
= a
->tv_nsec
- b
->tv_nsec
;
76 r
->tv_nsec
+= NSEC_PER_SEC
;
81 * Add a nanosecond value to a timespec
83 * \param r[out] result: a + b
84 * \param a[in] base operand as timespec
85 * \param b[in] operand in nanoseconds
88 timespec_add_nsec(struct timespec
*r
, const struct timespec
*a
, uint64_t b
)
90 r
->tv_sec
= a
->tv_sec
+ (b
/ NSEC_PER_SEC
);
91 r
->tv_nsec
= a
->tv_nsec
+ (b
% NSEC_PER_SEC
);
93 if (r
->tv_nsec
>= NSEC_PER_SEC
) {
95 r
->tv_nsec
-= NSEC_PER_SEC
;
96 } else if (r
->tv_nsec
< 0) {
98 r
->tv_nsec
+= NSEC_PER_SEC
;
103 * Add a millisecond value to a timespec
105 * \param r[out] result: a + b
106 * \param a[in] base operand as timespec
107 * \param b[in] operand in milliseconds
110 timespec_add_msec(struct timespec
*r
, const struct timespec
*a
, uint64_t b
)
112 timespec_add_nsec(r
, a
, b
* 1000000);
116 * Convert timespec to nanoseconds
119 * \return nanoseconds
121 static inline uint64_t
122 timespec_to_nsec(const struct timespec
*a
)
124 return (uint64_t)a
->tv_sec
* NSEC_PER_SEC
+ a
->tv_nsec
;
128 * Subtract timespecs and return result in nanoseconds
130 * \param a[in] operand
131 * \param b[in] operand
132 * \return to_nanoseconds(a - b)
134 static inline uint64_t
135 timespec_sub_to_nsec(const struct timespec
*a
, const struct timespec
*b
)
138 timespec_sub(&r
, a
, b
);
139 return timespec_to_nsec(&r
);
143 * Convert timespec to milliseconds
146 * \return milliseconds
148 * Rounding to integer milliseconds happens always down (floor()).
150 static inline uint64_t
151 timespec_to_msec(const struct timespec
*a
)
153 return (uint64_t)a
->tv_sec
* 1000 + a
->tv_nsec
/ 1000000;
157 * Subtract timespecs and return result in milliseconds
159 * \param a[in] operand
160 * \param b[in] operand
161 * \return to_milliseconds(a - b)
163 static inline uint64_t
164 timespec_sub_to_msec(const struct timespec
*a
, const struct timespec
*b
)
166 return timespec_sub_to_nsec(a
, b
) / 1000000;
170 * Convert timespec to microseconds
173 * \return microseconds
175 * Rounding to integer microseconds happens always down (floor()).
177 static inline uint64_t
178 timespec_to_usec(const struct timespec
*a
)
180 return (uint64_t)a
->tv_sec
* 1000000 + a
->tv_nsec
/ 1000;
184 * Convert timespec to protocol data
187 * \param tv_sec_hi[out] the high bytes of the seconds part
188 * \param tv_sec_lo[out] the low bytes of the seconds part
189 * \param tv_nsec[out] the nanoseconds part
191 * The input timespec must be normalized (the nanoseconds part should
192 * be less than 1 second) and non-negative.
195 timespec_to_proto(const struct timespec
*a
, uint32_t *tv_sec_hi
,
196 uint32_t *tv_sec_lo
, uint32_t *tv_nsec
)
198 assert(a
->tv_sec
>= 0);
199 assert(a
->tv_nsec
>= 0 && a
->tv_nsec
< NSEC_PER_SEC
);
201 uint64_t sec64
= a
->tv_sec
;
203 *tv_sec_hi
= sec64
>> 32;
204 *tv_sec_lo
= sec64
& 0xffffffff;
205 *tv_nsec
= a
->tv_nsec
;
209 * Convert nanoseconds to timespec
212 * \param b nanoseconds
215 timespec_from_nsec(struct timespec
*a
, uint64_t b
)
217 a
->tv_sec
= b
/ NSEC_PER_SEC
;
218 a
->tv_nsec
= b
% NSEC_PER_SEC
;
222 * Convert microseconds to timespec
225 * \param b microseconds
228 timespec_from_usec(struct timespec
*a
, uint64_t b
)
230 timespec_from_nsec(a
, b
* 1000);
234 * Convert milliseconds to timespec
237 * \param b milliseconds
240 timespec_from_msec(struct timespec
*a
, uint64_t b
)
242 timespec_from_nsec(a
, b
* 1000000);
246 * Convert protocol data to timespec
248 * \param a[out] timespec
249 * \param tv_sec_hi the high bytes of seconds part
250 * \param tv_sec_lo the low bytes of seconds part
251 * \param tv_nsec the nanoseconds part
254 timespec_from_proto(struct timespec
*a
, uint32_t tv_sec_hi
,
255 uint32_t tv_sec_lo
, uint32_t tv_nsec
)
257 a
->tv_sec
= ((uint64_t)tv_sec_hi
<< 32) + tv_sec_lo
;
258 a
->tv_nsec
= tv_nsec
;
262 * Check if a timespec is zero
265 * \return whether the timespec is zero
268 timespec_is_zero(const struct timespec
*a
)
270 return a
->tv_sec
== 0 && a
->tv_nsec
== 0;
274 * Check if two timespecs are equal
276 * \param a[in] timespec to check
277 * \param b[in] timespec to check
278 * \return whether timespecs a and b are equal
281 timespec_eq(const struct timespec
*a
, const struct timespec
*b
)
283 return a
->tv_sec
== b
->tv_sec
&&
284 a
->tv_nsec
== b
->tv_nsec
;
288 * Convert milli-Hertz to nanoseconds
290 * \param mhz frequency in mHz, not zero
291 * \return period in nanoseconds
293 static inline uint64_t
294 millihz_to_nsec(uint32_t mhz
)
297 return 1000000000000LL / mhz
;
301 * Checks whether a timespec value is after another
303 * \param a[in] timespec to compare
304 * \param b[in] timespec to compare
305 * \return whether a is after b
308 timespec_after(const struct timespec
*a
, const struct timespec
*b
)
310 return (a
->tv_sec
== b
->tv_sec
) ?
311 (a
->tv_nsec
> b
->tv_nsec
) :
312 (a
->tv_sec
> b
->tv_sec
);
316 * Checks whether a timespec value is after the current time
318 * \param clock_domain[in] clock in which to do the comparison
319 * \param deadline[in] timespec to compare
320 * \return whether deadline is after the current time
323 timespec_passed(clockid_t clock_domain
, const struct timespec
*deadline
)
325 struct timespec current_time
;
326 clock_gettime(clock_domain
, ¤t_time
);
327 return timespec_after(¤t_time
, deadline
);
330 #endif /* TIMESPEC_H */