Re: [PATCH V11 03/15] iothread: track users with holder name

Zhang Chen <[email protected]>
Newsgroups org.nongnu.qemu-devel
Message-ID <CAK3tnvJL0nJbH0erBf3UFc=ZAoBGGAEkeo3fmLPpZOXOpo+UXg@mail.gmail.com>
On Wed, Aug 12, 2026 at 3:19 AM Stefan Hajnoczi <[email protected]> wrote:
>
> On Tue, Aug 11, 2026 at 04:51:55PM +0800, Zhang Chen wrote:
> > On Fri, Aug 7, 2026 at 9:41 PM Markus Armbruster <[email protected]> wrote:
> > >
> > > Zhang Chen <[email protected]> writes:
> > >
> > > > Introduce iothread_ref_and_get_aio_context() with a holder argument
> > > > and its counterpart iothread_put_aio_context().
> > > >
> > > > Previously, users of an IOThread AioContext did not explicitly record
> > > > their identity, making it difficult to debug which devices or
> > > > subsystems were pinning an IOThread.
> > > >
> > > > Registering a holder takes an IOThread object reference so that the
> > > > IOThread and its AioContext stay alive until the matching put
> > > > operation. Document the ownership and BQL requirements.
> > > >
> > > > Signed-off-by: Zhang Chen <[email protected]>
> > > > ---
> > > >  include/system/iothread.h | 21 +++++++++++++++++++++
> > > >  iothread.c                | 23 ++++++++++++++++++++++-
> > > >  2 files changed, 43 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/include/system/iothread.h b/include/system/iothread.h
> > > > index b8aeb32b0e..b6664e7a38 100644
> > > > --- a/include/system/iothread.h
> > > > +++ b/include/system/iothread.h
> > > > @@ -67,6 +67,27 @@ 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);
> > > > +
> > > > +/*
> > > > + * Register @holder and return @iothread's AioContext.  The holder is copied,
> > > > + * and a reference is taken on @iothread so that both the IOThread and its
> > > > + * AioContext remain alive.
> > > > + *
> > > > + * The caller must eventually call iothread_put_aio_context() with an
> > > > + * equivalent holder.  This function is not thread-safe and must be called
> > > > + * under the Big QEMU Lock (BQL).
> > > > + */
> > > > +AioContext *iothread_ref_and_get_aio_context(IOThread *iothread,
> > > > +                                             const IOThreadHolder *holder);
> > > > +
> > > > +/*
> > > > + * Unregister @holder and release the corresponding reference on @iothread.
> > > > + * Calling this function without a matching
> > > > + * iothread_ref_and_get_aio_context() call is a programming error.
> > > > + *
> > > > + * This function is not thread-safe and must be called under the BQL.
> > > > + */
> > > > +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 2a4c92e08b..0cc8344ee6 100644
> > > > --- a/iothread.c
> > > > +++ b/iothread.c
> > > > @@ -33,6 +33,11 @@ void iothread_ref(IOThread *iothread, const IOThreadHolder *holder)
> > > >      assert(holder);
> > > >
> > > >      QAPI_LIST_PREPEND(iothread->holders, QAPI_CLONE(IOThreadHolder, holder));
> > > > +    /*
> > > > +     * 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(const IOThreadHolder *holder_a,
> > > > @@ -78,6 +83,7 @@ void iothread_unref(IOThread *iothread, const IOThreadHolder *holder)
> > > >              *prev = curr->next;
> > > >              curr->next = NULL;
> > > >              qapi_free_IOThreadHolderList(curr);
> > > > +            object_unref(OBJECT(iothread));
> > > >              return;
> > > >          }
> > > >          prev = &curr->next;
> > > > @@ -199,7 +205,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);
> > > > @@ -421,6 +427,21 @@ AioContext *iothread_get_aio_context(IOThread *iothread)
> > > >      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)
> > >
> > > Should we name this "unref" rather than "put"?  Perhaps Stefan has an
> > > opinion.
> >
> > It's OK for me. The original code was designed to match the
> > "iothread_get_aio_context",
> > If Stefan has no objection, I will change the name to
> > "iothread_unref_aio_context".
>
> iothread_unref_and_put_aio_context() would be consistent with
> iothread_ref_and_get_aio_context() :)

Sure, it looks much better.

Thanks
Chen

>
> Stefan
>
> >
> > Thanks
> >
> > Chen
> >
> > >
> > > > +{
> > > > +    /* Delete IOThreadHolder from the list */
> > > > +    iothread_unref(iothread, holder);
> > > > +}
> > > > +
> > > >  static int query_one_iothread(Object *object, void *opaque)
> > > >  {
> > > >      IOThreadInfoList ***tail = opaque;
> > >
> >
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.