Introduce iothread_get_aio_context() (In this patch named "iothread_ref_and_get_aio_context" for build, will change the name in the last patch) with a 'holder' argument and its counterpart iothread_put_aio_context().
Previously, users of an IOThread's AioContext did not explicitly record their identity, making it difficult to debug which devices or subsystems were pinning an IOThread. This patch enhances the reference counting mechanism by: 1. Automatically incrementing the object reference count when a context is retrieved. 2. Tracking holders using iothread_ref() and iothread_unref(). In iothread_instance_finalize(), we now retrieve the source name from the GMainContext to correctly unref the initial internal holder. Signed-off-by: Zhang Chen <[email protected]> --- include/system/iothread.h | 4 ++++ iothread.c | 31 +++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/include/system/iothread.h b/include/system/iothread.h index b9207ad829..b483bbfab3 100644 --- a/include/system/iothread.h +++ b/include/system/iothread.h @@ -18,6 +18,7 @@ #include "qemu/thread.h" #include "qom/object.h" #include "system/event-loop-base.h" +#include "qapi/qapi-types-misc.h" #define TYPE_IOTHREAD "iothread" @@ -70,6 +71,9 @@ DECLARE_INSTANCE_CHECKER(IOThread, IOTHREAD, char *iothread_get_id(IOThread *iothread); IOThread *iothread_by_id(const char *id); AioContext *iothread_get_aio_context(IOThread *iothread); +AioContext *iothread_ref_and_get_aio_context(IOThread *iothread, + const IOThreadHolder *holder); +void iothread_put_aio_context(IOThread *iothread, const IOThreadHolder *holder); GMainContext *iothread_get_g_main_context(IOThread *iothread); /* diff --git a/iothread.c b/iothread.c index 3301b8d495..528002c34a 100644 --- a/iothread.c +++ b/iothread.c @@ -55,6 +55,12 @@ static void iothread_ref(IOThread *iothread, const IOThreadHolder *holder) } iothread->holders = g_list_prepend(iothread->holders, h); + + /* + * This guarantees that the IOThread and its AioContext remain alive + * as long as there is a holder. + */ + object_ref(OBJECT(iothread)); } static int iothread_holder_compare(gconstpointer a, gconstpointer b) @@ -109,6 +115,8 @@ static void iothread_unref(IOThread *iothread, const IOThreadHolder *holder) IOThreadHolder *h = (IOThreadHolder *)link->data; qapi_free_IOThreadHolder(h); iothread->holders = g_list_delete_link(iothread->holders, link); + + object_unref(OBJECT(iothread)); } static void *iothread_run(void *opaque) @@ -223,7 +231,7 @@ static void iothread_init_gcontext(IOThread *iothread, const char *thread_name) g_autofree char *name = g_strdup_printf("%s aio-context", thread_name); iothread->worker_context = g_main_context_new(); - source = aio_get_g_source(iothread_get_aio_context(iothread)); + source = aio_get_g_source(iothread->ctx); g_source_set_name(source, name); g_source_attach(source, iothread->worker_context); g_source_unref(source); @@ -442,17 +450,24 @@ char *iothread_get_id(IOThread *iothread) AioContext *iothread_get_aio_context(IOThread *iothread) { - /* Remove in next patch for build */ - IOThreadHolder holder = { - .type = IO_THREAD_HOLDER_KIND_QOM_OBJECT, - .u.qom_object.qom_path = (char *)"tmp_path", - }; - iothread_ref(iothread, &holder); - iothread_unref(iothread, &holder); + return iothread->ctx; +} + +AioContext *iothread_ref_and_get_aio_context(IOThread *iothread, + const IOThreadHolder *holder) +{ + /* Add IOThreadHolder to the list */ + iothread_ref(iothread, holder); return iothread->ctx; } +void iothread_put_aio_context(IOThread *iothread, const IOThreadHolder *holder) +{ + /* Delete IOThreadHolder from the list */ + iothread_unref(iothread, holder); +} + static int query_one_iothread(Object *object, void *opaque) { IOThreadInfoList ***tail = opaque; -- 2.49.0
