Skip to content

Commit

Permalink
docs/devel: introduce some key concepts for QOM development
Browse files Browse the repository at this point in the history
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

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20230630180423.558337-28-alex.bennee@linaro.org>
  • Loading branch information
stsquad committed Jul 3, 2023
1 parent da966a8 commit 4339840
Showing 1 changed file with 52 additions and 6 deletions.
58 changes: 52 additions & 6 deletions docs/devel/qom.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
===============================================
Expand Down Expand Up @@ -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.

0 comments on commit 4339840

Please sign in to comment.