diff mbox series

[v3,25/36] docs/devel: introduce some key concepts for QOM development

Message ID 20230627160943.2956928-26-alex.bennee@linaro.org
State Superseded
Headers show
Series maintainer omnibus: testing, fuzz, plugins, documentation, gdbstub (pre-PR) | expand

Commit Message

Alex Bennée June 27, 2023, 4:09 p.m. UTC
Using QOM correctly is increasingly important to maintaining a modern
code base. However the current documentation skips some important
concepts before launching into a simple example. Lets:

  - at least mention properties
  - mention TYPE_OBJECT and TYPE_DEVICE
  - talk about why we have realize/unrealize
  - mention the QOM tree
  - lightly re-arrange the order we mention things

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20230619171437.357374-6-alex.bennee@linaro.org>

---
v3
  - moved around as per Paolo's review
---
 docs/devel/qom.rst | 58 +++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 52 insertions(+), 6 deletions(-)

Comments

Philippe Mathieu-Daudé June 29, 2023, 1:41 p.m. UTC | #1
On 27/6/23 18:09, Alex Bennée wrote:
> Using QOM correctly is increasingly important to maintaining a modern
> code base. However the current documentation skips some important
> concepts before launching into a simple example. Lets:
> 
>    - at least mention properties
>    - mention TYPE_OBJECT and TYPE_DEVICE
>    - talk about why we have realize/unrealize
>    - mention the QOM tree
>    - lightly re-arrange the order we mention things
> 
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> Message-Id: <20230619171437.357374-6-alex.bennee@linaro.org>
> 
> ---
> v3
>    - moved around as per Paolo's review
> ---
>   docs/devel/qom.rst | 58 +++++++++++++++++++++++++++++++++++++++++-----
>   1 file changed, 52 insertions(+), 6 deletions(-)


> +Creating a QOM class
> +====================
> +
> +A simple minimal device implementation may look something like bellow:
>   
>   .. code-block:: c
>      :caption: Creating a minimal type
> @@ -48,6 +66,12 @@ In the above example, we create a simple type that is described by #TypeInfo.
>   #TypeInfo describes information about the type including what it inherits
>   from, the instance and class size, and constructor/destructor hooks.
>   
> +The TYPE_DEVICE class is the parent class for all modern devices
> +implemented in QEMU and adds some specific methods to handle QEMU
> +device model. This includes managing the lifetime of devices from
> +creation through to when they become visible to the guest and
> +eventually unrealized.

Good enough but we are mixing QOM vs QDev...

>   Alternatively several static types could be registered using helper macro
>   DEFINE_TYPES()


> +.. _device-life-cycle:
> +
> +Device Life-cycle
> +=================
> +
> +As class initialisation cannot fail devices have an two additional
> +methods to handle the creation of dynamic devices. The ``realize``
> +function is called with ``Error **`` pointer which should be set if
> +the device cannot complete its setup. Otherwise on successful
> +completion of the ``realize`` method the device object is added to the
> +QOM tree and made visible to the guest.
> +
> +The reverse function is ``unrealize`` and should be were clean-up
> +code lives to tidy up after the system is done with the device.

Worth mentioning hotplug devices must implement it?

> +All devices can be instantiated by C code, however only some can
> +created dynamically via the command line or monitor.
>   
> +Likewise only some can be unplugged after creation and need an
> +explicit ``unrealize`` implementation.

Ah, here we go.

> This is determined by the
> +``user_creatable`` variable in the root ``DeviceClass`` structure.
> +Devices can only be unplugged if their ``parent_bus`` has a registered
> +``HotplugHandler``.

TODO on top, mentions the reset() handlers are called after realize(),
and can be called multiple times.

>   API Reference
> --------------
> +=============
>   
>   See the :ref:`QOM API<qom-api>` and :ref:`QDEV API<qdev-api>`
>   documents for the complete API description.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Alex Bennée June 30, 2023, 8:03 a.m. UTC | #2
Philippe Mathieu-Daudé <philmd@linaro.org> writes:

> On 27/6/23 18:09, Alex Bennée wrote:
>> Using QOM correctly is increasingly important to maintaining a modern
>> code base. However the current documentation skips some important
>> concepts before launching into a simple example. Lets:
>>    - at least mention properties
>>    - mention TYPE_OBJECT and TYPE_DEVICE
>>    - talk about why we have realize/unrealize
>>    - mention the QOM tree
>>    - lightly re-arrange the order we mention things
>> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>> Message-Id: <20230619171437.357374-6-alex.bennee@linaro.org>
>> ---
>> v3
>>    - moved around as per Paolo's review
>> ---
>>   docs/devel/qom.rst | 58 +++++++++++++++++++++++++++++++++++++++++-----
>>   1 file changed, 52 insertions(+), 6 deletions(-)
>
>
>> +Creating a QOM class
>> +====================
>> +
>> +A simple minimal device implementation may look something like bellow:
>>     .. code-block:: c
>>      :caption: Creating a minimal type
>> @@ -48,6 +66,12 @@ In the above example, we create a simple type that is described by #TypeInfo.
>>   #TypeInfo describes information about the type including what it inherits
>>   from, the instance and class size, and constructor/destructor hooks.
>>   +The TYPE_DEVICE class is the parent class for all modern devices
>> +implemented in QEMU and adds some specific methods to handle QEMU
>> +device model. This includes managing the lifetime of devices from
>> +creation through to when they become visible to the guest and
>> +eventually unrealized.
>
> Good enough but we are mixing QOM vs QDev...

Yeah, but one relies on the other. From the point of view of someone
coming new to the code I think we do want to mention them both together.
Most people implementing QOM classes will be for devices I think.

Maybe we should enumerate all the types that have TYPE_OBJECT as their
parent?

>
>>   Alternatively several static types could be registered using helper macro
>>   DEFINE_TYPES()
>
>
>> +.. _device-life-cycle:
>> +
>> +Device Life-cycle
>> +=================
>> +
>> +As class initialisation cannot fail devices have an two additional
>> +methods to handle the creation of dynamic devices. The ``realize``
>> +function is called with ``Error **`` pointer which should be set if
>> +the device cannot complete its setup. Otherwise on successful
>> +completion of the ``realize`` method the device object is added to the
>> +QOM tree and made visible to the guest.
>> +
>> +The reverse function is ``unrealize`` and should be were clean-up
>> +code lives to tidy up after the system is done with the device.
>
> Worth mentioning hotplug devices must implement it?
>
>> +All devices can be instantiated by C code, however only some can
>> +created dynamically via the command line or monitor.
>>   +Likewise only some can be unplugged after creation and need an
>> +explicit ``unrealize`` implementation.
>
> Ah, here we go.
>
>> This is determined by the
>> +``user_creatable`` variable in the root ``DeviceClass`` structure.
>> +Devices can only be unplugged if their ``parent_bus`` has a registered
>> +``HotplugHandler``.
>
> TODO on top, mentions the reset() handlers are called after realize(),
> and can be called multiple times.

Where is this TODO? I'm wary of talking about reset too much as the old
reset handler is a deprecated API.

>
>>   API Reference
>> --------------
>> +=============
>>     See the :ref:`QOM API<qom-api>` and :ref:`QDEV API<qdev-api>`
>>   documents for the complete API description.
>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Paolo Bonzini June 30, 2023, 8:57 a.m. UTC | #3
Il gio 29 giu 2023, 15:41 Philippe Mathieu-Daudé <philmd@linaro.org> ha
scritto:

> > +The TYPE_DEVICE class is the parent class for all modern devices
> > +implemented in QEMU and adds some specific methods to handle QEMU
> > +device model. This includes managing the lifetime of devices from
> > +creation through to when they become visible to the guest and
> > +eventually unrealized.
>
> Good enough but we are mixing QOM vs QDev...
>

TYPE_DEVICE is mentioned here because it appears in the code (the part that
is not changing and thus is not included in the diff). It's not mixing QOM
with qdev.

Paolo

>   Alternatively several static types could be registered using helper
> macro
> >   DEFINE_TYPES()
>
>
> > +.. _device-life-cycle:
> > +
> > +Device Life-cycle
> > +=================
> > +
> > +As class initialisation cannot fail devices have an two additional
> > +methods to handle the creation of dynamic devices. The ``realize``
> > +function is called with ``Error **`` pointer which should be set if
> > +the device cannot complete its setup. Otherwise on successful
> > +completion of the ``realize`` method the device object is added to the
> > +QOM tree and made visible to the guest.
> > +
> > +The reverse function is ``unrealize`` and should be were clean-up
> > +code lives to tidy up after the system is done with the device.
>
> Worth mentioning hotplug devices must implement it?
>
> > +All devices can be instantiated by C code, however only some can
> > +created dynamically via the command line or monitor.
> >
> > +Likewise only some can be unplugged after creation and need an
> > +explicit ``unrealize`` implementation.
>
> Ah, here we go.
>
> > This is determined by the
> > +``user_creatable`` variable in the root ``DeviceClass`` structure.
> > +Devices can only be unplugged if their ``parent_bus`` has a registered
> > +``HotplugHandler``.
>
> TODO on top, mentions the reset() handlers are called after realize(),
> and can be called multiple times.
>
> >   API Reference
> > --------------
> > +=============
> >
> >   See the :ref:`QOM API<qom-api>` and :ref:`QDEV API<qdev-api>`
> >   documents for the complete API description.
>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>
>
diff mbox series

Patch

diff --git a/docs/devel/qom.rst b/docs/devel/qom.rst
index c342ce18e3..0b506426d7 100644
--- a/docs/devel/qom.rst
+++ b/docs/devel/qom.rst
@@ -13,6 +13,24 @@  features:
 - System for dynamically registering types
 - Support for single-inheritance of types
 - Multiple inheritance of stateless interfaces
+- Mapping internal members to publicly exposed properties
+
+The root object class is TYPE_OBJECT which provides for the basic
+object methods.
+
+The QOM tree
+============
+
+The QOM tree is a composition tree which represents all of the objects
+that make up a QEMU "machine". You can view this tree by running
+``info qom-tree`` in the :ref:`QEMU monitor`. It will contain both
+objects created by the machine itself as well those created due to
+user configuration.
+
+Creating a QOM class
+====================
+
+A simple minimal device implementation may look something like bellow:
 
 .. code-block:: c
    :caption: Creating a minimal type
@@ -48,6 +66,12 @@  In the above example, we create a simple type that is described by #TypeInfo.
 #TypeInfo describes information about the type including what it inherits
 from, the instance and class size, and constructor/destructor hooks.
 
+The TYPE_DEVICE class is the parent class for all modern devices
+implemented in QEMU and adds some specific methods to handle QEMU
+device model. This includes managing the lifetime of devices from
+creation through to when they become visible to the guest and
+eventually unrealized.
+
 Alternatively several static types could be registered using helper macro
 DEFINE_TYPES()
 
@@ -98,7 +122,7 @@  when the object is needed.
    module_obj(TYPE_MY_DEVICE);
 
 Class Initialization
-====================
+--------------------
 
 Before an object is initialized, the class for the object must be
 initialized.  There is only one class object for all instance objects
@@ -168,7 +192,7 @@  will also have a wrapper function to call it easily:
    }
 
 Interfaces
-==========
+----------
 
 Interfaces allow a limited form of multiple inheritance.  Instances are
 similar to normal types except for the fact that are only defined by
@@ -182,7 +206,7 @@  an argument to a method on its corresponding SomethingIfClass, or to
 dynamically cast it to an object that implements the interface.
 
 Methods
-=======
+-------
 
 A *method* is a function within the namespace scope of
 a class. It usually operates on the object instance by passing it as a
@@ -275,8 +299,8 @@  Alternatively, object_class_by_name() can be used to obtain the class and
 its non-overridden methods for a specific type. This would correspond to
 ``MyClass::method(...)`` in C++.
 
-The first example of such a QOM method was #CPUClass.reset,
-another example is #DeviceClass.realize.
+One example of such methods is ``DeviceClass.reset``. More examples
+can be found at :ref:`device-life-cycle`.
 
 Standard type declaration and definition macros
 ===============================================
@@ -382,10 +406,32 @@  OBJECT_DEFINE_ABSTRACT_TYPE() macro can be used instead:
    OBJECT_DEFINE_ABSTRACT_TYPE(MyDevice, my_device,
                                MY_DEVICE, DEVICE)
 
+.. _device-life-cycle:
+
+Device Life-cycle
+=================
+
+As class initialisation cannot fail devices have an two additional
+methods to handle the creation of dynamic devices. The ``realize``
+function is called with ``Error **`` pointer which should be set if
+the device cannot complete its setup. Otherwise on successful
+completion of the ``realize`` method the device object is added to the
+QOM tree and made visible to the guest.
+
+The reverse function is ``unrealize`` and should be were clean-up
+code lives to tidy up after the system is done with the device.
+
+All devices can be instantiated by C code, however only some can
+created dynamically via the command line or monitor.
 
+Likewise only some can be unplugged after creation and need an
+explicit ``unrealize`` implementation. This is determined by the
+``user_creatable`` variable in the root ``DeviceClass`` structure.
+Devices can only be unplugged if their ``parent_bus`` has a registered
+``HotplugHandler``.
 
 API Reference
--------------
+=============
 
 See the :ref:`QOM API<qom-api>` and :ref:`QDEV API<qdev-api>`
 documents for the complete API description.