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
37 /*
38 * Converts timespec to microseconds.
39 */
tst_timespec_to_us(struct timespec t)40 static inline long long tst_timespec_to_us(struct timespec t)
41 {
42 return t.tv_sec * 1000000 + (t.tv_nsec + 500) / 1000;
43 }
44
45 /*
46 * Converts timespec to miliseconds.
47 */
tst_timespec_to_ms(struct timespec t)48 static inline long long tst_timespec_to_ms(struct timespec t)
49 {
50 return t.tv_sec * 1000 + (t.tv_nsec + 500000) / 1000000;
51 }
52
53 /*
54 * Converts ms to struct timeval
55 */
tst_ms_to_timeval(long long ms)56 static inline struct timeval tst_ms_to_timeval(long long ms)
57 {
58 struct timeval ret;
59
60 ret.tv_sec = ms / 1000;
61 ret.tv_usec = (ms % 1000) * 1000;
62
63 return ret;
64 }
65
66 /*
67 * Converts us to struct timeval
68 */
tst_us_to_timeval(long long us)69 static inline struct timeval tst_us_to_timeval(long long us)
70 {
71 struct timeval ret;
72
73 ret.tv_sec = us / 1000000;
74 ret.tv_usec = us % 1000000;
75
76 return ret;
77 }
78
79 /*
80 * Comparsions
81 */
tst_timespec_lt(struct timespec t1,struct timespec t2)82 static inline int tst_timespec_lt(struct timespec t1, struct timespec t2)
83 {
84 if (t1.tv_sec == t2.tv_sec)
85 return t1.tv_nsec < t2.tv_nsec;
86
87 return t1.tv_sec < t2.tv_sec;
88 }
89
90 /*
91 * Adds us microseconds to t.
92 */
tst_timespec_add_us(struct timespec t,long long us)93 static inline struct timespec tst_timespec_add_us(struct timespec t,
94 long long us)
95 {
96 t.tv_sec += us / 1000000;
97 t.tv_nsec += (us % 1000000) * 1000;
98
99 if (t.tv_nsec >= 1000000000) {
100 t.tv_sec++;
101 t.tv_nsec -= 1000000000;
102 }
103
104 return t;
105 }
106
107 /*
108 * Returns difference between two timespec structures.
109 */
tst_timespec_diff(struct timespec t1,struct timespec t2)110 static inline struct timespec tst_timespec_diff(struct timespec t1,
111 struct timespec t2)
112 {
113 struct timespec res;
114
115 res.tv_sec = t1.tv_sec - t2.tv_sec;
116
117 if (t1.tv_nsec < t2.tv_nsec) {
118 res.tv_sec--;
119 res.tv_nsec = 1000000000 - (t2.tv_nsec - t1.tv_nsec);
120 } else {
121 res.tv_nsec = t1.tv_nsec - t2.tv_nsec;
122 }
123
124 return res;
125 }
126
tst_timespec_diff_us(struct timespec t1,struct timespec t2)127 static inline long long tst_timespec_diff_us(struct timespec t1,
128 struct timespec t2)
129 {
130 return tst_timespec_to_us(tst_timespec_diff(t1, t2));
131 }
132
tst_timespec_diff_ms(struct timespec t1,struct timespec t2)133 static inline long long tst_timespec_diff_ms(struct timespec t1,
134 struct timespec t2)
135 {
136 return tst_timespec_to_ms(tst_timespec_diff(t1, t2));
137 }
138
139 /*
140 * Returns absolute value of difference between two timespec structures.
141 */
tst_timespec_abs_diff(struct timespec t1,struct timespec t2)142 static inline struct timespec tst_timespec_abs_diff(struct timespec t1,
143 struct timespec t2)
144 {
145 if (tst_timespec_lt(t1, t2))
146 return tst_timespec_diff(t2, t1);
147 else
148 return tst_timespec_diff(t1, t2);
149 }
150
tst_timespec_abs_diff_us(struct timespec t1,struct timespec t2)151 static inline long long tst_timespec_abs_diff_us(struct timespec t1,
152 struct timespec t2)
153 {
154 return tst_timespec_to_us(tst_timespec_abs_diff(t1, t2));
155 }
156
tst_timespec_abs_diff_ms(struct timespec t1,struct timespec t2)157 static inline long long tst_timespec_abs_diff_ms(struct timespec t1,
158 struct timespec t2)
159 {
160 return tst_timespec_to_ms(tst_timespec_abs_diff(t1, t2));
161 }
162
163 /*
164 * Exits the test with TCONF if particular timer is not supported. This is
165 * intended to be used in test setup. There is no cleanup callback parameter as
166 * you are expected to call it before initializing any resources that has to be
167 * cleaned up later.
168 *
169 * @clk_id: Posix clock to use.
170 */
171 void tst_timer_check(clockid_t clk_id);
172
173 /*
174 * Marks a start time for given clock type.
175 *
176 * @clk_id: Posix clock to use.
177 */
178 void tst_timer_start(clockid_t clk_id);
179
180 /*
181 * Marks timer end time.
182 */
183 void tst_timer_stop(void);
184
185 /*
186 * Retuns elapsed time in struct timespec.
187 */
188 struct timespec tst_timer_elapsed(void);
189
190 /*
191 * Returns elapsed time in miliseconds.
192 */
tst_timer_elapsed_ms(void)193 static inline long long tst_timer_elapsed_ms(void)
194 {
195 return tst_timespec_to_ms(tst_timer_elapsed());
196 }
197
198 /*
199 * Returns elapsed time in microseconds.
200 */
tst_timer_elapsed_us(void)201 static inline long long tst_timer_elapsed_us(void)
202 {
203 return tst_timespec_to_us(tst_timer_elapsed());
204 }
205
206 #endif /* TST_TIMER */
207