All of lore.kernel.org
 help / color / mirror / Atom feed
From: Zhao Liu <zhao1.liu@intel.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org
Subject: Re: [PATCH 02/10] rust: qom: add reference counting functionality
Date: Wed, 5 Feb 2025 16:28:15 +0800	[thread overview]
Message-ID: <Z6MhH0bLVRw8O/8c@intel.com> (raw)
In-Reply-To: <CABgObfZ1659K9TrAAa3HYfhr0vf31eveoN-=33rSmpJnLo1RKg@mail.gmail.com>

On Wed, Jan 29, 2025 at 11:03:31AM +0100, Paolo Bonzini wrote:
> Date: Wed, 29 Jan 2025 11:03:31 +0100
> From: Paolo Bonzini <pbonzini@redhat.com>
> Subject: Re: [PATCH 02/10] rust: qom: add reference counting functionality
> 
> On Sun, Jan 26, 2025 at 3:56 PM Zhao Liu <zhao1.liu@intel.com> wrote:
> >
> > Hi Paolo,
> >
> > On Fri, Jan 17, 2025 at 08:39:55PM +0100, Paolo Bonzini wrote:
> > > Date: Fri, 17 Jan 2025 20:39:55 +0100
> > > From: Paolo Bonzini <pbonzini@redhat.com>
> > > Subject: [PATCH 02/10] rust: qom: add reference counting functionality
> > > X-Mailer: git-send-email 2.47.1
> > >
> > > Add a smart pointer that allows to add and remove references from
> > > QOM objects.  It's important to note that while all QOM objects have a
> > > reference count, in practice not all of them have their lifetime guarded
> > > by it.
> >
> > About the background, I have a maybe common question...why Rust needs
> > extra reference count guarding?
> 
> Children properties are removed, and thus their reference is dropped,
> before instance_finalize() is called (see object_finalize() in
> qom/object.c). This is not valid in Rust, you need to keep the object
> alive until the last line of Rust code has run - which is after
> Drop::drop() has run.

I see, this is also a typical effort to eliminate unsafe crossing of FFI
boundaries.

> > Additionally, I felt that the ref count may be a bit confusing. After
> > creating Child<> property, the child object's ref count is sometimes 1,
> > and other times it's 2:
> >
> >  * With object_initialize_child(), child's ref count is 1.
> >
> >  * With object_property_add_child() (usually after a object_new() to
> >    create child first):
> >
> >    - sometimes user will call object_unref(), and then the ref count is 1.
> >      E.g., x86_cpu_apic_create() in target/i386/cpu-apic.c.
> >
> >    - sometimes no object_unref(), then ref count is 2.
> >      E.g., exynos4210_realize() in hw/arm/exynos4210.c, creats "cortex-a9".
> 
> In C, having a ref count of 2 is usually a latent memory leak (because
> most of the time there's not going to be an object_unref() in the
> instance_finalize() method). In this case the leak is latent, because
> TYPE_EXYNOS4210_SOC is not hot-unpluggable and thus will never really
> go away once realized.

Further, what about doing object_unref() in object_property_add_child()
or object_property_try_add_child()?

Then we can ensure the object will have ref count of 1 on the exit of
object_property_add_child() and people will no longer miss
object_unref().

Although, there are a few more devices involved to fix similar issues.

> In Rust, this class of leaks simply does not exist with the right API.
> ObjectMethods::property_add_child() could either:
> 
> - take an Owned<T> and consume it, thus always giving a ref count of 1
> on exit. If you want to keep the object you would have to clone it.
>
> - take "&'owner self, &'child T where 'owner: 'child", then you can
> pass an embedded object like object_initialize_child().
> 
> In the latter case however you *still* need to keep the reference
> count elevated until Drop runs. That is, unlike C, Rust code will
> always have a ref count of 2 for children. For this reason, instead of
> having a "T" in the struct you would have another wrapper---something
> like Child<'owner, T>. This wrapper cannot be cloned but it does an
> unref when dropped.

Thanks, the whole picture is nice.

> My expectation is that property_add_child() will be used exclusivel
> for the first case, i.e. it will take an Owned<T>. If you want to
> create a child property from an embedded object, something like
> object_initialize_child() can be used once pinned-init is used to
> rewrite how instance_init is used. It will look something like
> 
> pin_init! {
>   &this in MyClass {
>     ...,
>     iomem <- MemoryRegion::init_io(
>             this,
>             &MY_MR_OPS,
>             "memory-region-name",
>             0x1000,
>     ),
>     child_obj <- ChildClass::init().to_child(this, "prop-name")
>   }
> }
> 
> where to_child() wraps an "impl PinInit<T>" and turns it into an "impl
> PinInit<Child<'a, T>>". Or something like that. :)

Elegant code design, looking forward to pin_init.

> > From this description, I understand your goal is:
> >
> >  * For embedded child object, its lifetimer is managed by its parent
> >    object, through Child<> for the most cases.
> >
> >  * For non-embedded child - a pointer/reference in parent object, its
> >    lifetimer is managed by `Owned<>` (and with Child<>).
> >
> > Am I right?
> 
> Yes, you're right.
> 
> I am not sure if you meant Child<> as the QOM concept, or as a Rust
> struct. If the latter, you're really really right.
> 

Thank you :-) It seems virtio device will have an embedded case to adopt
Child<> struct (virtio_instance_init_common()).

Regards,
Zhao



  reply	other threads:[~2025-02-05  8:09 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-17 19:39 [RFC PATCH 00/10] rust: remaining part of qdev bindings Paolo Bonzini
2025-01-17 19:39 ` [PATCH 01/10] rust: qemu-api: add sub-subclass to the integration tests Paolo Bonzini
2025-01-20 16:40   ` Zhao Liu
2025-01-17 19:39 ` [PATCH 02/10] rust: qom: add reference counting functionality Paolo Bonzini
2025-01-26 15:15   ` Zhao Liu
2025-01-29 10:03     ` Paolo Bonzini
2025-02-05  8:28       ` Zhao Liu [this message]
2025-01-27  7:57   ` Zhao Liu
2025-01-29 10:16     ` Paolo Bonzini
2025-02-05  9:13       ` Zhao Liu
2025-02-05  9:10         ` Paolo Bonzini
2025-02-05  9:40           ` Zhao Liu
2025-02-06  3:26   ` Zhao Liu
2025-01-17 19:39 ` [PATCH 03/10] rust: qom: add object creation functionality Paolo Bonzini
2025-02-06  7:49   ` Zhao Liu
2025-02-06  7:39     ` Paolo Bonzini
2025-01-17 19:39 ` [PATCH 04/10] rust: callbacks: allow passing optional callbacks as () Paolo Bonzini
2025-01-27  8:41   ` Zhao Liu
2025-01-17 19:39 ` [PATCH 05/10] rust: qdev: add clock creation Paolo Bonzini
2025-02-06  8:15   ` Zhao Liu
2025-01-17 19:39 ` [PATCH 06/10] rust: qom: allow initializing interface vtables Paolo Bonzini
2025-01-27 10:33   ` Zhao Liu
2025-01-17 19:40 ` [PATCH 07/10] rust: qdev: make ObjectImpl a supertrait of DeviceImpl Paolo Bonzini
2025-01-27  9:10   ` Zhao Liu
2025-02-06  8:37   ` Philippe Mathieu-Daudé
2025-01-17 19:40 ` [PATCH 08/10] rust: qdev: switch from legacy reset to Resettable Paolo Bonzini
2025-01-27 10:31   ` Zhao Liu
2025-01-27 18:01     ` Paolo Bonzini
2025-01-28  9:25       ` Zhao Liu
2025-02-06  8:31   ` Zhao Liu
2025-01-17 19:40 ` [PATCH 09/10] rust: bindings: add Sync markers to types referred to by MemoryRegionOps Paolo Bonzini
2025-01-27 10:58   ` Zhao Liu
2025-01-17 19:40 ` [PATCH 10/10] rust: bindings for MemoryRegionOps Paolo Bonzini
2025-01-27 12:12   ` Zhao Liu
2025-01-27 18:11     ` Paolo Bonzini
2025-02-06  9:15       ` Zhao Liu
2025-02-06  9:15         ` Paolo Bonzini
2025-02-06  8:39   ` Philippe Mathieu-Daudé
2025-02-06  8:46     ` Paolo Bonzini
2025-02-06 10:02       ` Philippe Mathieu-Daudé
2025-02-06 10:19         ` Paolo Bonzini
2025-02-10 10:38           ` Philippe Mathieu-Daudé
2025-01-24  2:46 ` [RFC PATCH 00/10] rust: remaining part of qdev bindings Zhao Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Z6MhH0bLVRw8O/8c@intel.com \
    --to=zhao1.liu@intel.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-rust@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.