qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: sysbus_create_simple Vs qdev_create


From: Markus Armbruster
Subject: Re: sysbus_create_simple Vs qdev_create
Date: Tue, 28 Jul 2020 09:19:28 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux)

Paolo Bonzini <pbonzini@redhat.com> writes:

> On 21/07/20 08:00, Markus Armbruster wrote:
>>> They are already mirrored as links, and guess what's the link
>>> name: "child[...]".
>> You're right, except for the link name: it's parent_bus.
>
> There's links in both directions.
>
>> So the qtree is actually embedded in the QOM graph: it's the device and
>> bus nodes connected by the child edges from device to provided bus and
>> parent_bus link egdes from device to bus it's plugged into, except the
>> latter are backward rather than forward.
>> 
>> Strange: even bus-less devices have this parent_bus link, and its value
>> is "" (the underlying pointer is null, and null gets mapped to "", for
>> better or worse).
>> 
>> Should the property be limited to devices that actually have a parent
>> bus?
>
> Yes, it could be done.
>
>>>> I don't know why the rebase of qdev onto QOM was done that way.  Perhaps
>>>> Paolo remembers.
>>> I'm guessing this is because QOM parent/child relationships
>>> represent ownership, while there's no ownership relationship
>>> between buses and devices.
>>
>> Plausible.  I guess the separate qtree was kept even though it's
>> redundant with the QOM graph because switching its users to the QOM
>> graph would be work.
>
> No, it was kept because:
>
> 1) the QOM graph wasn't embedding the qdev tree at the time.  That was
> added later.
>
> 2) the composition tree generally mirrors things that are born and die
> at the same time, and creating children is generally reserved to the
> object itself.

Yes.  Notable exceptions: containers /machine/peripheral,
/machine/peripheral-anon, /machine/unattached.

>                 Children are usually embedded directly in a struct, for
> example.

We sometimes use object_new() + object_property_add_child() instead.
Extra indirection.  I guess we'd be better off without the extra
indirection most of the time.  Implementation detail.

We sometimes use object_new() without object_property_add_child(), and
have qdev_realize() put the device in the /machine/unattached orphanage.
Meh.  I guess the orphanage feature exists to make conversion to QOM
slightly easier.  Could we ban its use for new boards at least?

>           Instead, peripherals are not created by the bus, they are
> created by the device_add monitor command and the like.

Plugged devices (the ones created with -device / device_add) have
/machine/peripheral or /machine/peripheral-anon as QOM parent.

> 3) accessing the QOM graph is slow (it requires hash table lookups,
> string comparisons and all that), so the pointers that cache the
> parent-child links are needed for use in hot paths.

True, but only because QOM's design opts for generality, efficiency be
damned :)

The QOM graph's edges are properties.

The child edges form the QOM composition tree.  The property contains
the child in ObjectProperty member @opaque.  To go from parent to child,
you have to get the property by name (hash table lookup), then follow
@opaque.  Except that would be too simple (and way too efficient), so we
convert pointers to QOM path names and back with visitors for accessing
a single child, or iterate over all properties (hash table iteration)
for accessing all children.

There is also a pointer from child back to parent, which is not a
property.  That one is actually fast and easy to use from C.

The remaining QOM graph edges are link edges.  Compared to child edges,
there's a further indirection through the LinkProperty struct, and no
support for iterating over link edge targets.

This design supports adding arbitrary children and links at run time,
with the actual object none the wiser.

A less general and more efficient design would put pointers right into
the objects' structs, then wrap what we call class properties around the
pointers.  C code for specific objects could then simply follow the
pointers.  Generic code could still use properties.  If efficiency
matters there, we could avoid the detour through path names.

Properties backed by a (pointer-valued) struct member are less general,
of course: you can't add this kind of property without first adding the
struct member.  The property needs to be declared at compile time rather
than built at run time.

I never quite understood why we need to build properties at run time.
It's makes reasoning about properties harder, and introspection brittle.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]