Home | History | Annotate | Download | only in include
      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 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  */
     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  */
     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  */
     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  */
     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  */
     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  */
     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  */
    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  */
    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  */
    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  */
    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  */
    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 
    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 
    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 
    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  */
    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 
    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 
    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  */
    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 
    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 
    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  */
    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  */
    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