On Thu, Mar 05, 2026 at 10:24:49PM +0800, Zhang Chen wrote:
> 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));

This is cleaner:

  source = aio_get_g_source(iothread->ctx);

That way iothread_get_aio_context() doesn't need a special case for
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));

Can this be done in iothread_ref()/iothread_unref()? That would ensure
that callers always increment the QOM reference count regardless of
whether the iothread_ref() or iothread_get_aio_context() API is used.

> +
> +        /* 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
> 

Attachment: signature.asc
Description: PGP signature

Reply via email to