Documentation: fix psyncv2 typo
[fio.git] / time.c
... / ...
CommitLineData
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
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
18/*
19 * busy looping version for the last few usec
20 */
21uint64_t usec_spin(unsigned int usec)
22{
23 struct timeval start;
24 uint64_t t;
25
26 fio_gettime(&start, NULL);
27 while ((t = utime_since_now(&start)) < usec)
28 nop;
29
30 return t;
31}
32
33uint64_t usec_sleep(struct thread_data *td, unsigned long usec)
34{
35 struct timespec req;
36 struct timeval tv;
37 uint64_t t = 0;
38
39 do {
40 unsigned long ts = usec;
41
42 if (usec < ns_granularity) {
43 t += usec_spin(usec);
44 break;
45 }
46
47 ts = usec - ns_granularity;
48
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)
59 break;
60
61 ts = utime_since_now(&tv);
62 t += ts;
63 if (ts >= usec)
64 break;
65
66 usec -= ts;
67 } while (!td->terminate);
68
69 return t;
70}
71
72uint64_t time_since_genesis(void)
73{
74 return time_since_now(&genesis);
75}
76
77uint64_t mtime_since_genesis(void)
78{
79 return mtime_since_now(&genesis);
80}
81
82uint64_t utime_since_genesis(void)
83{
84 return utime_since_now(&genesis);
85}
86
87int in_ramp_time(struct thread_data *td)
88{
89 return td->o.ramp_time && !td->ramp_time_over;
90}
91
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
104int ramp_time_over(struct thread_data *td)
105{
106 struct timeval tv;
107
108 if (!td->o.ramp_time || td->ramp_time_over)
109 return 1;
110
111 fio_gettime(&tv, NULL);
112 if (utime_since(&td->epoch, &tv) >= td->o.ramp_time) {
113 td->ramp_time_over = 1;
114 reset_all_stats(td);
115 td_set_runstate(td, TD_RAMP);
116 parent_update_ramp(td);
117 return 1;
118 }
119
120 return 0;
121}
122
123void fio_time_init(void)
124{
125 int i;
126
127 fio_clock_init();
128
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 }
147}
148
149void set_genesis_time(void)
150{
151 fio_gettime(&genesis, NULL);
152}
153
154void fill_start_time(struct timeval *t)
155{
156 memcpy(t, &genesis, sizeof(genesis));
157}