]> git.proxmox.com Git - mirror_qemu.git/blob - iothread.c
iothread: stash thread ID away
[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 QemuMutex init_done_lock;
30 QemuCond init_done_cond; /* is thread initialization done? */
31 bool stopping;
32 int thread_id;
33 };
34
35 #define IOTHREAD_GET_CLASS(obj) \
36 OBJECT_GET_CLASS(IOThreadClass, obj, TYPE_IOTHREAD)
37 #define IOTHREAD_CLASS(klass) \
38 OBJECT_CLASS_CHECK(IOThreadClass, klass, TYPE_IOTHREAD)
39
40 static void *iothread_run(void *opaque)
41 {
42 IOThread *iothread = opaque;
43
44 qemu_mutex_lock(&iothread->init_done_lock);
45 iothread->thread_id = qemu_get_thread_id();
46 qemu_cond_signal(&iothread->init_done_cond);
47 qemu_mutex_unlock(&iothread->init_done_lock);
48
49 while (!iothread->stopping) {
50 aio_context_acquire(iothread->ctx);
51 while (!iothread->stopping && aio_poll(iothread->ctx, true)) {
52 /* Progress was made, keep going */
53 }
54 aio_context_release(iothread->ctx);
55 }
56 return NULL;
57 }
58
59 static void iothread_instance_finalize(Object *obj)
60 {
61 IOThread *iothread = IOTHREAD(obj);
62
63 iothread->stopping = true;
64 aio_notify(iothread->ctx);
65 qemu_thread_join(&iothread->thread);
66 qemu_cond_destroy(&iothread->init_done_cond);
67 qemu_mutex_destroy(&iothread->init_done_lock);
68 aio_context_unref(iothread->ctx);
69 }
70
71 static void iothread_complete(UserCreatable *obj, Error **errp)
72 {
73 IOThread *iothread = IOTHREAD(obj);
74
75 iothread->stopping = false;
76 iothread->ctx = aio_context_new();
77 iothread->thread_id = -1;
78
79 qemu_mutex_init(&iothread->init_done_lock);
80 qemu_cond_init(&iothread->init_done_cond);
81
82 /* This assumes we are called from a thread with useful CPU affinity for us
83 * to inherit.
84 */
85 qemu_thread_create(&iothread->thread, "iothread", iothread_run,
86 iothread, QEMU_THREAD_JOINABLE);
87
88 /* Wait for initialization to complete */
89 qemu_mutex_lock(&iothread->init_done_lock);
90 while (iothread->thread_id == -1) {
91 qemu_cond_wait(&iothread->init_done_cond,
92 &iothread->init_done_lock);
93 }
94 qemu_mutex_unlock(&iothread->init_done_lock);
95 }
96
97 static void iothread_class_init(ObjectClass *klass, void *class_data)
98 {
99 UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
100 ucc->complete = iothread_complete;
101 }
102
103 static const TypeInfo iothread_info = {
104 .name = TYPE_IOTHREAD,
105 .parent = TYPE_OBJECT,
106 .class_init = iothread_class_init,
107 .instance_size = sizeof(IOThread),
108 .instance_finalize = iothread_instance_finalize,
109 .interfaces = (InterfaceInfo[]) {
110 {TYPE_USER_CREATABLE},
111 {}
112 },
113 };
114
115 static void iothread_register_types(void)
116 {
117 type_register_static(&iothread_info);
118 }
119
120 type_init(iothread_register_types)
121
122 IOThread *iothread_find(const char *id)
123 {
124 Object *container = container_get(object_get_root(), IOTHREADS_PATH);
125 Object *child;
126
127 child = object_property_get_link(container, id, NULL);
128 if (!child) {
129 return NULL;
130 }
131 return (IOThread *)object_dynamic_cast(child, TYPE_IOTHREAD);
132 }
133
134 char *iothread_get_id(IOThread *iothread)
135 {
136 return object_get_canonical_path_component(OBJECT(iothread));
137 }
138
139 AioContext *iothread_get_aio_context(IOThread *iothread)
140 {
141 return iothread->ctx;
142 }