• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright (C) 2015-2020 Cyril Hrubis <chrubis@suse.cz>
3  */
4 
5  /*
6 
7    Timer - struct timespec conversion runtimes and easy to use functions to
8            measure elapsed time.
9 
10   */
11 
12 #ifndef TST_TIMER
13 #define TST_TIMER
14 
15 #include <linux/time_types.h>
16 #include <linux/types.h>
17 #include <sched.h>
18 #include <sys/time.h>
19 #include <mqueue.h>
20 #include <time.h>
21 #include "tst_test.h"
22 #include "lapi/common_timers.h"
23 #include "lapi/posix_types.h"
24 #include "lapi/syscalls.h"
25 
26 /*
27  * Converts timeval to microseconds.
28  */
tst_timeval_to_us(struct timeval t)29 static inline long long tst_timeval_to_us(struct timeval t)
30 {
31 	return ((long long)t.tv_sec) * 1000000 + t.tv_usec;
32 }
33 
34 /*
35  * Converts timeval to milliseconds.
36  */
tst_timeval_to_ms(struct timeval t)37 static inline long long tst_timeval_to_ms(struct timeval t)
38 {
39 	return ((long long)t.tv_sec) * 1000 + (t.tv_usec + 500) / 1000;
40 }
41 
42 /*
43  * Converts milliseconds to struct timeval
44  */
tst_ms_to_timeval(long long ms)45 static inline struct timeval tst_ms_to_timeval(long long ms)
46 {
47 	struct timeval ret;
48 
49 	ret.tv_sec = ms / 1000;
50 	ret.tv_usec = (ms % 1000) * 1000;
51 
52 	return ret;
53 }
54 
55 /*
56  * Converts microseconds to struct timeval
57  */
tst_us_to_timeval(long long us)58 static inline struct timeval tst_us_to_timeval(long long us)
59 {
60 	struct timeval ret;
61 
62 	ret.tv_sec = us / 1000000;
63 	ret.tv_usec = us % 1000000;
64 
65 	return ret;
66 }
67 
68 /*
69  * Returns difference between two timeval structures.
70  */
tst_timeval_diff(struct timeval t1,struct timeval t2)71 static inline struct timeval tst_timeval_diff(struct timeval t1,
72                                               struct timeval t2)
73 {
74 	struct timeval res;
75 
76 	res.tv_sec = t1.tv_sec - t2.tv_sec;
77 
78 	if (t1.tv_usec < t2.tv_usec) {
79 		res.tv_sec--;
80 		res.tv_usec = 1000000 - (t2.tv_usec - t1.tv_usec);
81 	} else {
82 		res.tv_usec = t1.tv_usec - t2.tv_usec;
83 	}
84 
85 	return res;
86 }
87 
tst_timeval_diff_us(struct timeval t1,struct timeval t2)88 static inline long long tst_timeval_diff_us(struct timeval t1,
89                                             struct timeval t2)
90 {
91 	return tst_timeval_to_us(tst_timeval_diff(t1, t2));
92 }
93 
tst_timeval_diff_ms(struct timeval t1,struct timeval t2)94 static inline long long tst_timeval_diff_ms(struct timeval t1,
95                                             struct timeval t2)
96 {
97 	return tst_timeval_to_ms(tst_timeval_diff(t1, t2));
98 }
99 
100 typedef __kernel_long_t	__kernel_old_time_t;
101 
102 #ifndef HAVE_STRUCT___KERNEL_OLD_TIMEVAL
103 struct __kernel_old_timeval {
104 	__kernel_old_time_t	tv_sec;		/* seconds */
105 	__kernel_suseconds_t	tv_usec;	/* microseconds */
106 };
107 #endif
108 
109 #ifndef HAVE_STRUCT___KERNEL_OLD_TIMESPEC
110 struct __kernel_old_timespec {
111 	__kernel_old_time_t	tv_sec;		/* seconds */
112 	__kernel_old_time_t	tv_nsec;	/* nanoseconds */
113 };
114 #endif
115 
116 typedef long long __kernel_time64_t;
117 
118 #ifndef HAVE_STRUCT___KERNEL_TIMESPEC
119 struct __kernel_timespec {
120 	__kernel_time64_t       tv_sec;                 /* seconds */
121 	long long               tv_nsec;                /* nanoseconds */
122 };
123 #endif
124 
125 struct __kernel_old_itimerspec {
126 	struct __kernel_old_timespec it_interval;    /* timer period */
127 	struct __kernel_old_timespec it_value;       /* timer expiration */
128 };
129 
130 #ifndef HAVE_STRUCT___KERNEL_ITIMERSPEC
131 struct __kernel_itimerspec {
132 	struct __kernel_timespec it_interval;    /* timer period */
133 	struct __kernel_timespec it_value;       /* timer expiration */
134 };
135 #endif
136 
137 enum tst_ts_type {
138 	TST_LIBC_TIMESPEC,
139 	TST_KERN_OLD_TIMESPEC,
140 	TST_KERN_TIMESPEC
141 };
142 
143 struct tst_ts {
144 	enum tst_ts_type type;
145 	union ts {
146 		struct timespec libc_ts;
147 		struct __kernel_old_timespec kern_old_ts;
148 		struct __kernel_timespec kern_ts;
149 	} ts;
150 };
151 
152 struct tst_its {
153 	enum tst_ts_type type;
154 	union {
155 		struct __kernel_old_itimerspec kern_old_its;
156 		struct __kernel_itimerspec kern_its;
157 	} ts;
158 };
159 
tst_ts_get(struct tst_ts * t)160 static inline void *tst_ts_get(struct tst_ts *t)
161 {
162 	if (!t)
163 		return NULL;
164 
165 	switch (t->type) {
166 	case TST_LIBC_TIMESPEC:
167 		return &t->ts.libc_ts;
168 	case TST_KERN_OLD_TIMESPEC:
169 		return &t->ts.kern_old_ts;
170 	case TST_KERN_TIMESPEC:
171 		return &t->ts.kern_ts;
172 	default:
173 		tst_brk(TBROK, "Invalid type: %d", t->type);
174 		return NULL;
175 	}
176 }
177 
tst_its_get(struct tst_its * t)178 static inline void *tst_its_get(struct tst_its *t)
179 {
180 	if (!t)
181 		return NULL;
182 
183 	switch (t->type) {
184 	case TST_KERN_OLD_TIMESPEC:
185 		return &t->ts.kern_old_its;
186 	case TST_KERN_TIMESPEC:
187 		return &t->ts.kern_its;
188 	default:
189 		tst_brk(TBROK, "Invalid type: %d", t->type);
190 		return NULL;
191 	}
192 }
193 
libc_clock_getres(clockid_t clk_id,void * ts)194 static inline int libc_clock_getres(clockid_t clk_id, void *ts)
195 {
196 	return clock_getres(clk_id, ts);
197 }
198 
sys_clock_getres(clockid_t clk_id,void * ts)199 static inline int sys_clock_getres(clockid_t clk_id, void *ts)
200 {
201 	return tst_syscall(__NR_clock_getres, clk_id, ts);
202 }
203 
sys_clock_getres64(clockid_t clk_id,void * ts)204 static inline int sys_clock_getres64(clockid_t clk_id, void *ts)
205 {
206 	return tst_syscall(__NR_clock_getres_time64, clk_id, ts);
207 }
208 
libc_clock_gettime(clockid_t clk_id,void * ts)209 static inline int libc_clock_gettime(clockid_t clk_id, void *ts)
210 {
211 	return clock_gettime(clk_id, ts);
212 }
213 
sys_clock_gettime(clockid_t clk_id,void * ts)214 static inline int sys_clock_gettime(clockid_t clk_id, void *ts)
215 {
216 	return tst_syscall(__NR_clock_gettime, clk_id, ts);
217 }
218 
sys_clock_gettime64(clockid_t clk_id,void * ts)219 static inline int sys_clock_gettime64(clockid_t clk_id, void *ts)
220 {
221 	return tst_syscall(__NR_clock_gettime64, clk_id, ts);
222 }
223 
libc_clock_settime(clockid_t clk_id,void * ts)224 static inline int libc_clock_settime(clockid_t clk_id, void *ts)
225 {
226 	return clock_settime(clk_id, ts);
227 }
228 
sys_clock_settime(clockid_t clk_id,void * ts)229 static inline int sys_clock_settime(clockid_t clk_id, void *ts)
230 {
231 	return tst_syscall(__NR_clock_settime, clk_id, ts);
232 }
233 
sys_clock_settime64(clockid_t clk_id,void * ts)234 static inline int sys_clock_settime64(clockid_t clk_id, void *ts)
235 {
236 	return tst_syscall(__NR_clock_settime64, clk_id, ts);
237 }
238 
libc_clock_nanosleep(clockid_t clk_id,int flags,void * request,void * remain)239 static inline int libc_clock_nanosleep(clockid_t clk_id, int flags,
240 				       void *request, void *remain)
241 {
242 	return clock_nanosleep(clk_id, flags, request, remain);
243 }
244 
sys_clock_nanosleep(clockid_t clk_id,int flags,void * request,void * remain)245 static inline int sys_clock_nanosleep(clockid_t clk_id, int flags,
246 				      void *request, void *remain)
247 {
248 	return tst_syscall(__NR_clock_nanosleep, clk_id, flags,
249 			   request, remain);
250 }
251 
sys_clock_nanosleep64(clockid_t clk_id,int flags,void * request,void * remain)252 static inline int sys_clock_nanosleep64(clockid_t clk_id, int flags,
253 				        void *request, void *remain)
254 {
255 	return tst_syscall(__NR_clock_nanosleep_time64, clk_id, flags,
256 			   request, remain);
257 }
258 
sys_futex(int * uaddr,int futex_op,int val,void * to,int * uaddr2,int val3)259 static inline int sys_futex(int *uaddr, int futex_op, int val, void *to,
260 			    int *uaddr2, int val3)
261 {
262 	return tst_syscall(__NR_futex, uaddr, futex_op, val, to, uaddr2, val3);
263 }
264 
sys_futex_time64(int * uaddr,int futex_op,int val,void * to,int * uaddr2,int val3)265 static inline int sys_futex_time64(int *uaddr, int futex_op, int val, void *to,
266 				   int *uaddr2, int val3)
267 {
268 	return tst_syscall(__NR_futex_time64, uaddr, futex_op, val, to, uaddr2, val3);
269 }
270 
libc_mq_timedsend(mqd_t mqdes,const char * msg_ptr,size_t msg_len,unsigned int msg_prio,void * abs_timeout)271 static inline int libc_mq_timedsend(mqd_t mqdes, const char *msg_ptr,
272 		size_t msg_len, unsigned int msg_prio, void *abs_timeout)
273 {
274 	return mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, abs_timeout);
275 }
276 
sys_mq_timedsend(mqd_t mqdes,const char * msg_ptr,size_t msg_len,unsigned int msg_prio,void * abs_timeout)277 static inline int sys_mq_timedsend(mqd_t mqdes, const char *msg_ptr,
278 		size_t msg_len, unsigned int msg_prio, void *abs_timeout)
279 {
280 	return tst_syscall(__NR_mq_timedsend, mqdes, msg_ptr, msg_len, msg_prio,
281 			   abs_timeout);
282 }
283 
sys_mq_timedsend64(mqd_t mqdes,const char * msg_ptr,size_t msg_len,unsigned int msg_prio,void * abs_timeout)284 static inline int sys_mq_timedsend64(mqd_t mqdes, const char *msg_ptr,
285 		size_t msg_len, unsigned int msg_prio, void *abs_timeout)
286 {
287 	return tst_syscall(__NR_mq_timedsend_time64, mqdes, msg_ptr, msg_len,
288 			   msg_prio, abs_timeout);
289 }
290 
libc_mq_timedreceive(mqd_t mqdes,char * msg_ptr,size_t msg_len,unsigned int * msg_prio,void * abs_timeout)291 static inline ssize_t libc_mq_timedreceive(mqd_t mqdes, char *msg_ptr,
292 		size_t msg_len, unsigned int *msg_prio, void *abs_timeout)
293 {
294 	return mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, abs_timeout);
295 }
296 
sys_mq_timedreceive(mqd_t mqdes,char * msg_ptr,size_t msg_len,unsigned int * msg_prio,void * abs_timeout)297 static inline ssize_t sys_mq_timedreceive(mqd_t mqdes, char *msg_ptr,
298 		size_t msg_len, unsigned int *msg_prio, void *abs_timeout)
299 {
300 	return tst_syscall(__NR_mq_timedreceive, mqdes, msg_ptr, msg_len,
301 			   msg_prio, abs_timeout);
302 }
303 
sys_mq_timedreceive64(mqd_t mqdes,char * msg_ptr,size_t msg_len,unsigned int * msg_prio,void * abs_timeout)304 static inline ssize_t sys_mq_timedreceive64(mqd_t mqdes, char *msg_ptr,
305 		size_t msg_len, unsigned int *msg_prio, void *abs_timeout)
306 {
307 	return tst_syscall(__NR_mq_timedreceive_time64, mqdes, msg_ptr, msg_len,
308 			   msg_prio, abs_timeout);
309 }
310 
libc_sched_rr_get_interval(pid_t pid,void * ts)311 static inline int libc_sched_rr_get_interval(pid_t pid, void *ts)
312 {
313 	return sched_rr_get_interval(pid, ts);
314 }
315 
sys_sched_rr_get_interval(pid_t pid,void * ts)316 static inline int sys_sched_rr_get_interval(pid_t pid, void *ts)
317 {
318 	return tst_syscall(__NR_sched_rr_get_interval, pid, ts);
319 }
320 
sys_sched_rr_get_interval64(pid_t pid,void * ts)321 static inline int sys_sched_rr_get_interval64(pid_t pid, void *ts)
322 {
323 	return tst_syscall(__NR_sched_rr_get_interval_time64, pid, ts);
324 }
325 
sys_timer_gettime(kernel_timer_t timerid,void * its)326 static inline int sys_timer_gettime(kernel_timer_t timerid, void *its)
327 {
328 	return tst_syscall(__NR_timer_gettime, timerid, its);
329 }
330 
sys_timer_gettime64(kernel_timer_t timerid,void * its)331 static inline int sys_timer_gettime64(kernel_timer_t timerid, void *its)
332 {
333 	return tst_syscall(__NR_timer_gettime64, timerid, its);
334 }
335 
sys_timer_settime(kernel_timer_t timerid,int flags,void * its,void * old_its)336 static inline int sys_timer_settime(kernel_timer_t timerid, int flags, void *its,
337 				    void *old_its)
338 {
339 	return tst_syscall(__NR_timer_settime, timerid, flags, its, old_its);
340 }
341 
sys_timer_settime64(kernel_timer_t timerid,int flags,void * its,void * old_its)342 static inline int sys_timer_settime64(kernel_timer_t timerid, int flags, void *its,
343 				      void *old_its)
344 {
345 	return tst_syscall(__NR_timer_settime64, timerid, flags, its, old_its);
346 }
347 
sys_timerfd_gettime(int fd,void * its)348 static inline int sys_timerfd_gettime(int fd, void *its)
349 {
350 	return tst_syscall(__NR_timerfd_gettime, fd, its);
351 }
352 
sys_timerfd_gettime64(int fd,void * its)353 static inline int sys_timerfd_gettime64(int fd, void *its)
354 {
355 	return tst_syscall(__NR_timerfd_gettime64, fd, its);
356 }
357 
sys_timerfd_settime(int fd,int flags,void * its,void * old_its)358 static inline int sys_timerfd_settime(int fd, int flags, void *its,
359 				      void *old_its)
360 {
361 	return tst_syscall(__NR_timerfd_settime, fd, flags, its, old_its);
362 }
363 
sys_timerfd_settime64(int fd,int flags,void * its,void * old_its)364 static inline int sys_timerfd_settime64(int fd, int flags, void *its,
365 				      void *old_its)
366 {
367 	return tst_syscall(__NR_timerfd_settime64, fd, flags, its, old_its);
368 }
369 
370 /*
371  * Returns tst_ts seconds.
372  */
tst_ts_get_sec(struct tst_ts ts)373 static inline long long tst_ts_get_sec(struct tst_ts ts)
374 {
375 	switch (ts.type) {
376 	case TST_LIBC_TIMESPEC:
377 		return ts.ts.libc_ts.tv_sec;
378 	case TST_KERN_OLD_TIMESPEC:
379 		return ts.ts.kern_old_ts.tv_sec;
380 	case TST_KERN_TIMESPEC:
381 		return ts.ts.kern_ts.tv_sec;
382 	default:
383 		tst_brk(TBROK, "Invalid type: %d", ts.type);
384 		return -1;
385 	}
386 }
387 
388 /*
389  * Returns tst_ts nanoseconds.
390  */
tst_ts_get_nsec(struct tst_ts ts)391 static inline long long tst_ts_get_nsec(struct tst_ts ts)
392 {
393 	switch (ts.type) {
394 	case TST_LIBC_TIMESPEC:
395 		return ts.ts.libc_ts.tv_nsec;
396 	case TST_KERN_OLD_TIMESPEC:
397 		return ts.ts.kern_old_ts.tv_nsec;
398 	case TST_KERN_TIMESPEC:
399 		return ts.ts.kern_ts.tv_nsec;
400 	default:
401 		tst_brk(TBROK, "Invalid type: %d", ts.type);
402 		return -1;
403 	}
404 }
405 
406 /*
407  * Sets tst_ts seconds.
408  */
tst_ts_set_sec(struct tst_ts * ts,long long sec)409 static inline void tst_ts_set_sec(struct tst_ts *ts, long long sec)
410 {
411 	switch (ts->type) {
412 	case TST_LIBC_TIMESPEC:
413 		ts->ts.libc_ts.tv_sec = sec;
414 	break;
415 	case TST_KERN_OLD_TIMESPEC:
416 		ts->ts.kern_old_ts.tv_sec = sec;
417 	break;
418 	case TST_KERN_TIMESPEC:
419 		ts->ts.kern_ts.tv_sec = sec;
420 	break;
421 	default:
422 		tst_brk(TBROK, "Invalid type: %d", ts->type);
423 	}
424 }
425 
426 /*
427  * Sets tst_ts nanoseconds.
428  */
tst_ts_set_nsec(struct tst_ts * ts,long long nsec)429 static inline void tst_ts_set_nsec(struct tst_ts *ts, long long nsec)
430 {
431 	switch (ts->type) {
432 	case TST_LIBC_TIMESPEC:
433 		ts->ts.libc_ts.tv_nsec = nsec;
434 	break;
435 	case TST_KERN_OLD_TIMESPEC:
436 		ts->ts.kern_old_ts.tv_nsec = nsec;
437 	break;
438 	case TST_KERN_TIMESPEC:
439 		ts->ts.kern_ts.tv_nsec = nsec;
440 	break;
441 	default:
442 		tst_brk(TBROK, "Invalid type: %d", ts->type);
443 	}
444 }
445 
446 /*
447  * Returns tst_its it_interval seconds.
448  */
tst_its_get_interval_sec(struct tst_its its)449 static inline long long tst_its_get_interval_sec(struct tst_its its)
450 {
451 	switch (its.type) {
452 	case TST_KERN_OLD_TIMESPEC:
453 		return its.ts.kern_old_its.it_interval.tv_sec;
454 	case TST_KERN_TIMESPEC:
455 		return its.ts.kern_its.it_interval.tv_sec;
456 	default:
457 		tst_brk(TBROK, "Invalid type: %d", its.type);
458 		return -1;
459 	}
460 }
461 
462 /*
463  * Returns tst_its it_interval nanoseconds.
464  */
tst_its_get_interval_nsec(struct tst_its its)465 static inline long long tst_its_get_interval_nsec(struct tst_its its)
466 {
467 	switch (its.type) {
468 	case TST_KERN_OLD_TIMESPEC:
469 		return its.ts.kern_old_its.it_interval.tv_nsec;
470 	case TST_KERN_TIMESPEC:
471 		return its.ts.kern_its.it_interval.tv_nsec;
472 	default:
473 		tst_brk(TBROK, "Invalid type: %d", its.type);
474 		return -1;
475 	}
476 }
477 
478 /*
479  * Sets tst_its it_interval seconds.
480  */
tst_its_set_interval_sec(struct tst_its * its,long long sec)481 static inline void tst_its_set_interval_sec(struct tst_its *its, long long sec)
482 {
483 	switch (its->type) {
484 	break;
485 	case TST_KERN_OLD_TIMESPEC:
486 		its->ts.kern_old_its.it_interval.tv_sec = sec;
487 	break;
488 	case TST_KERN_TIMESPEC:
489 		its->ts.kern_its.it_interval.tv_sec = sec;
490 	break;
491 	default:
492 		tst_brk(TBROK, "Invalid type: %d", its->type);
493 	}
494 }
495 
496 /*
497  * Sets tst_its it_interval nanoseconds.
498  */
tst_its_set_interval_nsec(struct tst_its * its,long long nsec)499 static inline void tst_its_set_interval_nsec(struct tst_its *its, long long nsec)
500 {
501 	switch (its->type) {
502 	break;
503 	case TST_KERN_OLD_TIMESPEC:
504 		its->ts.kern_old_its.it_interval.tv_nsec = nsec;
505 	break;
506 	case TST_KERN_TIMESPEC:
507 		its->ts.kern_its.it_interval.tv_nsec = nsec;
508 	break;
509 	default:
510 		tst_brk(TBROK, "Invalid type: %d", its->type);
511 	}
512 }
513 
514 /*
515  * Returns tst_its it_value seconds.
516  */
tst_its_get_value_sec(struct tst_its its)517 static inline long long tst_its_get_value_sec(struct tst_its its)
518 {
519 	switch (its.type) {
520 	case TST_KERN_OLD_TIMESPEC:
521 		return its.ts.kern_old_its.it_value.tv_sec;
522 	case TST_KERN_TIMESPEC:
523 		return its.ts.kern_its.it_value.tv_sec;
524 	default:
525 		tst_brk(TBROK, "Invalid type: %d", its.type);
526 		return -1;
527 	}
528 }
529 
530 /*
531  * Returns tst_its it_value nanoseconds.
532  */
tst_its_get_value_nsec(struct tst_its its)533 static inline long long tst_its_get_value_nsec(struct tst_its its)
534 {
535 	switch (its.type) {
536 	case TST_KERN_OLD_TIMESPEC:
537 		return its.ts.kern_old_its.it_value.tv_nsec;
538 	case TST_KERN_TIMESPEC:
539 		return its.ts.kern_its.it_value.tv_nsec;
540 	default:
541 		tst_brk(TBROK, "Invalid type: %d", its.type);
542 		return -1;
543 	}
544 }
545 
546 /*
547  * Sets tst_its it_value seconds.
548  */
tst_its_set_value_sec(struct tst_its * its,long long sec)549 static inline void tst_its_set_value_sec(struct tst_its *its, long long sec)
550 {
551 	switch (its->type) {
552 	break;
553 	case TST_KERN_OLD_TIMESPEC:
554 		its->ts.kern_old_its.it_value.tv_sec = sec;
555 	break;
556 	case TST_KERN_TIMESPEC:
557 		its->ts.kern_its.it_value.tv_sec = sec;
558 	break;
559 	default:
560 		tst_brk(TBROK, "Invalid type: %d", its->type);
561 	}
562 }
563 
564 /*
565  * Sets tst_its it_value nanoseconds.
566  */
tst_its_set_value_nsec(struct tst_its * its,long long nsec)567 static inline void tst_its_set_value_nsec(struct tst_its *its, long long nsec)
568 {
569 	switch (its->type) {
570 	break;
571 	case TST_KERN_OLD_TIMESPEC:
572 		its->ts.kern_old_its.it_value.tv_nsec = nsec;
573 	break;
574 	case TST_KERN_TIMESPEC:
575 		its->ts.kern_its.it_value.tv_nsec = nsec;
576 	break;
577 	default:
578 		tst_brk(TBROK, "Invalid type: %d", its->type);
579 	}
580 }
581 
582 /*
583  * Checks that timespec is valid, i.e. that the timestamp is not zero and that
584  * the nanoseconds are normalized i.e. in <0, 1s) interval.
585  *
586  *  0: On success, i.e. timespec updated correctly.
587  * -1: Error, timespec not updated.
588  * -2: Error, tv_nsec is corrupted.
589  */
tst_ts_valid(struct tst_ts * t)590 static inline int tst_ts_valid(struct tst_ts *t)
591 {
592 	long long nsec = tst_ts_get_nsec(*t);
593 
594 	if (nsec < 0 || nsec >= 1000000000)
595 		return -2;
596 
597 	if (tst_ts_get_sec(*t) == 0 && tst_ts_get_nsec(*t) == 0)
598 		return -1;
599 
600 	return 0;
601 }
602 
603 /*
604  * Converts timespec to tst_ts.
605  */
tst_ts_from_timespec(struct timespec ts)606 static inline struct tst_ts tst_ts_from_timespec(struct timespec ts)
607 {
608 	struct tst_ts t = {
609 		.type = TST_LIBC_TIMESPEC,
610 		.ts.libc_ts.tv_sec = ts.tv_sec,
611 		.ts.libc_ts.tv_nsec = ts.tv_nsec,
612 	};
613 
614 	return t;
615 }
616 
617 /*
618  * Converst tst_ts into timespec.
619  */
tst_ts_to_timespec(struct tst_ts t)620 static inline struct timespec tst_ts_to_timespec(struct tst_ts t)
621 {
622 	return t.ts.libc_ts;
623 }
624 
625 /*
626  * Converts tst_ts to nanoseconds.
627  */
tst_ts_to_ns(struct tst_ts t)628 static inline long long tst_ts_to_ns(struct tst_ts t)
629 {
630 	return tst_ts_get_sec(t) * 1000000000 + tst_ts_get_nsec(t);
631 }
632 
633 /*
634  * Converts tst_ts to microseconds and rounds the value.
635  */
tst_ts_to_us(struct tst_ts t)636 static inline long long tst_ts_to_us(struct tst_ts t)
637 {
638 	return tst_ts_get_sec(t) * 1000000 +
639 	       (tst_ts_get_nsec(t) + 500) / 1000;
640 }
641 
642 /*
643  * Converts timespec to microseconds and rounds the value.
644  */
tst_timespec_to_us(struct timespec ts)645 static inline long long tst_timespec_to_us(struct timespec ts)
646 {
647 	return tst_ts_to_us(tst_ts_from_timespec(ts));
648 }
649 
650 /*
651  * Converts tst_ts to milliseconds and rounds the value.
652  */
tst_ts_to_ms(struct tst_ts t)653 static inline long long tst_ts_to_ms(struct tst_ts t)
654 {
655 	return tst_ts_get_sec(t) * 1000 +
656 	       (tst_ts_get_nsec(t) + 500000) / 1000000;
657 }
658 
659 /*
660  * Converts timespec to milliseconds and rounds the value.
661  */
tst_timespec_to_ms(struct timespec ts)662 static inline long long tst_timespec_to_ms(struct timespec ts)
663 {
664 	return tst_ts_to_ms(tst_ts_from_timespec(ts));
665 }
666 
667 /*
668  * Converts nanoseconds to tst_ts
669  */
670 static inline struct tst_ts
tst_ts_from_ns(enum tst_ts_type type,long long ns)671 tst_ts_from_ns(enum tst_ts_type type, long long ns)
672 {
673 	struct tst_ts ret = {.type = type};
674 
675 	tst_ts_set_sec(&ret, ns / 1000000000);
676 	tst_ts_set_nsec(&ret, ns % 1000000000);
677 
678 	return ret;
679 }
680 
681 /*
682  * Converts microseconds to tst_ts
683  */
684 static inline struct tst_ts
tst_ts_from_us(enum tst_ts_type type,long long us)685 tst_ts_from_us(enum tst_ts_type type, long long us)
686 {
687 	struct tst_ts ret = {.type = type};
688 
689 	tst_ts_set_sec(&ret, us / 1000000);
690 	tst_ts_set_nsec(&ret, (us % 1000000) * 1000);
691 
692 	return ret;
693 }
694 
695 /*
696  * Converts microseconds to timespec
697  */
698 static inline struct timespec
tst_timespec_from_us(long long us)699 tst_timespec_from_us(long long us)
700 {
701 	return tst_ts_to_timespec(tst_ts_from_us(TST_LIBC_TIMESPEC, us));
702 }
703 
704 /*
705  * Converts miliseconds to tst_ts
706  */
707 static inline struct tst_ts
tst_ts_from_ms(enum tst_ts_type type,long long ms)708 tst_ts_from_ms(enum tst_ts_type type, long long ms)
709 {
710 	struct tst_ts ret = {.type = type};
711 
712 	tst_ts_set_sec(&ret, ms / 1000);
713 	tst_ts_set_nsec(&ret, (ms % 1000) * 1000000);
714 
715 	return ret;
716 }
717 
718 /*
719  * Converts miliseconds to timespec
720  */
721 static inline struct timespec
tst_timespec_from_ms(long long ms)722 tst_timespec_from_ms(long long ms)
723 {
724 	return tst_ts_to_timespec(tst_ts_from_ms(TST_LIBC_TIMESPEC, ms));
725 }
726 
727 /*
728  * Sets tst_its it_value from microseconds.
729  */
tst_its_set_interval_from_us(struct tst_its * its,long long usec)730 static inline void tst_its_set_interval_from_us(struct tst_its *its, long long usec)
731 {
732 	struct timespec tp = tst_timespec_from_us(usec);
733 
734 	tst_its_set_interval_sec(its, tp.tv_sec);
735 	tst_its_set_interval_nsec(its, tp.tv_nsec);
736 }
737 
738 /*
739  * Sets tst_its it_value from microseconds.
740  */
tst_its_set_value_from_us(struct tst_its * its,long long usec)741 static inline void tst_its_set_value_from_us(struct tst_its *its, long long usec)
742 {
743 	struct timespec tp = tst_timespec_from_us(usec);
744 
745 	tst_its_set_value_sec(its, tp.tv_sec);
746 	tst_its_set_value_nsec(its, tp.tv_nsec);
747 }
748 
749 /*
750  * Sets tst_its it_interval from tst_ts.
751  */
tst_its_set_interval_from_ts(struct tst_its * its,struct tst_ts ts)752 static inline void tst_its_set_interval_from_ts(struct tst_its *its, struct tst_ts ts)
753 {
754 	tst_its_set_interval_sec(its, tst_ts_get_sec(ts));
755 	tst_its_set_interval_nsec(its, tst_ts_get_nsec(ts));
756 }
757 
758 /*
759  * Sets tst_its it_value from tst_ts.
760  */
tst_its_set_value_from_ts(struct tst_its * its,struct tst_ts ts)761 static inline void tst_its_set_value_from_ts(struct tst_its *its, struct tst_ts ts)
762 {
763 	tst_its_set_value_sec(its, tst_ts_get_sec(ts));
764 	tst_its_set_value_nsec(its, tst_ts_get_nsec(ts));
765 }
766 
767 /*
768  * Returns if t1 less than t2. Both t1 and t2 must be normalized.
769  */
tst_ts_lt(struct tst_ts t1,struct tst_ts t2)770 static inline int tst_ts_lt(struct tst_ts t1, struct tst_ts t2)
771 {
772 	if (tst_ts_get_sec(t1) == tst_ts_get_sec(t2))
773 		return tst_ts_get_nsec(t1) < tst_ts_get_nsec(t2);
774 
775 	return tst_ts_get_sec(t1) < tst_ts_get_sec(t2);
776 }
777 
778 /*
779  * Returns if ts1 less than ts2. Both ts1 and ts2 must be normalized.
780  */
tst_timespec_lt(struct timespec ts1,struct timespec ts2)781 static inline int tst_timespec_lt(struct timespec ts1, struct timespec ts2)
782 {
783 	return tst_ts_lt(tst_ts_from_timespec(ts1), tst_ts_from_timespec(ts2));
784 }
785 
786 /*
787  * Returns normalized tst_ts, i.e. 0 <= nsec < 1000000000.
788  */
tst_ts_normalize(struct tst_ts t)789 static inline struct tst_ts tst_ts_normalize(struct tst_ts t)
790 {
791 	long long sec = tst_ts_get_sec(t);
792 	long long nsec = tst_ts_get_nsec(t);
793 
794 	if (nsec >= 1000000000) {
795 		tst_ts_set_sec(&t, sec + 1);
796 		tst_ts_set_nsec(&t, nsec - 1000000000);
797 	}
798 
799 	if (nsec < 0) {
800 		tst_ts_set_sec(&t, sec - 1);
801 		tst_ts_set_nsec(&t, nsec + 1000000000);
802 	}
803 
804 	return t;
805 }
806 
807 /*
808  * Adds us microseconds to tst_ts.
809  */
810 static inline struct tst_ts
tst_ts_add_us(struct tst_ts t,long long us)811 tst_ts_add_us(struct tst_ts t, long long us)
812 {
813 	struct tst_ts res = {.type = t.type};
814 
815 	tst_ts_set_sec(&res, tst_ts_get_sec(t) + us / 1000000);
816 	tst_ts_set_nsec(&res, tst_ts_get_nsec(t) + (us % 1000000) * 1000);
817 
818 	return tst_ts_normalize(res);
819 }
820 
821 /*
822  * Adds us microseconds to struct timespec.
823  */
824 static inline struct timespec
tst_timespec_add_us(struct timespec ts,long long us)825 tst_timespec_add_us(struct timespec ts, long long us)
826 {
827 	struct tst_ts res;
828 
829 	res = tst_ts_add_us(tst_ts_from_timespec(ts), us);
830 
831 	return tst_ts_to_timespec(res);
832 }
833 
834 /*
835  * Substracts us microseconds from tst_ts.
836  */
837 static inline struct tst_ts
tst_ts_sub_us(struct tst_ts t,long long us)838 tst_ts_sub_us(struct tst_ts t, long long us)
839 {
840 	struct tst_ts res = {.type = t.type};
841 
842 	tst_ts_set_sec(&res, tst_ts_get_sec(t) - us / 1000000);
843 	tst_ts_set_nsec(&res, tst_ts_get_nsec(t) - (us % 1000000) * 1000);
844 
845 	return tst_ts_normalize(res);
846 }
847 
848 /*
849  * Substracts us microseconds from timespec.
850  */
851 static inline struct timespec
tst_timespec_sub_us(struct timespec ts,long long us)852 tst_timespec_sub_us(struct timespec ts, long long us)
853 {
854 	struct tst_ts res;
855 
856 	res = tst_ts_sub_us(tst_ts_from_timespec(ts), us);
857 
858 	return tst_ts_to_timespec(res);
859 }
860 
861 /*
862  * Adds two tst_ts structures.
863  */
864 static inline struct tst_ts
tst_ts_add(struct tst_ts t1,struct tst_ts t2)865 tst_ts_add(struct tst_ts t1, struct tst_ts t2)
866 {
867 	struct tst_ts res = {.type = t1.type};
868 
869 	tst_ts_set_sec(&res, tst_ts_get_sec(t1) + tst_ts_get_sec(t2));
870 	tst_ts_set_nsec(&res, tst_ts_get_nsec(t1) + tst_ts_get_nsec(t2));
871 
872 	return tst_ts_normalize(res);
873 }
874 
875 /*
876  * Adds two timespec structures.
877  */
878 static inline struct timespec
tst_timespec_add(struct timespec ts1,struct timespec ts2)879 tst_timespec_add(struct timespec ts1, struct timespec ts2)
880 {
881 	struct tst_ts res;
882 
883 	res = tst_ts_add(tst_ts_from_timespec(ts1), tst_ts_from_timespec(ts2));
884 
885 	return tst_ts_to_timespec(res);
886 }
887 
888 /*
889  * Substract two tst_ts structures.
890  */
891 static inline struct tst_ts
tst_ts_diff(struct tst_ts t1,struct tst_ts t2)892 tst_ts_diff(struct tst_ts t1, struct tst_ts t2)
893 {
894 	struct tst_ts res = {.type = t1.type};
895 
896 	tst_ts_set_sec(&res, tst_ts_get_sec(t1) - tst_ts_get_sec(t2));
897 	tst_ts_set_nsec(&res, tst_ts_get_nsec(t1) - tst_ts_get_nsec(t2));
898 
899 	return tst_ts_normalize(res);
900 }
901 
902 /*
903  * Substract two timespec structures.
904  */
905 static inline struct timespec
tst_timespec_diff(struct timespec ts1,struct timespec ts2)906 tst_timespec_diff(struct timespec ts1, struct timespec ts2)
907 {
908 	struct tst_ts res;
909 
910 	res = tst_ts_diff(tst_ts_from_timespec(ts1), tst_ts_from_timespec(ts2));
911 
912 	return tst_ts_to_timespec(res);
913 }
914 
915 /*
916  * Substract two tst_ts structures returns number of nanoseconds.
917  */
918 static inline long long
tst_ts_diff_ns(struct tst_ts t1,struct tst_ts t2)919 tst_ts_diff_ns(struct tst_ts t1, struct tst_ts t2)
920 {
921 	return tst_ts_to_ns(tst_ts_diff(t1, t2));
922 }
923 
924 /*
925  * Substract two timespec structures returns number of nanoseconds.
926  */
927 static inline long long
tst_timespec_diff_ns(struct timespec ts1,struct timespec ts2)928 tst_timespec_diff_ns(struct timespec ts1, struct timespec ts2)
929 {
930 	return tst_ts_diff_ns(tst_ts_from_timespec(ts1), tst_ts_from_timespec(ts2));
931 }
932 
933 /*
934  * Substract two tst_ts structures returns number of microseconds.
935  */
936 static inline long long
tst_ts_diff_us(struct tst_ts t1,struct tst_ts t2)937 tst_ts_diff_us(struct tst_ts t1, struct tst_ts t2)
938 {
939 	return tst_ts_to_us(tst_ts_diff(t1, t2));
940 }
941 
942 /*
943  * Substract two timespec structures returns number of microseconds.
944  */
945 static inline long long
tst_timespec_diff_us(struct timespec ts1,struct timespec ts2)946 tst_timespec_diff_us(struct timespec ts1, struct timespec ts2)
947 {
948 	return tst_ts_diff_us(tst_ts_from_timespec(ts1), tst_ts_from_timespec(ts2));
949 }
950 
951 /*
952  * Substract two tst_ts structures returns number of milliseconds.
953  */
954 static inline long long
tst_ts_diff_ms(struct tst_ts t1,struct tst_ts t2)955 tst_ts_diff_ms(struct tst_ts t1, struct tst_ts t2)
956 {
957 	return tst_ts_to_ms(tst_ts_diff(t1, t2));
958 }
959 
960 /*
961  * Substract two timespec structures returns number of milliseconds.
962  */
963 static inline long long
tst_timespec_diff_ms(struct timespec ts1,struct timespec ts2)964 tst_timespec_diff_ms(struct timespec ts1, struct timespec ts2)
965 {
966 	return tst_ts_diff_ms(tst_ts_from_timespec(ts1), tst_ts_from_timespec(ts2));
967 }
968 
969 /*
970  * Returns absolute value of difference between two timespec structures.
971  */
972 static inline struct tst_ts
tst_ts_abs_diff(struct tst_ts t1,struct tst_ts t2)973 tst_ts_abs_diff(struct tst_ts t1, struct tst_ts t2)
974 {
975 	if (tst_ts_lt(t1, t2))
976 		return tst_ts_diff(t2, t1);
977 	else
978 		return tst_ts_diff(t1, t2);
979 }
980 
981 /*
982  * Returns absolute value of difference between two tst_ts structures in
983  * microseconds.
984  */
985 static inline long long
tst_ts_abs_diff_us(struct tst_ts t1,struct tst_ts t2)986 tst_ts_abs_diff_us(struct tst_ts t1, struct tst_ts t2)
987 {
988 	return tst_ts_to_us(tst_ts_abs_diff(t1, t2));
989 }
990 
991 /*
992  * Returns absolute value of difference between two timespec structures in
993  * microseconds.
994  */
995 static inline long long
tst_timespec_abs_diff_us(struct timespec ts1,struct timespec ts2)996 tst_timespec_abs_diff_us(struct timespec ts1, struct timespec ts2)
997 {
998 	return tst_ts_abs_diff_us(tst_ts_from_timespec(ts1), tst_ts_from_timespec(ts2));
999 }
1000 
1001 /*
1002  * Returns absolute value of difference between two timespec structures in
1003  * milliseconds.
1004  */
1005 static inline long long
tst_ts_abs_diff_ms(struct tst_ts t1,struct tst_ts t2)1006 tst_ts_abs_diff_ms(struct tst_ts t1, struct tst_ts t2)
1007 {
1008 	return tst_ts_to_ms(tst_ts_abs_diff(t1, t2));
1009 }
1010 
1011 /*
1012  * Exits the test with TCONF if particular timer is not supported. This is
1013  * intended to be used in test setup. There is no cleanup callback parameter as
1014  * you are expected to call it before initializing any resources that has to be
1015  * cleaned up later.
1016  *
1017  * @clk_id: Posix clock to use.
1018  */
1019 void tst_timer_check(clockid_t clk_id);
1020 
1021 /*
1022  * Marks a start time for given clock type.
1023  *
1024  * @clk_id: Posix clock to use.
1025  */
1026 void tst_timer_start(clockid_t clk_id);
1027 
1028 /*
1029  * Returns true if timer started by tst_timer_start() has been running for
1030  * longer than ms seconds.
1031  *
1032  * @ms: Time interval in milliseconds.
1033  */
1034 int tst_timer_expired_ms(long long ms);
1035 
1036 /*
1037  * Marks timer end time.
1038  */
1039 void tst_timer_stop(void);
1040 
1041 /*
1042  * Retuns elapsed time in struct timespec.
1043  */
1044 struct timespec tst_timer_elapsed(void);
1045 
1046 /*
1047  * Returns elapsed time in milliseconds.
1048  */
tst_timer_elapsed_ms(void)1049 static inline long long tst_timer_elapsed_ms(void)
1050 {
1051 	return tst_timespec_to_ms(tst_timer_elapsed());
1052 }
1053 
1054 /*
1055  * Returns elapsed time in microseconds.
1056  */
tst_timer_elapsed_us(void)1057 static inline long long tst_timer_elapsed_us(void)
1058 {
1059 	return tst_timespec_to_us(tst_timer_elapsed());
1060 }
1061 
1062 #endif /* TST_TIMER */
1063