1 /* 2 * Copyright (C) 2015 Cyril Hrubis <chrubis (at) 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 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 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 */ 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 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 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 */ 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 */ 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