Introduce iothread_get_aio_context() 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 by name 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 |  3 ++-
 iothread.c                | 28 ++++++++++++++++++++++++++--
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/include/system/iothread.h b/include/system/iothread.h
index 21a76bd70d..595abeefbe 100644
--- a/include/system/iothread.h
+++ b/include/system/iothread.h
@@ -47,7 +47,8 @@ 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_get_aio_context(IOThread *iothread, const char *holder);
+void iothread_put_aio_context(IOThread *iothread, const char *holder);
 GMainContext *iothread_get_g_main_context(IOThread *iothread);
 
 /*
diff --git a/iothread.c b/iothread.c
index 80a8cf4b32..da98fbb9ad 100644
--- a/iothread.c
+++ b/iothread.c
@@ -172,7 +172,8 @@ 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));
+    /* No need setup itself as the init holder */
+    source = aio_get_g_source(iothread_get_aio_context(iothread, NULL));
     g_source_set_name(source, name);
     g_source_attach(source, iothread->worker_context);
     g_source_unref(source);
@@ -362,11 +363,34 @@ char *iothread_get_id(IOThread *iothread)
     return g_strdup(object_get_canonical_path_component(OBJECT(iothread)));
 }
 
-AioContext *iothread_get_aio_context(IOThread *iothread)
+AioContext *iothread_get_aio_context(IOThread *iothread, const char *holder)
 {
+    /*
+     * In some cases, iothread user need the ctx to clearup other resource.
+     * When holder is empty, back to the legacy way.
+     */
+    if (holder) {
+        /*
+         * This guarantees that the IOThread and its AioContext remain alive
+         * as long as there is a holder.
+         */
+        object_ref(OBJECT(iothread));
+
+        /* Add holder device path to the list */
+        iothread_ref(iothread, holder);
+    }
+
     return iothread->ctx;
 }
 
+void iothread_put_aio_context(IOThread *iothread, const char *holder)
+{
+    object_unref(OBJECT(iothread));
+
+    /* Delete holder device path from the list */
+    iothread_unref(iothread, holder);
+}
+
 static int query_one_iothread(Object *object, void *opaque)
 {
     IOThreadInfoList ***tail = opaque;
-- 
2.49.0


Reply via email to