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 | { | |
10 | double sec, usec; | |
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 | ||
24 | static unsigned long utime_since_now(struct timeval *s) | |
25 | { | |
26 | struct timeval t; | |
27 | ||
28 | gettimeofday(&t, NULL); | |
29 | return utime_since(s, &t); | |
30 | } | |
31 | ||
32 | unsigned long mtime_since(struct timeval *s, struct timeval *e) | |
33 | { | |
34 | double sec, usec; | |
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; | |
52 | ||
53 | gettimeofday(&t, NULL); | |
54 | return mtime_since(s, &t); | |
55 | } | |
56 | ||
57 | unsigned long time_since_now(struct timeval *s) | |
58 | { | |
59 | return mtime_since_now(s) / 1000; | |
60 | } | |
61 | ||
62 | /* | |
63 | * busy looping version for the last few usec | |
64 | */ | |
b990b5c0 | 65 | void __usec_sleep(unsigned int usec) |
3c39a379 JA |
66 | { |
67 | struct timeval start; | |
68 | ||
69 | gettimeofday(&start, NULL); | |
70 | while (utime_since_now(&start) < usec) | |
71 | nop; | |
72 | } | |
73 | ||
74 | void usec_sleep(struct thread_data *td, unsigned long usec) | |
75 | { | |
76 | struct timespec req, rem; | |
77 | ||
78 | req.tv_sec = usec / 1000000; | |
79 | req.tv_nsec = usec * 1000 - req.tv_sec * 1000000; | |
80 | ||
81 | do { | |
82 | if (usec < 5000) { | |
83 | __usec_sleep(usec); | |
84 | break; | |
85 | } | |
86 | ||
87 | rem.tv_sec = rem.tv_nsec = 0; | |
88 | if (nanosleep(&req, &rem) < 0) | |
89 | break; | |
90 | ||
91 | if ((rem.tv_sec + rem.tv_nsec) == 0) | |
92 | break; | |
93 | ||
94 | req.tv_nsec = rem.tv_nsec; | |
95 | req.tv_sec = rem.tv_sec; | |
96 | ||
97 | usec = rem.tv_sec * 1000000 + rem.tv_nsec / 1000; | |
98 | } while (!td->terminate); | |
99 | } | |
100 | ||
101 | void rate_throttle(struct thread_data *td, unsigned long time_spent, | |
102 | unsigned int bytes) | |
103 | { | |
104 | unsigned long usec_cycle; | |
105 | ||
106 | if (!td->rate) | |
107 | return; | |
108 | ||
109 | usec_cycle = td->rate_usec_cycle * (bytes / td->min_bs); | |
110 | ||
111 | if (time_spent < usec_cycle) { | |
112 | unsigned long s = usec_cycle - time_spent; | |
113 | ||
114 | td->rate_pending_usleep += s; | |
115 | if (td->rate_pending_usleep >= 100000) { | |
116 | usec_sleep(td, td->rate_pending_usleep); | |
117 | td->rate_pending_usleep = 0; | |
118 | } | |
119 | } else { | |
120 | long overtime = time_spent - usec_cycle; | |
121 | ||
122 | td->rate_pending_usleep -= overtime; | |
123 | } | |
124 | } | |
263e529f JA |
125 | |
126 | unsigned long mtime_since_genesis(void) | |
127 | { | |
128 | return mtime_since_now(&genesis); | |
129 | } | |
130 | ||
131 | void time_init(void) | |
132 | { | |
133 | gettimeofday(&genesis, NULL); | |
134 | } |