Add a section to the QOM developer documentation explaining that
every object must have a composition-tree parent before use, how
to pick the parent (creator owns lifetime), how to name children,
the reference-count contract for parented creators, and where the
contract is enforced (device_set_realized, memory_region_do_init,
qdev_connect_gpio_out_named).

Assisted-by: Kiro
Signed-off-by: Alexander Graf <[email protected]>
---
 docs/devel/qom.rst | 96 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/docs/devel/qom.rst b/docs/devel/qom.rst
index 935bb1004a..ffcb3333b5 100644
--- a/docs/devel/qom.rst
+++ b/docs/devel/qom.rst
@@ -27,6 +27,102 @@ that make up a QEMU "machine". You can view this tree by 
running
 objects created by the machine itself as well those created due to
 user configuration.
 
+Composition-tree parenting contract
+====================================
+
+Every QOM object that participates in the running system must have a
+composition-tree parent before it is used.  The parent gives the object
+a stable, canonical path such as ``/machine/soc/uart[0]`` that is
+visible in ``info qom-tree`` and addressable via ``qom-get`` and
+``qom-set``.  Objects that reach ``realize`` (for devices), that are
+wired to another object (for IRQ lines), or that are given a name (for
+memory regions) without a parent are programming errors.
+
+Creating parented objects
+-------------------------
+
+The standard creation helpers all take the composition-tree parent and
+the child name as their first two arguments:
+
+.. code-block:: c
+
+    Object      *object_new_child(Object *parent, const char *id,
+                                  const char *typename);
+    DeviceState *qdev_new(Object *parent, const char *id,
+                          const char *typename);
+    DeviceState *sysbus_create_simple(Object *parent, const char *id,
+                                      const char *type, hwaddr, qemu_irq);
+    PCIDevice   *pci_new(Object *parent, const char *id, ...);
+    ISADevice   *isa_new(Object *parent, const char *id, ...);
+    /* i2c_slave_new(), ssi_create_peripheral(), usb_new(),
+       cpu_create() etc. follow the same pattern. */
+
+``object_new()`` remains available as the primitive allocator for
+transient introspection objects and for ``qdev_device_add()``, which
+parents the device via ``qdev_set_id()``.  All other callers should use
+one of the parented helpers above, or ``object_initialize_child()`` for
+objects that are embedded by value in the parent's instance struct.
+
+Choosing the parent
+-------------------
+
+The QOM parent is the object that owns the child's lifetime.  In
+practice this is the object whose code is creating the child:
+
+* Board code (``MachineClass.init``) parents onboard devices to the
+  machine: ``OBJECT(machine)``.
+* A composite device's ``DeviceClass.realize`` parents the sub-devices
+  it creates to itself: ``OBJECT(dev)``.
+* An SoC container likewise parents the devices it creates to the SoC
+  object.
+
+The bus a device is plugged into is *not* its composition-tree parent.
+A device may sit on a bus owned by ``B`` without being a child of
+``B``; the bus relationship is expressed through the ``parent_bus``
+link, not the ``child<>`` property.
+
+Choosing the child name
+-----------------------
+
+* A single instance takes a bare noun: ``"uart"``, ``"gic"``, ``"rtc"``.
+* A fixed number of identical instances take an explicit index:
+  ``"uart[0]"``, ``"uart[1]"``.
+* When the caller does not care about the index, ``"uart[*]"`` lets
+  QOM allocate the next free slot in the ``uart[]`` array.
+* Address-based names such as ``"eth@0x30000000"`` should only be used
+  when the address is genuinely the identity of the device.
+
+Child names share the parent's property namespace, so avoid names that
+collide with class-defined properties of the parent (in particular,
+machine class properties visible on ``/machine``).
+
+Reference-count contract
+------------------------
+
+``object_new_child()``, ``qdev_new()`` and the per-bus creators return
+with the object's single reference held by the parent's ``child<>``
+property.  The caller does *not* hold a reference of its own and must
+therefore pair creation with plain ``qdev_realize()`` rather than
+``qdev_realize_and_unref()``.  The object is finalized when the parent
+drops its ``child<>`` property, typically via ``object_unparent()``.
+
+Enforcement
+-----------
+
+The parenting contract is enforced at the points where an unparented
+object would first become visible or entangled with another object:
+
+* ``device_set_realized()`` fails with an ``Error`` if the device has
+  no composition-tree parent.
+* ``memory_region_do_init()`` asserts that a memory region given a
+  non-empty name also has an owner.
+* ``qdev_connect_gpio_out_named()`` asserts that the outbound IRQ
+  line being connected already has a composition-tree parent.
+
+There is no ``/machine/unattached`` fallback container; an object that
+would previously have landed there now triggers one of the errors
+above instead.
+
 Creating a QOM class
 ====================
 
-- 
2.47.1


Reply via email to