On Mon, Mar 9, 2026 at 4:02 PM Stefan Hajnoczi <[email protected]> wrote:
>
> 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.

OK for here. But according to the following patch we try to use the
NULL to handle
problems that cannot be easily solved using ref/unref or get/put.
For example the patch 7 and 9.  We can discuss the details in that mail threads.

>
> >      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.

Sure, will move it into iothread_ref()/iothread_unref().

Thanks

Chen

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