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