bloom: if we're not setting bits, break after first failed mask check
[fio.git] / helper_thread.c
1 #include "fio.h"
2 #include "smalloc.h"
3 #include "helper_thread.h"
4 #include "steadystate.h"
5
6 static struct helper_data {
7         volatile int exit;
8         volatile int reset;
9         volatile int do_stat;
10         struct sk_out *sk_out;
11         pthread_t thread;
12         pthread_mutex_t lock;
13         pthread_cond_t cond;
14         struct fio_mutex *startup_mutex;
15 } *helper_data;
16
17 void helper_thread_destroy(void)
18 {
19         pthread_cond_destroy(&helper_data->cond);
20         pthread_mutex_destroy(&helper_data->lock);
21         sfree(helper_data);
22 }
23
24 void helper_reset(void)
25 {
26         if (!helper_data)
27                 return;
28
29         pthread_mutex_lock(&helper_data->lock);
30
31         if (!helper_data->reset) {
32                 helper_data->reset = 1;
33                 pthread_cond_signal(&helper_data->cond);
34         }
35
36         pthread_mutex_unlock(&helper_data->lock);
37 }
38
39 void helper_do_stat(void)
40 {
41         if (!helper_data)
42                 return;
43
44         pthread_mutex_lock(&helper_data->lock);
45         helper_data->do_stat = 1;
46         pthread_cond_signal(&helper_data->cond);
47         pthread_mutex_unlock(&helper_data->lock);
48 }
49
50 bool helper_should_exit(void)
51 {
52         if (!helper_data)
53                 return true;
54
55         return helper_data->exit;
56 }
57
58 void helper_thread_exit(void)
59 {
60         void *ret;
61
62         pthread_mutex_lock(&helper_data->lock);
63         helper_data->exit = 1;
64         pthread_cond_signal(&helper_data->cond);
65         pthread_mutex_unlock(&helper_data->lock);
66
67         pthread_join(helper_data->thread, &ret);
68 }
69
70 static void *helper_thread_main(void *data)
71 {
72         struct helper_data *hd = data;
73         unsigned int msec_to_next_event, next_log, next_ss = STEADYSTATE_MSEC;
74         struct timeval tv, last_du, last_ss;
75         int ret = 0;
76
77         sk_out_assign(hd->sk_out);
78
79         gettimeofday(&tv, NULL);
80         memcpy(&last_du, &tv, sizeof(tv));
81         memcpy(&last_ss, &tv, sizeof(tv));
82
83         fio_mutex_up(hd->startup_mutex);
84
85         msec_to_next_event = DISK_UTIL_MSEC;
86         while (!ret && !hd->exit) {
87                 struct timespec ts;
88                 struct timeval now;
89                 uint64_t since_du, since_ss = 0;
90
91                 timeval_add_msec(&tv, msec_to_next_event);
92                 ts.tv_sec = tv.tv_sec;
93                 ts.tv_nsec = tv.tv_usec * 1000;
94
95                 pthread_mutex_lock(&hd->lock);
96                 pthread_cond_timedwait(&hd->cond, &hd->lock, &ts);
97
98                 gettimeofday(&now, NULL);
99
100                 if (hd->reset) {
101                         memcpy(&tv, &now, sizeof(tv));
102                         memcpy(&last_du, &now, sizeof(last_du));
103                         memcpy(&last_ss, &now, sizeof(last_ss));
104                         hd->reset = 0;
105                 }
106
107                 pthread_mutex_unlock(&hd->lock);
108
109                 since_du = mtime_since(&last_du, &now);
110                 if (since_du >= DISK_UTIL_MSEC || DISK_UTIL_MSEC - since_du < 10) {
111                         ret = update_io_ticks();
112                         timeval_add_msec(&last_du, DISK_UTIL_MSEC);
113                         msec_to_next_event = DISK_UTIL_MSEC;
114                         if (since_du >= DISK_UTIL_MSEC)
115                                 msec_to_next_event -= (since_du - DISK_UTIL_MSEC);
116                 } else
117                         msec_to_next_event = DISK_UTIL_MSEC - since_du;
118
119                 if (hd->do_stat) {
120                         hd->do_stat = 0;
121                         __show_running_run_stats();
122                 }
123
124                 next_log = calc_log_samples();
125                 if (!next_log)
126                         next_log = DISK_UTIL_MSEC;
127
128                 if (steadystate_enabled) {
129                         since_ss = mtime_since(&last_ss, &now);
130                         if (since_ss >= STEADYSTATE_MSEC || STEADYSTATE_MSEC - since_ss < 10) {
131                                 steadystate_check();
132                                 timeval_add_msec(&last_ss, since_ss);
133                                 if (since_ss > STEADYSTATE_MSEC)
134                                         next_ss = STEADYSTATE_MSEC - (since_ss - STEADYSTATE_MSEC);
135                                 else
136                                         next_ss = STEADYSTATE_MSEC;
137                         }
138                         else
139                                 next_ss = STEADYSTATE_MSEC - since_ss;
140                 }
141
142                 msec_to_next_event = min(min(next_log, msec_to_next_event), next_ss);
143                 dprint(FD_HELPERTHREAD, "since_ss: %llu, next_ss: %u, next_log: %u, msec_to_next_event: %u\n", (unsigned long long)since_ss, next_ss, next_log, msec_to_next_event);
144
145                 if (!is_backend)
146                         print_thread_status();
147         }
148
149         fio_writeout_logs(false);
150
151         sk_out_drop();
152         return NULL;
153 }
154
155 int helper_thread_create(struct fio_mutex *startup_mutex, struct sk_out *sk_out)
156 {
157         struct helper_data *hd;
158         int ret;
159
160         hd = smalloc(sizeof(*hd));
161
162         setup_disk_util();
163         steadystate_setup();
164
165         hd->sk_out = sk_out;
166
167         ret = mutex_cond_init_pshared(&hd->lock, &hd->cond);
168         if (ret)
169                 return 1;
170
171         hd->startup_mutex = startup_mutex;
172
173         ret = pthread_create(&hd->thread, NULL, helper_thread_main, hd);
174         if (ret) {
175                 log_err("Can't create helper thread: %s\n", strerror(ret));
176                 return 1;
177         }
178
179         helper_data = hd;
180
181         dprint(FD_MUTEX, "wait on startup_mutex\n");
182         fio_mutex_down(startup_mutex);
183         dprint(FD_MUTEX, "done waiting on startup_mutex\n");
184         return 0;
185 }