X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=iothread.c;h=bd7034481123849fa3bb0a2cbfca72a87a54bbd4;hb=f7e242d6a3323083d1a930b3f5f6511658cb1016;hp=f90bbc339ea7abaf32b34a02e5598e442ca59189;hpb=88eb7c29e4320597d2f246adf731f0aac97cfbcc;p=mirror_qemu.git diff --git a/iothread.c b/iothread.c index f90bbc339e..bd70344811 100644 --- a/iothread.c +++ b/iothread.c @@ -11,70 +11,92 @@ * */ +#include "qemu/osdep.h" #include "qom/object.h" #include "qom/object_interfaces.h" #include "qemu/module.h" -#include "qemu/thread.h" #include "block/aio.h" +#include "block/block.h" #include "sysemu/iothread.h" - -#define IOTHREADS_PATH "/objects" +#include "qmp-commands.h" +#include "qemu/error-report.h" +#include "qemu/rcu.h" +#include "qemu/main-loop.h" typedef ObjectClass IOThreadClass; -struct IOThread { - Object parent_obj; - - QemuThread thread; - AioContext *ctx; - QemuMutex init_done_lock; - QemuCond init_done_cond; /* is thread initialization done? */ - bool stopping; - int thread_id; -}; #define IOTHREAD_GET_CLASS(obj) \ OBJECT_GET_CLASS(IOThreadClass, obj, TYPE_IOTHREAD) #define IOTHREAD_CLASS(klass) \ OBJECT_CLASS_CHECK(IOThreadClass, klass, TYPE_IOTHREAD) +static __thread IOThread *my_iothread; + +AioContext *qemu_get_current_aio_context(void) +{ + return my_iothread ? my_iothread->ctx : qemu_get_aio_context(); +} + static void *iothread_run(void *opaque) { IOThread *iothread = opaque; + rcu_register_thread(); + + my_iothread = iothread; qemu_mutex_lock(&iothread->init_done_lock); iothread->thread_id = qemu_get_thread_id(); qemu_cond_signal(&iothread->init_done_cond); qemu_mutex_unlock(&iothread->init_done_lock); - while (!iothread->stopping) { - aio_context_acquire(iothread->ctx); - while (!iothread->stopping && aio_poll(iothread->ctx, true)) { - /* Progress was made, keep going */ - } - aio_context_release(iothread->ctx); + while (!atomic_read(&iothread->stopping)) { + aio_poll(iothread->ctx, true); } + + rcu_unregister_thread(); return NULL; } -static void iothread_instance_finalize(Object *obj) +static int iothread_stop(Object *object, void *opaque) { - IOThread *iothread = IOTHREAD(obj); + IOThread *iothread; + iothread = (IOThread *)object_dynamic_cast(object, TYPE_IOTHREAD); + if (!iothread || !iothread->ctx) { + return 0; + } iothread->stopping = true; aio_notify(iothread->ctx); qemu_thread_join(&iothread->thread); + return 0; +} + +static void iothread_instance_finalize(Object *obj) +{ + IOThread *iothread = IOTHREAD(obj); + + iothread_stop(obj, NULL); qemu_cond_destroy(&iothread->init_done_cond); qemu_mutex_destroy(&iothread->init_done_lock); + if (!iothread->ctx) { + return; + } aio_context_unref(iothread->ctx); } static void iothread_complete(UserCreatable *obj, Error **errp) { + Error *local_error = NULL; IOThread *iothread = IOTHREAD(obj); + char *name, *thread_name; iothread->stopping = false; - iothread->ctx = aio_context_new(); iothread->thread_id = -1; + iothread->ctx = aio_context_new(&local_error); + if (!iothread->ctx) { + error_propagate(errp, local_error); + return; + } qemu_mutex_init(&iothread->init_done_lock); qemu_cond_init(&iothread->init_done_cond); @@ -82,8 +104,12 @@ static void iothread_complete(UserCreatable *obj, Error **errp) /* This assumes we are called from a thread with useful CPU affinity for us * to inherit. */ - qemu_thread_create(&iothread->thread, "iothread", iothread_run, + name = object_get_canonical_path_component(OBJECT(obj)); + thread_name = g_strdup_printf("IO %s", name); + qemu_thread_create(&iothread->thread, thread_name, iothread_run, iothread, QEMU_THREAD_JOINABLE); + g_free(thread_name); + g_free(name); /* Wait for initialization to complete */ qemu_mutex_lock(&iothread->init_done_lock); @@ -119,24 +145,66 @@ static void iothread_register_types(void) type_init(iothread_register_types) -IOThread *iothread_find(const char *id) +char *iothread_get_id(IOThread *iothread) +{ + return object_get_canonical_path_component(OBJECT(iothread)); +} + +AioContext *iothread_get_aio_context(IOThread *iothread) { - Object *container = container_get(object_get_root(), IOTHREADS_PATH); - Object *child; + return iothread->ctx; +} - child = object_property_get_link(container, id, NULL); - if (!child) { - return NULL; +static int query_one_iothread(Object *object, void *opaque) +{ + IOThreadInfoList ***prev = opaque; + IOThreadInfoList *elem; + IOThreadInfo *info; + IOThread *iothread; + + iothread = (IOThread *)object_dynamic_cast(object, TYPE_IOTHREAD); + if (!iothread) { + return 0; } - return (IOThread *)object_dynamic_cast(child, TYPE_IOTHREAD); + + info = g_new0(IOThreadInfo, 1); + info->id = iothread_get_id(iothread); + info->thread_id = iothread->thread_id; + + elem = g_new0(IOThreadInfoList, 1); + elem->value = info; + elem->next = NULL; + + **prev = elem; + *prev = &elem->next; + return 0; } -char *iothread_get_id(IOThread *iothread) +IOThreadInfoList *qmp_query_iothreads(Error **errp) { - return object_get_canonical_path_component(OBJECT(iothread)); + IOThreadInfoList *head = NULL; + IOThreadInfoList **prev = &head; + Object *container = object_get_objects_root(); + + object_child_foreach(container, query_one_iothread, &prev); + return head; } -AioContext *iothread_get_aio_context(IOThread *iothread) +void iothread_stop_all(void) { - return iothread->ctx; + Object *container = object_get_objects_root(); + BlockDriverState *bs; + BdrvNextIterator it; + + for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) { + AioContext *ctx = bdrv_get_aio_context(bs); + if (ctx == qemu_get_aio_context()) { + continue; + } + aio_context_acquire(ctx); + bdrv_set_aio_context(bs, qemu_get_aio_context()); + aio_context_release(ctx); + } + + object_child_foreach(container, iothread_stop, NULL); }