Commit | Line | Data |
---|---|---|
3c39a379 JA |
1 | #include <time.h> |
2 | #include <sys/time.h> | |
3 | ||
4 | #include "fio.h" | |
5 | ||
263e529f JA |
6 | static struct timeval genesis; |
7 | ||
3c39a379 JA |
8 | unsigned long utime_since(struct timeval *s, struct timeval *e) |
9 | { | |
1e97cce9 | 10 | long sec, usec; |
3c39a379 JA |
11 | |
12 | sec = e->tv_sec - s->tv_sec; | |
13 | usec = e->tv_usec - s->tv_usec; | |
14 | if (sec > 0 && usec < 0) { | |
15 | sec--; | |
16 | usec += 1000000; | |
17 | } | |
18 | ||
19 | sec *= (double) 1000000; | |
20 | ||
21 | return sec + usec; | |
22 | } | |
23 | ||
69008999 | 24 | unsigned long utime_since_now(struct timeval *s) |
3c39a379 JA |
25 | { |
26 | struct timeval t; | |
27 | ||
02bcaa8c | 28 | fio_gettime(&t, NULL); |
3c39a379 JA |
29 | return utime_since(s, &t); |
30 | } | |
31 | ||
32 | unsigned long mtime_since(struct timeval *s, struct timeval *e) | |
33 | { | |
1e97cce9 | 34 | long sec, usec; |
3c39a379 JA |
35 | |
36 | sec = e->tv_sec - s->tv_sec; | |
37 | usec = e->tv_usec - s->tv_usec; | |
38 | if (sec > 0 && usec < 0) { | |
39 | sec--; | |
40 | usec += 1000000; | |
41 | } | |
42 | ||
43 | sec *= (double) 1000; | |
44 | usec /= (double) 1000; | |
45 | ||
46 | return sec + usec; | |
47 | } | |
48 | ||
49 | unsigned long mtime_since_now(struct timeval *s) | |
50 | { | |
51 | struct timeval t; | |
02bcaa8c | 52 | void *p = __builtin_return_address(0); |
3c39a379 | 53 | |
02bcaa8c | 54 | fio_gettime(&t, p); |
3c39a379 JA |
55 | return mtime_since(s, &t); |
56 | } | |
57 | ||
58 | unsigned long time_since_now(struct timeval *s) | |
59 | { | |
60 | return mtime_since_now(s) / 1000; | |
61 | } | |
62 | ||
63 | /* | |
64 | * busy looping version for the last few usec | |
65 | */ | |
b990b5c0 | 66 | void __usec_sleep(unsigned int usec) |
3c39a379 JA |
67 | { |
68 | struct timeval start; | |
69 | ||
02bcaa8c | 70 | fio_gettime(&start, NULL); |
3c39a379 JA |
71 | while (utime_since_now(&start) < usec) |
72 | nop; | |
73 | } | |
74 | ||
75 | void usec_sleep(struct thread_data *td, unsigned long usec) | |
76 | { | |
77 | struct timespec req, rem; | |
78 | ||
79 | req.tv_sec = usec / 1000000; | |
80 | req.tv_nsec = usec * 1000 - req.tv_sec * 1000000; | |
81 | ||
82 | do { | |
83 | if (usec < 5000) { | |
84 | __usec_sleep(usec); | |
85 | break; | |
86 | } | |
87 | ||
88 | rem.tv_sec = rem.tv_nsec = 0; | |
89 | if (nanosleep(&req, &rem) < 0) | |
90 | break; | |
91 | ||
92 | if ((rem.tv_sec + rem.tv_nsec) == 0) | |
93 | break; | |
94 | ||
95 | req.tv_nsec = rem.tv_nsec; | |
96 | req.tv_sec = rem.tv_sec; | |
97 | ||
98 | usec = rem.tv_sec * 1000000 + rem.tv_nsec / 1000; | |
99 | } while (!td->terminate); | |
100 | } | |
101 | ||
102 | void rate_throttle(struct thread_data *td, unsigned long time_spent, | |
a00735e6 | 103 | unsigned int bytes, int ddir) |
3c39a379 JA |
104 | { |
105 | unsigned long usec_cycle; | |
106 | ||
107 | if (!td->rate) | |
108 | return; | |
109 | ||
a00735e6 | 110 | usec_cycle = td->rate_usec_cycle * (bytes / td->min_bs[ddir]); |
3c39a379 JA |
111 | |
112 | if (time_spent < usec_cycle) { | |
113 | unsigned long s = usec_cycle - time_spent; | |
114 | ||
115 | td->rate_pending_usleep += s; | |
116 | if (td->rate_pending_usleep >= 100000) { | |
117 | usec_sleep(td, td->rate_pending_usleep); | |
118 | td->rate_pending_usleep = 0; | |
119 | } | |
120 | } else { | |
121 | long overtime = time_spent - usec_cycle; | |
122 | ||
123 | td->rate_pending_usleep -= overtime; | |
124 | } | |
125 | } | |
263e529f JA |
126 | |
127 | unsigned long mtime_since_genesis(void) | |
128 | { | |
129 | return mtime_since_now(&genesis); | |
130 | } | |
131 | ||
02bcaa8c | 132 | static void fio_init time_init(void) |
263e529f | 133 | { |
02bcaa8c | 134 | fio_gettime(&genesis, NULL); |
263e529f | 135 | } |
6043c579 JA |
136 | |
137 | void fill_start_time(struct timeval *t) | |
138 | { | |
139 | memcpy(t, &genesis, sizeof(genesis)); | |
140 | } |