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