eta: Fix ETA oddness at crossover points
[fio.git] / time.c
CommitLineData
3c39a379
JA
1#include <time.h>
2#include <sys/time.h>
3
4#include "fio.h"
5
263e529f 6static struct timeval genesis;
fd841467 7static unsigned long ns_granularity;
263e529f 8
a47591e4
JA
9void timeval_add_msec(struct timeval *tv, unsigned int msec)
10{
11 tv->tv_usec += 1000 * msec;
12 if (tv->tv_usec >= 1000000) {
13 tv->tv_usec -= 1000000;
14 tv->tv_sec++;
15 }
16}
17
3c39a379
JA
18/*
19 * busy looping version for the last few usec
20 */
9cc80b6d 21uint64_t usec_spin(unsigned int usec)
3c39a379
JA
22{
23 struct timeval start;
9cc80b6d 24 uint64_t t;
3c39a379 25
02bcaa8c 26 fio_gettime(&start, NULL);
9cc80b6d 27 while ((t = utime_since_now(&start)) < usec)
3c39a379 28 nop;
9cc80b6d
JA
29
30 return t;
3c39a379
JA
31}
32
9cc80b6d 33uint64_t usec_sleep(struct thread_data *td, unsigned long usec)
3c39a379 34{
fd841467
JA
35 struct timespec req;
36 struct timeval tv;
9cc80b6d 37 uint64_t t = 0;
3c39a379
JA
38
39 do {
fd841467
JA
40 unsigned long ts = usec;
41
42 if (usec < ns_granularity) {
9cc80b6d 43 t += usec_spin(usec);
3c39a379
JA
44 break;
45 }
46
fd841467 47 ts = usec - ns_granularity;
3c39a379 48
fd841467
JA
49 if (ts >= 1000000) {
50 req.tv_sec = ts / 1000000;
51 ts -= 1000000 * req.tv_sec;
52 } else
53 req.tv_sec = 0;
54
55 req.tv_nsec = ts * 1000;
56 fio_gettime(&tv, NULL);
57
58 if (nanosleep(&req, NULL) < 0)
3c39a379
JA
59 break;
60
fd841467 61 ts = utime_since_now(&tv);
9cc80b6d 62 t += ts;
fd841467
JA
63 if (ts >= usec)
64 break;
3c39a379 65
fd841467 66 usec -= ts;
3c39a379 67 } while (!td->terminate);
9cc80b6d
JA
68
69 return t;
3c39a379
JA
70}
71
8b22c785
JA
72uint64_t time_since_genesis(void)
73{
74 return time_since_now(&genesis);
75}
76
aa60bc58 77uint64_t mtime_since_genesis(void)
263e529f
JA
78{
79 return mtime_since_now(&genesis);
80}
81
0de5b26f
JA
82uint64_t utime_since_genesis(void)
83{
84 return utime_since_now(&genesis);
85}
86
356014ff 87bool in_ramp_time(struct thread_data *td)
b29ee5b3
JA
88{
89 return td->o.ramp_time && !td->ramp_time_over;
90}
91
ada8f235
JA
92static void parent_update_ramp(struct thread_data *td)
93{
94 struct thread_data *parent = td->parent;
95
96 if (!parent || parent->ramp_time_over)
97 return;
98
99 reset_all_stats(parent);
100 parent->ramp_time_over = 1;
101 td_set_runstate(parent, TD_RAMP);
102}
103
356014ff 104bool ramp_time_over(struct thread_data *td)
721938ae
JA
105{
106 struct timeval tv;
107
108 if (!td->o.ramp_time || td->ramp_time_over)
356014ff 109 return true;
721938ae
JA
110
111 fio_gettime(&tv, NULL);
0de5b26f 112 if (utime_since(&td->epoch, &tv) >= td->o.ramp_time) {
721938ae 113 td->ramp_time_over = 1;
b29ee5b3
JA
114 reset_all_stats(td);
115 td_set_runstate(td, TD_RAMP);
ada8f235 116 parent_update_ramp(td);
356014ff 117 return true;
721938ae
JA
118 }
119
356014ff 120 return false;
721938ae
JA
121}
122
03e20d68 123void fio_time_init(void)
263e529f 124{
fd841467
JA
125 int i;
126
c223da83
JA
127 fio_clock_init();
128
fd841467
JA
129 /*
130 * Check the granularity of the nanosleep function
131 */
132 for (i = 0; i < 10; i++) {
133 struct timeval tv;
134 struct timespec ts;
135 unsigned long elapsed;
136
137 fio_gettime(&tv, NULL);
138 ts.tv_sec = 0;
139 ts.tv_nsec = 1000;
140
141 nanosleep(&ts, NULL);
142 elapsed = utime_since_now(&tv);
143
144 if (elapsed > ns_granularity)
145 ns_granularity = elapsed;
146 }
263e529f 147}
6043c579 148
a2f77c9f
JA
149void set_genesis_time(void)
150{
151 fio_gettime(&genesis, NULL);
152}
153
3aea75b1
KC
154void set_epoch_time(struct thread_data *td, int log_unix_epoch)
155{
156 fio_gettime(&td->epoch, NULL);
157 if (log_unix_epoch) {
158 struct timeval tv;
159 gettimeofday(&tv, NULL);
160 td->unix_epoch = (unsigned long long)(tv.tv_sec) * 1000 +
161 (unsigned long long)(tv.tv_usec) / 1000;
162 }
163}
164
6043c579
JA
165void fill_start_time(struct timeval *t)
166{
167 memcpy(t, &genesis, sizeof(genesis));
168}