+Bernhard

On 24/2/26 13:22, Mark Cave-Ayland wrote:
On 24/02/2026 11:10, Peter Maydell wrote:

On Tue, 24 Feb 2026 at 09:48, Daniel P. Berrangé <[email protected]> wrote:
IMHO, it is slightly more subtle - people believe they are already
adding children.

Consider this code.

     port92 = isa_create_simple(isa_bus, TYPE_PORT92);

my reading of that is that I'm creating a "port92" device that is a
child of "isa_bus". Why would I need to tell QEMU that it is a child
for a second time ?

If I trace calls through isa_create_simple I get to a call to:

    qdev_realize_and_unref(dev, parent, errp);

and once I again I'm left wondering why I would need to tell
QEMU 'dev' is a child of 'parent' a second time.

Of course I know the answer. We need to give a name for the
child and it isn't trivial to "do the right thing" to invent
an automatic name.

Still, overall I'm inclined to largely blame our API designs for
not guiding people into doing the right thing.


Picking another random unattached set of objects "smbus-eeprom"
I again find they've being created with qdev_realize_and_unref.

Pick another unattached device 'i8259_init_chip', and again
we end up calling into qdev_realize_and_unref()


It feels like qdev_realize_and_unref() is a common point of
blame in unattached devices. IMHO it ought to be taking a
"const char *name" parameter.

I think that is because this is the function that is used
in older code that predates the "everything should be in
the QOM tree" model. Newer code doesn't use it, I think;
and it's not surprising that old pre-QOM code doesn't do
anything to put objects into the QOM tree.

The two patterns are:

  dev = qdev_new(...);
  ...
  qdev_realize_and_unref(dev, bus, errp);

and

  object_initialize_child(...);
  ...
  qdev_realize(dev, bus, errp);

This also is somewhat tangled up with the question of whether you want:

  * call a function which allocates memory and initializes it
    with an object of this type
  * I have the memory here, init the object in-place

If we could come to a definite conclusion on what we want then
we would probably be in a better position to try to enforce it.

I recall a previous discussion where we said in-place allocation
does not scale with dynamic machines (data driven config), and IIRC
Bernhard said by switching to dynamic heap allocation we'd use more
QOM cast macros and lose compiler safety type checks. Can't find it
now in the archives.

We have some model declension where we allocate in-place $MAX members
and expose a QOM property to initialize up to that number (or worst,
de-initialize and unparent what is left!) in the DeviceRealize handler.
Not "in-place" could simplify this.

Exactly this! I think what tends to happen is that we get stuck in situations where someone suggests an improvement, but then we get hung up trying to work out the corner-cases where it doesn't work and then things don't progress.

The approach I believe we need to take is to work out what we want the API and QOM tree to look like first, and then work backwards from there.

I tend to be in agreement with Akihiko's argument that we want to deprecate in-place initialisation with object_initialize_child() and simply use refcounting everywhere because then we don't hit any lifcycle issues if something retains a reference to the internal object (memory regions!).

The questions I think we need to answer as a starting point:

   1. Which API shall we converge on: qdev or QOM? Can we come up with a
      code sample(s) showing what we want object/device initialisation to
      look lie? Longer term can we unify the QOM and qdev trees?

   2. Should we convert to use external object allocation with
      refcounting?

   3. How do we handle memory regions? With Akihiko's recent refcount
      fixes then Zoltan's memory region changes could work: I don't agree
      with the motivation of simplifying devices as I think it's i)
      subjective and ii) harder to debug if we lose the pointer to the
      memory region, but I can see how it fixes the RCU-thread doing an
      unref after the owner device has already been destroyed issue.

As several people have already pointed out in this thread, we do have a poor track record of API conversions but the introduction of memory regions shows how this can be done successfully.

Given that we already have multiple ways of doing the same thing, I tend to lean against not introducing yet-another-API unless we can come up with a long-term strategy for its use. In particular this causes problems in review where e.g. one reviewer may want to use QOM to setup a device whilst another may want to use qdev which is confusing for everyone, including the code submitter.

If we can at least get an answer to 1) then I'd be willing to have a go at writing some kind of specification document and put it out for feedback...


ATB,

Mark.




Reply via email to