1#include <time.h> 2#include <sys/time.h> 3 4#include "fio.h" 5 6static struct timeval genesis; 7static unsigned long ns_granularity; 8 9/* 10 * busy looping version for the last few usec 11 */ 12uint64_t usec_spin(unsigned int usec) 13{ 14 struct timeval start; 15 uint64_t t; 16 17 fio_gettime(&start, NULL); 18 while ((t = utime_since_now(&start)) < usec) 19 nop; 20 21 return t; 22} 23 24uint64_t usec_sleep(struct thread_data *td, unsigned long usec) 25{ 26 struct timespec req; 27 struct timeval tv; 28 uint64_t t = 0; 29 30 do { 31 unsigned long ts = usec; 32 33 if (usec < ns_granularity) { 34 t += usec_spin(usec); 35 break; 36 } 37 38 ts = usec - ns_granularity; 39 40 if (ts >= 1000000) { 41 req.tv_sec = ts / 1000000; 42 ts -= 1000000 * req.tv_sec; 43 } else 44 req.tv_sec = 0; 45 46 req.tv_nsec = ts * 1000; 47 fio_gettime(&tv, NULL); 48 49 if (nanosleep(&req, NULL) < 0) 50 break; 51 52 ts = utime_since_now(&tv); 53 t += ts; 54 if (ts >= usec) 55 break; 56 57 usec -= ts; 58 } while (!td->terminate); 59 60 return t; 61} 62 63uint64_t time_since_genesis(void) 64{ 65 return time_since_now(&genesis); 66} 67 68uint64_t mtime_since_genesis(void) 69{ 70 return mtime_since_now(&genesis); 71} 72 73uint64_t utime_since_genesis(void) 74{ 75 return utime_since_now(&genesis); 76} 77 78int in_ramp_time(struct thread_data *td) 79{ 80 return td->o.ramp_time && !td->ramp_time_over; 81} 82 83int ramp_time_over(struct thread_data *td) 84{ 85 struct timeval tv; 86 87 if (!td->o.ramp_time || td->ramp_time_over) 88 return 1; 89 90 fio_gettime(&tv, NULL); 91 if (utime_since(&td->epoch, &tv) >= td->o.ramp_time) { 92 td->ramp_time_over = 1; 93 reset_all_stats(td); 94 td_set_runstate(td, TD_RAMP); 95 return 1; 96 } 97 98 return 0; 99} 100 101void fio_time_init(void) 102{ 103 int i; 104 105 fio_clock_init(); 106 107 /* 108 * Check the granularity of the nanosleep function 109 */ 110 for (i = 0; i < 10; i++) { 111 struct timeval tv; 112 struct timespec ts; 113 unsigned long elapsed; 114 115 fio_gettime(&tv, NULL); 116 ts.tv_sec = 0; 117 ts.tv_nsec = 1000; 118 119 nanosleep(&ts, NULL); 120 elapsed = utime_since_now(&tv); 121 122 if (elapsed > ns_granularity) 123 ns_granularity = elapsed; 124 } 125} 126 127void set_genesis_time(void) 128{ 129 fio_gettime(&genesis, NULL); 130} 131 132void fill_start_time(struct timeval *t) 133{ 134 memcpy(t, &genesis, sizeof(genesis)); 135} 136