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 timeval to microseconds.
55 */
tst_timeval_to_us(struct timeval t)56 static inline long long tst_timeval_to_us(struct timeval t)
57 {
58 return t.tv_sec * 1000000 + t.tv_usec;
59 }
60
61 /*
62 * Converts timeval to miliseconds.
63 */
tst_timeval_to_ms(struct timeval t)64 static inline long long tst_timeval_to_ms(struct timeval t)
65 {
66 return t.tv_sec * 1000 + (t.tv_usec + 500) / 1000;
67 }
68
69 /*
70 * Converts ms to struct timeval
71 */
tst_ms_to_timeval(long long ms)72 static inline struct timeval tst_ms_to_timeval(long long ms)
73 {
74 struct timeval ret;
75
76 ret.tv_sec = ms / 1000;
77 ret.tv_usec = (ms % 1000) * 1000;
78
79 return ret;
80 }
81
82 /*
83 * Converts us to struct timeval
84 */
tst_us_to_timeval(long long us)85 static inline struct timeval tst_us_to_timeval(long long us)
86 {
87 struct timeval ret;
88
89 ret.tv_sec = us / 1000000;
90 ret.tv_usec = us % 1000000;
91
92 return ret;
93 }
94
95 /*
96 * Converts ms to struct timespec
97 */
tst_ms_to_timespec(long long ms)98 static inline struct timespec tst_ms_to_timespec(long long ms)
99 {
100 struct timespec ret;
101
102 ret.tv_sec = ms / 1000;
103 ret.tv_nsec = (ms % 1000) * 1000000;
104
105 return ret;
106 }
107
108 /*
109 * Converts us to struct timespec
110 */
tst_us_to_timespec(long long us)111 static inline struct timespec tst_us_to_timespec(long long us)
112 {
113 struct timespec ret;
114
115 ret.tv_sec = us / 1000000;
116 ret.tv_nsec = (us % 1000000) * 1000;
117
118 return ret;
119 }
120
121 /*
122 * Comparsions
123 */
tst_timespec_lt(struct timespec t1,struct timespec t2)124 static inline int tst_timespec_lt(struct timespec t1, struct timespec t2)
125 {
126 if (t1.tv_sec == t2.tv_sec)
127 return t1.tv_nsec < t2.tv_nsec;
128
129 return t1.tv_sec < t2.tv_sec;
130 }
131
132 /*
133 * Adds us microseconds to t.
134 */
tst_timespec_add_us(struct timespec t,long long us)135 static inline struct timespec tst_timespec_add_us(struct timespec t,
136 long long us)
137 {
138 t.tv_sec += us / 1000000;
139 t.tv_nsec += (us % 1000000) * 1000;
140
141 if (t.tv_nsec >= 1000000000) {
142 t.tv_sec++;
143 t.tv_nsec -= 1000000000;
144 }
145
146 return t;
147 }
148
149 /*
150 * Returns difference between two timespec structures.
151 */
tst_timespec_diff(struct timespec t1,struct timespec t2)152 static inline struct timespec tst_timespec_diff(struct timespec t1,
153 struct timespec t2)
154 {
155 struct timespec res;
156
157 res.tv_sec = t1.tv_sec - t2.tv_sec;
158
159 if (t1.tv_nsec < t2.tv_nsec) {
160 res.tv_sec--;
161 res.tv_nsec = 1000000000 - (t2.tv_nsec - t1.tv_nsec);
162 } else {
163 res.tv_nsec = t1.tv_nsec - t2.tv_nsec;
164 }
165
166 return res;
167 }
168
tst_timespec_diff_us(struct timespec t1,struct timespec t2)169 static inline long long tst_timespec_diff_us(struct timespec t1,
170 struct timespec t2)
171 {
172 return tst_timespec_to_us(tst_timespec_diff(t1, t2));
173 }
174
tst_timespec_diff_ms(struct timespec t1,struct timespec t2)175 static inline long long tst_timespec_diff_ms(struct timespec t1,
176 struct timespec t2)
177 {
178 return tst_timespec_to_ms(tst_timespec_diff(t1, t2));
179 }
180
181 /*
182 * Returns difference between two timeval structures.
183 */
tst_timeval_diff(struct timeval t1,struct timeval t2)184 static inline struct timeval tst_timeval_diff(struct timeval t1,
185 struct timeval t2)
186 {
187 struct timeval res;
188
189 res.tv_sec = t1.tv_sec - t2.tv_sec;
190
191 if (t1.tv_usec < t2.tv_usec) {
192 res.tv_sec--;
193 res.tv_usec = 1000000 - (t2.tv_usec - t1.tv_usec);
194 } else {
195 res.tv_usec = t1.tv_usec - t2.tv_usec;
196 }
197
198 return res;
199 }
200
tst_timeval_diff_us(struct timeval t1,struct timeval t2)201 static inline long long tst_timeval_diff_us(struct timeval t1,
202 struct timeval t2)
203 {
204 return tst_timeval_to_us(tst_timeval_diff(t1, t2));
205 }
206
tst_timeval_diff_ms(struct timeval t1,struct timeval t2)207 static inline long long tst_timeval_diff_ms(struct timeval t1,
208 struct timeval t2)
209 {
210 return tst_timeval_to_ms(tst_timeval_diff(t1, t2));
211 }
212
213 /*
214 * Returns absolute value of difference between two timespec structures.
215 */
tst_timespec_abs_diff(struct timespec t1,struct timespec t2)216 static inline struct timespec tst_timespec_abs_diff(struct timespec t1,
217 struct timespec t2)
218 {
219 if (tst_timespec_lt(t1, t2))
220 return tst_timespec_diff(t2, t1);
221 else
222 return tst_timespec_diff(t1, t2);
223 }
224
tst_timespec_abs_diff_us(struct timespec t1,struct timespec t2)225 static inline long long tst_timespec_abs_diff_us(struct timespec t1,
226 struct timespec t2)
227 {
228 return tst_timespec_to_us(tst_timespec_abs_diff(t1, t2));
229 }
230
tst_timespec_abs_diff_ms(struct timespec t1,struct timespec t2)231 static inline long long tst_timespec_abs_diff_ms(struct timespec t1,
232 struct timespec t2)
233 {
234 return tst_timespec_to_ms(tst_timespec_abs_diff(t1, t2));
235 }
236
237 /*
238 * Exits the test with TCONF if particular timer is not supported. This is
239 * intended to be used in test setup. There is no cleanup callback parameter as
240 * you are expected to call it before initializing any resources that has to be
241 * cleaned up later.
242 *
243 * @clk_id: Posix clock to use.
244 */
245 void tst_timer_check(clockid_t clk_id);
246
247 /*
248 * Marks a start time for given clock type.
249 *
250 * @clk_id: Posix clock to use.
251 */
252 void tst_timer_start(clockid_t clk_id);
253
254 /*
255 * Marks timer end time.
256 */
257 void tst_timer_stop(void);
258
259 /*
260 * Retuns elapsed time in struct timespec.
261 */
262 struct timespec tst_timer_elapsed(void);
263
264 /*
265 * Returns elapsed time in miliseconds.
266 */
tst_timer_elapsed_ms(void)267 static inline long long tst_timer_elapsed_ms(void)
268 {
269 return tst_timespec_to_ms(tst_timer_elapsed());
270 }
271
272 /*
273 * Returns elapsed time in microseconds.
274 */
tst_timer_elapsed_us(void)275 static inline long long tst_timer_elapsed_us(void)
276 {
277 return tst_timespec_to_us(tst_timer_elapsed());
278 }
279
280 #endif /* TST_TIMER */
281