]> git.proxmox.com Git - mirror_qemu.git/blob - iothread.c
iothread: add I/O thread object
[mirror_qemu.git] / iothread.c
1 /*
2 * Event loop thread
3 *
4 * Copyright Red Hat Inc., 2013
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 "qom/object.h"
15 #include "qom/object_interfaces.h"
16 #include "qemu/module.h"
17 #include "qemu/thread.h"
18 #include "block/aio.h"
19 #include "sysemu/iothread.h"
20
21 #define IOTHREADS_PATH "/objects"
22
23 typedef ObjectClass IOThreadClass;
24 struct IOThread {
25 Object parent_obj;
26
27 QemuThread thread;
28 AioContext *ctx;
29 bool stopping;
30 };
31
32 #define IOTHREAD_GET_CLASS(obj) \
33 OBJECT_GET_CLASS(IOThreadClass, obj, TYPE_IOTHREAD)
34 #define IOTHREAD_CLASS(klass) \
35 OBJECT_CLASS_CHECK(IOThreadClass, klass, TYPE_IOTHREAD)
36
37 static void *iothread_run(void *opaque)
38 {
39 IOThread *iothread = opaque;
40
41 while (!iothread->stopping) {
42 aio_context_acquire(iothread->ctx);
43 while (!iothread->stopping && aio_poll(iothread->ctx, true)) {
44 /* Progress was made, keep going */
45 }
46 aio_context_release(iothread->ctx);
47 }
48 return NULL;
49 }
50
51 static void iothread_instance_finalize(Object *obj)
52 {
53 IOThread *iothread = IOTHREAD(obj);
54
55 iothread->stopping = true;
56 aio_notify(iothread->ctx);
57 qemu_thread_join(&iothread->thread);
58 aio_context_unref(iothread->ctx);
59 }
60
61 static void iothread_complete(UserCreatable *obj, Error **errp)
62 {
63 IOThread *iothread = IOTHREAD(obj);
64
65 iothread->stopping = false;
66 iothread->ctx = aio_context_new();
67
68 /* This assumes we are called from a thread with useful CPU affinity for us
69 * to inherit.
70 */
71 qemu_thread_create(&iothread->thread, "iothread", iothread_run,
72 iothread, QEMU_THREAD_JOINABLE);
73 }
74
75 static void iothread_class_init(ObjectClass *klass, void *class_data)
76 {
77 UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
78 ucc->complete = iothread_complete;
79 }
80
81 static const TypeInfo iothread_info = {
82 .name = TYPE_IOTHREAD,
83 .parent = TYPE_OBJECT,
84 .class_init = iothread_class_init,
85 .instance_size = sizeof(IOThread),
86 .instance_finalize = iothread_instance_finalize,
87 .interfaces = (InterfaceInfo[]) {
88 {TYPE_USER_CREATABLE},
89 {}
90 },
91 };
92
93 static void iothread_register_types(void)
94 {
95 type_register_static(&iothread_info);
96 }
97
98 type_init(iothread_register_types)
99
100 IOThread *iothread_find(const char *id)
101 {
102 Object *container = container_get(object_get_root(), IOTHREADS_PATH);
103 Object *child;
104
105 child = object_property_get_link(container, id, NULL);
106 if (!child) {
107 return NULL;
108 }
109 return (IOThread *)object_dynamic_cast(child, TYPE_IOTHREAD);
110 }
111
112 char *iothread_get_id(IOThread *iothread)
113 {
114 return object_get_canonical_path_component(OBJECT(iothread));
115 }
116
117 AioContext *iothread_get_aio_context(IOThread *iothread)
118 {
119 return iothread->ctx;
120 }