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