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 } 121