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