]> git.proxmox.com Git - mirror_qemu.git/blame - iothread.c
dataplane: replace internal thread with IOThread
[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;
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
37static 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
51static 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
61static 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
75static void iothread_class_init(ObjectClass *klass, void *class_data)
76{
77 UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
78 ucc->complete = iothread_complete;
79}
80
81static 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
93static void iothread_register_types(void)
94{
95 type_register_static(&iothread_info);
96}
97
98type_init(iothread_register_types)
99
100IOThread *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
112char *iothread_get_id(IOThread *iothread)
113{
114 return object_get_canonical_path_component(OBJECT(iothread));
115}
116
117AioContext *iothread_get_aio_context(IOThread *iothread)
118{
119 return iothread->ctx;
120}