master
c 429 lines 12.6 KB
Raw
1 /*
2 * Event loop thread
3 *
4 * Copyright Red Hat Inc., 2013, 2020
5 *
6 * Authors:
7 * Stefan Hajnoczi <stefanha@redhat.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 *
12 */
13
14 #include "qemu/osdep.h"
15 #include "qom/object.h"
16 #include "qom/object_interfaces.h"
17 #include "qemu/module.h"
18 #include "qemu/aio.h"
19 #include "block/block.h"
20 #include "system/event-loop-base.h"
21 #include "system/iothread.h"
22 #include "qapi/error.h"
23 #include "qapi/qapi-commands-misc.h"
24 #include "qemu/error-report.h"
25 #include "qemu/rcu.h"
26 #include "qemu/main-loop.h"
27
28 static void *iothread_run(void *opaque)
29 {
30 IOThread *iothread = opaque;
31
32 rcu_register_thread();
33 /*
34 * g_main_context_push_thread_default() must be called before anything
35 * in this new thread uses glib.
36 */
37 g_main_context_push_thread_default(iothread->worker_context);
38 qemu_set_current_aio_context(iothread->ctx);
39 iothread->thread_id = qemu_get_thread_id();
40 qemu_sem_post(&iothread->init_done_sem);
41
42 while (iothread->running) {
43 /*
44 * Note: from functional-wise the g_main_loop_run() below can
45 * already cover the aio_poll() events, but we can't run the
46 * main loop unconditionally because explicit aio_poll() here
47 * is faster than g_main_loop_run() when we do not need the
48 * gcontext at all (e.g., pure block layer iothreads). In
49 * other words, when we want to run the gcontext with the
50 * iothread we need to pay some performance for functionality.
51 */
52 aio_poll(iothread->ctx, true);
53
54 /*
55 * We must check the running state again in case it was
56 * changed in previous aio_poll()
57 */
58 if (iothread->running && qatomic_read(&iothread->run_gcontext)) {
59 g_main_loop_run(iothread->main_loop);
60 }
61 }
62
63 g_main_context_pop_thread_default(iothread->worker_context);
64 rcu_unregister_thread();
65 return NULL;
66 }
67
68 /* Runs in iothread_run() thread */
69 static void iothread_stop_bh(void *opaque)
70 {
71 IOThread *iothread = opaque;
72
73 iothread->running = false; /* stop iothread_run() */
74
75 if (iothread->main_loop) {
76 g_main_loop_quit(iothread->main_loop);
77 }
78 }
79
80 void iothread_stop(IOThread *iothread)
81 {
82 if (!iothread->ctx || iothread->stopping) {
83 return;
84 }
85 iothread->stopping = true;
86 aio_bh_schedule_oneshot(iothread->ctx, iothread_stop_bh, iothread);
87 qemu_thread_join(&iothread->thread);
88 }
89
90 static void iothread_instance_init(Object *obj)
91 {
92 IOThread *iothread = IOTHREAD(obj);
93
94 iothread->poll_max_ns = IOTHREAD_POLL_MAX_NS_DEFAULT;
95 iothread->poll_grow = IOTHREAD_POLL_GROW_DEFAULT;
96 iothread->poll_shrink = IOTHREAD_POLL_SHRINK_DEFAULT;
97 iothread->poll_weight = IOTHREAD_POLL_WEIGHT_DEFAULT;
98
99 iothread->thread_id = -1;
100 qemu_sem_init(&iothread->init_done_sem, 0);
101 /* By default, we don't run gcontext */
102 qatomic_set(&iothread->run_gcontext, 0);
103 }
104
105 static void iothread_instance_finalize(Object *obj)
106 {
107 IOThread *iothread = IOTHREAD(obj);
108
109 iothread_stop(iothread);
110
111 /*
112 * Before glib2 2.33.10, there is a glib2 bug that GSource context
113 * pointer may not be cleared even if the context has already been
114 * destroyed (while it should). Here let's free the AIO context
115 * earlier to bypass that glib bug.
116 *
117 * We can remove this comment after the minimum supported glib2
118 * version boosts to 2.33.10. Before that, let's free the
119 * GSources first before destroying any GMainContext.
120 */
121 if (iothread->ctx) {
122 aio_context_unref(iothread->ctx);
123 iothread->ctx = NULL;
124 }
125 if (iothread->worker_context) {
126 g_main_context_unref(iothread->worker_context);
127 iothread->worker_context = NULL;
128 g_main_loop_unref(iothread->main_loop);
129 iothread->main_loop = NULL;
130 }
131 qemu_sem_destroy(&iothread->init_done_sem);
132 }
133
134 static void iothread_init_gcontext(IOThread *iothread, const char *thread_name)
135 {
136 GSource *source;
137 g_autofree char *name = g_strdup_printf("%s aio-context", thread_name);
138
139 iothread->worker_context = g_main_context_new();
140 source = aio_get_g_source(iothread_get_aio_context(iothread));
141 g_source_set_name(source, name);
142 g_source_attach(source, iothread->worker_context);
143 g_source_unref(source);
144 iothread->main_loop = g_main_loop_new(iothread->worker_context, TRUE);
145 }
146
147 static void iothread_set_aio_context_params(EventLoopBase *base, Error **errp)
148 {
149 ERRP_GUARD();
150 IOThread *iothread = IOTHREAD(base);
151
152 if (!iothread->ctx) {
153 return;
154 }
155
156 aio_context_set_poll_params(iothread->ctx,
157 iothread->poll_max_ns,
158 iothread->poll_grow,
159 iothread->poll_shrink,
160 iothread->poll_weight,
161 errp);
162 if (*errp) {
163 return;
164 }
165
166 aio_context_set_aio_params(iothread->ctx,
167 iothread->parent_obj.aio_max_batch);
168
169 aio_context_set_thread_pool_params(iothread->ctx, base->thread_pool_min,
170 base->thread_pool_max, errp);
171 }
172
173
174 static void iothread_init(EventLoopBase *base, Error **errp)
175 {
176 Error *local_error = NULL;
177 IOThread *iothread = IOTHREAD(base);
178 g_autofree char *thread_name = NULL;
179
180 iothread->stopping = false;
181 iothread->running = true;
182 iothread->ctx = aio_context_new(errp);
183 if (!iothread->ctx) {
184 return;
185 }
186
187 thread_name = g_strdup_printf("IO %s",
188 object_get_canonical_path_component(OBJECT(base)));
189
190 /*
191 * Init one GMainContext for the iothread unconditionally, even if
192 * it's not used
193 */
194 iothread_init_gcontext(iothread, thread_name);
195
196 iothread_set_aio_context_params(base, &local_error);
197 if (local_error) {
198 error_propagate(errp, local_error);
199 aio_context_unref(iothread->ctx);
200 iothread->ctx = NULL;
201 return;
202 }
203
204 /* This assumes we are called from a thread with useful CPU affinity for us
205 * to inherit.
206 */
207 qemu_thread_create(&iothread->thread, thread_name, iothread_run,
208 iothread, QEMU_THREAD_JOINABLE);
209
210 /* Wait for initialization to complete */
211 while (iothread->thread_id == -1) {
212 qemu_sem_wait(&iothread->init_done_sem);
213 }
214 }
215
216 typedef struct {
217 const char *name;
218 ptrdiff_t offset; /* field's byte offset in IOThread struct */
219 } IOThreadParamInfo;
220
221 static IOThreadParamInfo poll_max_ns_info = {
222 "poll-max-ns", offsetof(IOThread, poll_max_ns),
223 };
224 static IOThreadParamInfo poll_grow_info = {
225 "poll-grow", offsetof(IOThread, poll_grow),
226 };
227 static IOThreadParamInfo poll_shrink_info = {
228 "poll-shrink", offsetof(IOThread, poll_shrink),
229 };
230 static IOThreadParamInfo poll_weight_info = {
231 "poll-weight", offsetof(IOThread, poll_weight),
232 };
233
234 static void iothread_get_param(Object *obj, Visitor *v,
235 const char *name, IOThreadParamInfo *info, Error **errp)
236 {
237 IOThread *iothread = IOTHREAD(obj);
238 int64_t *field = (void *)iothread + info->offset;
239
240 visit_type_int64(v, name, field, errp);
241 }
242
243 static bool iothread_set_param(Object *obj, Visitor *v,
244 const char *name, IOThreadParamInfo *info, Error **errp)
245 {
246 IOThread *iothread = IOTHREAD(obj);
247 int64_t *field = (void *)iothread + info->offset;
248 int64_t value;
249
250 if (!visit_type_int64(v, name, &value, errp)) {
251 return false;
252 }
253
254 if (info->offset == offsetof(IOThread, poll_weight)) {
255 if (value < 0 || value > 63) {
256 error_setg(errp, "%s value must be in range [0, 63]",
257 info->name);
258 return false;
259 }
260 } else if (value < 0) {
261 error_setg(errp, "%s value must be in range [0, %" PRId64 "]",
262 info->name, INT64_MAX);
263 return false;
264 }
265
266 if (value == 0) {
267 if (info->offset == offsetof(IOThread, poll_grow)) {
268 *field = IOTHREAD_POLL_GROW_DEFAULT;
269 } else if (info->offset == offsetof(IOThread, poll_shrink)) {
270 *field = IOTHREAD_POLL_SHRINK_DEFAULT;
271 } else if (info->offset == offsetof(IOThread, poll_weight)) {
272 *field = IOTHREAD_POLL_WEIGHT_DEFAULT;
273 } else {
274 *field = value;
275 }
276 } else {
277 *field = value;
278 }
279
280 return true;
281 }
282
283 static void iothread_get_poll_param(Object *obj, Visitor *v,
284 const char *name, void *opaque, Error **errp)
285 {
286 IOThreadParamInfo *info = opaque;
287
288 iothread_get_param(obj, v, name, info, errp);
289 }
290
291 static void iothread_set_poll_param(Object *obj, Visitor *v,
292 const char *name, void *opaque, Error **errp)
293 {
294 IOThread *iothread = IOTHREAD(obj);
295 IOThreadParamInfo *info = opaque;
296
297 if (!iothread_set_param(obj, v, name, info, errp)) {
298 return;
299 }
300
301 if (iothread->ctx) {
302 aio_context_set_poll_params(iothread->ctx,
303 iothread->poll_max_ns,
304 iothread->poll_grow,
305 iothread->poll_shrink,
306 iothread->poll_weight,
307 errp);
308 }
309 }
310
311 static void iothread_class_init(ObjectClass *klass, const void *class_data)
312 {
313 EventLoopBaseClass *bc = EVENT_LOOP_BASE_CLASS(klass);
314
315 bc->init = iothread_init;
316 bc->update_params = iothread_set_aio_context_params;
317
318 object_class_property_add(klass, "poll-max-ns", "int",
319 iothread_get_poll_param,
320 iothread_set_poll_param,
321 NULL, &poll_max_ns_info);
322 object_class_property_add(klass, "poll-grow", "int",
323 iothread_get_poll_param,
324 iothread_set_poll_param,
325 NULL, &poll_grow_info);
326 object_class_property_add(klass, "poll-shrink", "int",
327 iothread_get_poll_param,
328 iothread_set_poll_param,
329 NULL, &poll_shrink_info);
330 object_class_property_add(klass, "poll-weight", "int",
331 iothread_get_poll_param,
332 iothread_set_poll_param,
333 NULL, &poll_weight_info);
334 }
335
336 static const TypeInfo iothread_info = {
337 .name = TYPE_IOTHREAD,
338 .parent = TYPE_EVENT_LOOP_BASE,
339 .class_init = iothread_class_init,
340 .instance_size = sizeof(IOThread),
341 .instance_init = iothread_instance_init,
342 .instance_finalize = iothread_instance_finalize,
343 };
344
345 static void iothread_register_types(void)
346 {
347 type_register_static(&iothread_info);
348 }
349
350 type_init(iothread_register_types)
351
352 char *iothread_get_id(IOThread *iothread)
353 {
354 return g_strdup(object_get_canonical_path_component(OBJECT(iothread)));
355 }
356
357 AioContext *iothread_get_aio_context(IOThread *iothread)
358 {
359 return iothread->ctx;
360 }
361
362 static int query_one_iothread(Object *object, void *opaque)
363 {
364 IOThreadInfoList ***tail = opaque;
365 IOThreadInfo *info;
366 IOThread *iothread;
367
368 iothread = (IOThread *)object_dynamic_cast(object, TYPE_IOTHREAD);
369 if (!iothread) {
370 return 0;
371 }
372
373 info = g_new0(IOThreadInfo, 1);
374 info->id = iothread_get_id(iothread);
375 info->thread_id = iothread->thread_id;
376 info->poll_max_ns = iothread->poll_max_ns;
377 info->poll_grow = iothread->poll_grow;
378 info->poll_shrink = iothread->poll_shrink;
379 info->poll_weight = iothread->poll_weight;
380 info->aio_max_batch = iothread->parent_obj.aio_max_batch;
381
382 QAPI_LIST_APPEND(*tail, info);
383 return 0;
384 }
385
386 IOThreadInfoList *qmp_query_iothreads(Error **errp)
387 {
388 IOThreadInfoList *head = NULL;
389 IOThreadInfoList **prev = &head;
390 Object *container = object_get_objects_root();
391
392 object_child_foreach(container, query_one_iothread, &prev);
393 return head;
394 }
395
396 GMainContext *iothread_get_g_main_context(IOThread *iothread)
397 {
398 qatomic_set(&iothread->run_gcontext, 1);
399 aio_notify(iothread->ctx);
400 return iothread->worker_context;
401 }
402
403 IOThread *iothread_create(const char *id, Error **errp)
404 {
405 Object *obj;
406
407 obj = object_new_with_props(TYPE_IOTHREAD,
408 object_get_internal_root(),
409 id, errp, NULL);
410
411 return IOTHREAD(obj);
412 }
413
414 void iothread_destroy(IOThread *iothread)
415 {
416 object_unparent(OBJECT(iothread));
417 }
418
419 /* Lookup IOThread by its id. Only finds user-created objects, not internal
420 * iothread_create() objects. */
421 IOThread *iothread_by_id(const char *id)
422 {
423 return IOTHREAD(object_resolve_path_type(id, TYPE_IOTHREAD, NULL));
424 }
425
426 bool qemu_in_iothread(void)
427 {
428 return qemu_get_current_aio_context() != qemu_get_aio_context();
429 }