]> git.proxmox.com Git - mirror_qemu.git/blame - iothread.c
iothread: stash thread ID away
[mirror_qemu.git] / iothread.c
CommitLineData
be8d8537
SH
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
23typedef ObjectClass IOThreadClass;
24struct IOThread {
25 Object parent_obj;
26
27 QemuThread thread;
28 AioContext *ctx;
88eb7c29
SH
29 QemuMutex init_done_lock;
30 QemuCond init_done_cond; /* is thread initialization done? */
be8d8537 31 bool stopping;
88eb7c29 32 int thread_id;
be8d8537
SH
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
40static void *iothread_run(void *opaque)
41{
42 IOThread *iothread = opaque;
43
88eb7c29
SH
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
be8d8537
SH
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
59static 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);
88eb7c29
SH
66 qemu_cond_destroy(&iothread->init_done_cond);
67 qemu_mutex_destroy(&iothread->init_done_lock);
be8d8537
SH
68 aio_context_unref(iothread->ctx);
69}
70
71static void iothread_complete(UserCreatable *obj, Error **errp)
72{
73 IOThread *iothread = IOTHREAD(obj);
74
75 iothread->stopping = false;
76 iothread->ctx = aio_context_new();
88eb7c29
SH
77 iothread->thread_id = -1;
78
79 qemu_mutex_init(&iothread->init_done_lock);
80 qemu_cond_init(&iothread->init_done_cond);
be8d8537
SH
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);
88eb7c29
SH
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);
be8d8537
SH
95}
96
97static void iothread_class_init(ObjectClass *klass, void *class_data)
98{
99 UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
100 ucc->complete = iothread_complete;
101}
102
103static 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
115static void iothread_register_types(void)
116{
117 type_register_static(&iothread_info);
118}
119
120type_init(iothread_register_types)
121
122IOThread *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
134char *iothread_get_id(IOThread *iothread)
135{
136 return object_get_canonical_path_component(OBJECT(iothread));
137}
138
139AioContext *iothread_get_aio_context(IOThread *iothread)
140{
141 return iothread->ctx;
142}