1 /*
2 * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24 /*
25
26 Timer - struct timespec conversion runtimes and easy to use functions to
27 measure elapsed time.
28
29 */
30
31 #ifndef TST_TIMER
32 #define TST_TIMER
33
34 #include <sys/time.h>
35 #include <time.h>
36
tst_timespec_to_ns(struct timespec t)37 static inline long long tst_timespec_to_ns(struct timespec t)
38 {
39 return t.tv_sec * 1000000000 + t.tv_nsec;
40 }
41
42 /*
43 * Converts timespec to microseconds.
44 */
tst_timespec_to_us(struct timespec t)45 static inline long long tst_timespec_to_us(struct timespec t)
46 {
47 return t.tv_sec * 1000000 + (t.tv_nsec + 500) / 1000;
48 }
49
50 /*
51 * Converts timespec to milliseconds.
52 */
tst_timespec_to_ms(struct timespec t)53 static inline long long tst_timespec_to_ms(struct timespec t)
54 {
55 return t.tv_sec * 1000 + (t.tv_nsec + 500000) / 1000000;
56 }
57
58 /*
59 * Converts timeval to microseconds.
60 */
tst_timeval_to_us(struct timeval t)61 static inline long long tst_timeval_to_us(struct timeval t)
62 {
63 return t.tv_sec * 1000000 + t.tv_usec;
64 }
65
66 /*
67 * Converts timeval to milliseconds.
68 */
tst_timeval_to_ms(struct timeval t)69 static inline long long tst_timeval_to_ms(struct timeval t)
70 {
71 return t.tv_sec * 1000 + (t.tv_usec + 500) / 1000;
72 }
73
74 /*
75 * Converts ms to struct timeval
76 */
tst_ms_to_timeval(long long ms)77 static inline struct timeval tst_ms_to_timeval(long long ms)
78 {
79 struct timeval ret;
80
81 ret.tv_sec = ms / 1000;
82 ret.tv_usec = (ms % 1000) * 1000;
83
84 return ret;
85 }
86
87 /*
88 * Converts us to struct timeval
89 */
tst_us_to_timeval(long long us)90 static inline struct timeval tst_us_to_timeval(long long us)
91 {
92 struct timeval ret;
93
94 ret.tv_sec = us / 1000000;
95 ret.tv_usec = us % 1000000;
96
97 return ret;
98 }
99
100 /*
101 * Converts ms to struct timespec
102 */
tst_ms_to_timespec(long long ms)103 static inline struct timespec tst_ms_to_timespec(long long ms)
104 {
105 struct timespec ret;
106
107 ret.tv_sec = ms / 1000;
108 ret.tv_nsec = (ms % 1000) * 1000000;
109
110 return ret;
111 }
112
113 /*
114 * Converts us to struct timespec
115 */
tst_us_to_timespec(long long us)116 static inline struct timespec tst_us_to_timespec(long long us)
117 {
118 struct timespec ret;
119
120 ret.tv_sec = us / 1000000;
121 ret.tv_nsec = (us % 1000000) * 1000;
122
123 return ret;
124 }
125
126 /*
127 * Comparsions
128 */
tst_timespec_lt(struct timespec t1,struct timespec t2)129 static inline int tst_timespec_lt(struct timespec t1, struct timespec t2)
130 {
131 if (t1.tv_sec == t2.tv_sec)
132 return t1.tv_nsec < t2.tv_nsec;
133
134 return t1.tv_sec < t2.tv_sec;
135 }
136
137 /*
138 * Adds us microseconds to t.
139 */
tst_timespec_add_us(struct timespec t,long long us)140 static inline struct timespec tst_timespec_add_us(struct timespec t,
141 long long us)
142 {
143 t.tv_sec += us / 1000000;
144 t.tv_nsec += (us % 1000000) * 1000;
145
146 if (t.tv_nsec >= 1000000000) {
147 t.tv_sec++;
148 t.tv_nsec -= 1000000000;
149 }
150
151 return t;
152 }
153
154 /*
155 * Adds two timespec structures.
156 */
tst_timespec_add(struct timespec t1,struct timespec t2)157 static inline struct timespec tst_timespec_add(struct timespec t1,
158 struct timespec t2)
159 {
160 struct timespec res;
161
162 res.tv_sec = t1.tv_sec + t2.tv_sec;
163 res.tv_nsec = t1.tv_nsec + t2.tv_nsec;
164
165 if (res.tv_nsec >= 1000000000) {
166 res.tv_sec++;
167 res.tv_nsec -= 1000000000;
168 }
169
170 return res;
171 }
172
173 /*
174 * Subtracts us microseconds from t.
175 */
tst_timespec_sub_us(struct timespec t,long long us)176 static inline struct timespec tst_timespec_sub_us(struct timespec t,
177 long long us)
178 {
179 t.tv_sec -= us / 1000000;
180 t.tv_nsec -= (us % 1000000) * 1000;
181
182 if (t.tv_nsec < 0) {
183 t.tv_sec--;
184 t.tv_nsec += 1000000000;
185 }
186
187 return t;
188 }
189
190 /*
191 * Returns difference between two timespec structures.
192 */
tst_timespec_diff(struct timespec t1,struct timespec t2)193 static inline struct timespec tst_timespec_diff(struct timespec t1,
194 struct timespec t2)
195 {
196 struct timespec res;
197
198 res.tv_sec = t1.tv_sec - t2.tv_sec;
199
200 if (t1.tv_nsec < t2.tv_nsec) {
201 res.tv_sec--;
202 res.tv_nsec = 1000000000 - (t2.tv_nsec - t1.tv_nsec);
203 } else {
204 res.tv_nsec = t1.tv_nsec - t2.tv_nsec;
205 }
206
207 return res;
208 }
209
tst_timespec_diff_ns(struct timespec t1,struct timespec t2)210 static inline long long tst_timespec_diff_ns(struct timespec t1,
211 struct timespec t2)
212 {
213 return t1.tv_nsec - t2.tv_nsec + 1000000000LL * (t1.tv_sec - t2.tv_sec);
214 }
215
tst_timespec_diff_us(struct timespec t1,struct timespec t2)216 static inline long long tst_timespec_diff_us(struct timespec t1,
217 struct timespec t2)
218 {
219 return tst_timespec_to_us(tst_timespec_diff(t1, t2));
220 }
221
tst_timespec_diff_ms(struct timespec t1,struct timespec t2)222 static inline long long tst_timespec_diff_ms(struct timespec t1,
223 struct timespec t2)
224 {
225 return tst_timespec_to_ms(tst_timespec_diff(t1, t2));
226 }
227
228 /*
229 * Returns difference between two timeval structures.
230 */
tst_timeval_diff(struct timeval t1,struct timeval t2)231 static inline struct timeval tst_timeval_diff(struct timeval t1,
232 struct timeval t2)
233 {
234 struct timeval res;
235
236 res.tv_sec = t1.tv_sec - t2.tv_sec;
237
238 if (t1.tv_usec < t2.tv_usec) {
239 res.tv_sec--;
240 res.tv_usec = 1000000 - (t2.tv_usec - t1.tv_usec);
241 } else {
242 res.tv_usec = t1.tv_usec - t2.tv_usec;
243 }
244
245 return res;
246 }
247
tst_timeval_diff_us(struct timeval t1,struct timeval t2)248 static inline long long tst_timeval_diff_us(struct timeval t1,
249 struct timeval t2)
250 {
251 return tst_timeval_to_us(tst_timeval_diff(t1, t2));
252 }
253
tst_timeval_diff_ms(struct timeval t1,struct timeval t2)254 static inline long long tst_timeval_diff_ms(struct timeval t1,
255 struct timeval t2)
256 {
257 return tst_timeval_to_ms(tst_timeval_diff(t1, t2));
258 }
259
260 /*
261 * Returns absolute value of difference between two timespec structures.
262 */
tst_timespec_abs_diff(struct timespec t1,struct timespec t2)263 static inline struct timespec tst_timespec_abs_diff(struct timespec t1,
264 struct timespec t2)
265 {
266 if (tst_timespec_lt(t1, t2))
267 return tst_timespec_diff(t2, t1);
268 else
269 return tst_timespec_diff(t1, t2);
270 }
271
tst_timespec_abs_diff_us(struct timespec t1,struct timespec t2)272 static inline long long tst_timespec_abs_diff_us(struct timespec t1,
273 struct timespec t2)
274 {
275 return tst_timespec_to_us(tst_timespec_abs_diff(t1, t2));
276 }
277
tst_timespec_abs_diff_ms(struct timespec t1,struct timespec t2)278 static inline long long tst_timespec_abs_diff_ms(struct timespec t1,
279 struct timespec t2)
280 {
281 return tst_timespec_to_ms(tst_timespec_abs_diff(t1, t2));
282 }
283
284 /*
285 * Exits the test with TCONF if particular timer is not supported. This is
286 * intended to be used in test setup. There is no cleanup callback parameter as
287 * you are expected to call it before initializing any resources that has to be
288 * cleaned up later.
289 *
290 * @clk_id: Posix clock to use.
291 */
292 void tst_timer_check(clockid_t clk_id);
293
294 /*
295 * Marks a start time for given clock type.
296 *
297 * @clk_id: Posix clock to use.
298 */
299 void tst_timer_start(clockid_t clk_id);
300
301 /*
302 * Returns true if timer started by tst_timer_start() has been running for
303 * longer than ms seconds.
304 *
305 * @ms: Time interval in milliseconds.
306 */
307 int tst_timer_expired_ms(long long ms);
308
309 /*
310 * Marks timer end time.
311 */
312 void tst_timer_stop(void);
313
314 /*
315 * Retuns elapsed time in struct timespec.
316 */
317 struct timespec tst_timer_elapsed(void);
318
319 /*
320 * Returns elapsed time in milliseconds.
321 */
tst_timer_elapsed_ms(void)322 static inline long long tst_timer_elapsed_ms(void)
323 {
324 return tst_timespec_to_ms(tst_timer_elapsed());
325 }
326
327 /*
328 * Returns elapsed time in microseconds.
329 */
tst_timer_elapsed_us(void)330 static inline long long tst_timer_elapsed_us(void)
331 {
332 return tst_timespec_to_us(tst_timer_elapsed());
333 }
334
335 /*
336 * Returns a string containing given clock type name
337 */
338 const char *tst_clock_name(clockid_t);
339
340 #endif /* TST_TIMER */
341