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 miliseconds.
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 miliseconds.
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 * Returns difference between two timespec structures.
156 */
tst_timespec_diff(struct timespec t1,struct timespec t2)157 static inline struct timespec tst_timespec_diff(struct timespec t1,
158 struct timespec t2)
159 {
160 struct timespec res;
161
162 res.tv_sec = t1.tv_sec - t2.tv_sec;
163
164 if (t1.tv_nsec < t2.tv_nsec) {
165 res.tv_sec--;
166 res.tv_nsec = 1000000000 - (t2.tv_nsec - t1.tv_nsec);
167 } else {
168 res.tv_nsec = t1.tv_nsec - t2.tv_nsec;
169 }
170
171 return res;
172 }
173
tst_timespec_diff_ns(struct timespec t1,struct timespec t2)174 static inline long long tst_timespec_diff_ns(struct timespec t1,
175 struct timespec t2)
176 {
177 return t1.tv_nsec - t2.tv_nsec + 1000000000LL * (t1.tv_sec - t2.tv_sec);
178 }
179
tst_timespec_diff_us(struct timespec t1,struct timespec t2)180 static inline long long tst_timespec_diff_us(struct timespec t1,
181 struct timespec t2)
182 {
183 return tst_timespec_to_us(tst_timespec_diff(t1, t2));
184 }
185
tst_timespec_diff_ms(struct timespec t1,struct timespec t2)186 static inline long long tst_timespec_diff_ms(struct timespec t1,
187 struct timespec t2)
188 {
189 return tst_timespec_to_ms(tst_timespec_diff(t1, t2));
190 }
191
192 /*
193 * Returns difference between two timeval structures.
194 */
tst_timeval_diff(struct timeval t1,struct timeval t2)195 static inline struct timeval tst_timeval_diff(struct timeval t1,
196 struct timeval t2)
197 {
198 struct timeval res;
199
200 res.tv_sec = t1.tv_sec - t2.tv_sec;
201
202 if (t1.tv_usec < t2.tv_usec) {
203 res.tv_sec--;
204 res.tv_usec = 1000000 - (t2.tv_usec - t1.tv_usec);
205 } else {
206 res.tv_usec = t1.tv_usec - t2.tv_usec;
207 }
208
209 return res;
210 }
211
tst_timeval_diff_us(struct timeval t1,struct timeval t2)212 static inline long long tst_timeval_diff_us(struct timeval t1,
213 struct timeval t2)
214 {
215 return tst_timeval_to_us(tst_timeval_diff(t1, t2));
216 }
217
tst_timeval_diff_ms(struct timeval t1,struct timeval t2)218 static inline long long tst_timeval_diff_ms(struct timeval t1,
219 struct timeval t2)
220 {
221 return tst_timeval_to_ms(tst_timeval_diff(t1, t2));
222 }
223
224 /*
225 * Returns absolute value of difference between two timespec structures.
226 */
tst_timespec_abs_diff(struct timespec t1,struct timespec t2)227 static inline struct timespec tst_timespec_abs_diff(struct timespec t1,
228 struct timespec t2)
229 {
230 if (tst_timespec_lt(t1, t2))
231 return tst_timespec_diff(t2, t1);
232 else
233 return tst_timespec_diff(t1, t2);
234 }
235
tst_timespec_abs_diff_us(struct timespec t1,struct timespec t2)236 static inline long long tst_timespec_abs_diff_us(struct timespec t1,
237 struct timespec t2)
238 {
239 return tst_timespec_to_us(tst_timespec_abs_diff(t1, t2));
240 }
241
tst_timespec_abs_diff_ms(struct timespec t1,struct timespec t2)242 static inline long long tst_timespec_abs_diff_ms(struct timespec t1,
243 struct timespec t2)
244 {
245 return tst_timespec_to_ms(tst_timespec_abs_diff(t1, t2));
246 }
247
248 /*
249 * Exits the test with TCONF if particular timer is not supported. This is
250 * intended to be used in test setup. There is no cleanup callback parameter as
251 * you are expected to call it before initializing any resources that has to be
252 * cleaned up later.
253 *
254 * @clk_id: Posix clock to use.
255 */
256 void tst_timer_check(clockid_t clk_id);
257
258 /*
259 * Marks a start time for given clock type.
260 *
261 * @clk_id: Posix clock to use.
262 */
263 void tst_timer_start(clockid_t clk_id);
264
265 /*
266 * Returns true if timer started by tst_timer_start() has been running for
267 * longer than ms seconds.
268 *
269 * @ms: Time interval in miliseconds.
270 */
271 int tst_timer_expired_ms(long long ms);
272
273 /*
274 * Marks timer end time.
275 */
276 void tst_timer_stop(void);
277
278 /*
279 * Retuns elapsed time in struct timespec.
280 */
281 struct timespec tst_timer_elapsed(void);
282
283 /*
284 * Returns elapsed time in miliseconds.
285 */
tst_timer_elapsed_ms(void)286 static inline long long tst_timer_elapsed_ms(void)
287 {
288 return tst_timespec_to_ms(tst_timer_elapsed());
289 }
290
291 /*
292 * Returns elapsed time in microseconds.
293 */
tst_timer_elapsed_us(void)294 static inline long long tst_timer_elapsed_us(void)
295 {
296 return tst_timespec_to_us(tst_timer_elapsed());
297 }
298
299 #endif /* TST_TIMER */
300