Philippe Mathieu-Daudé <phi...@linaro.org> writes:

> +Markus
>
> On 24/5/25 13:55, Richard Henderson wrote:
>> On 5/15/25 14:20, Thomas Huth wrote:
>>> +static int machine_get_endianness(Object *obj, Error **errp G_GNUC_UNUSED)
>>> +{
>>> +    S3Adsp1800MachineState *ms = PETALOGIX_S3ADSP1800_MACHINE(obj);
>>> +    return ms->endianness;
>>> +}
>>> +
>>> +static void machine_set_endianness(Object *obj, int endianness, Error 
>>> **errp)
>>> +{
>>> +    S3Adsp1800MachineState *ms = PETALOGIX_S3ADSP1800_MACHINE(obj);
>>> +    ms->endianness = endianness;
>>> +}
>>> +
>>>   static void petalogix_s3adsp1800_machine_class_init(ObjectClass *oc,
>>>                                                       const void *data)
>>>   {
>>>       MachineClass *mc = MACHINE_CLASS(oc);
>>> +    ObjectProperty *prop;
>>>       mc->desc = "PetaLogix linux refdesign for xilinx Spartan 3ADSP1800";
>>>       mc->init = petalogix_s3adsp1800_init;
>>>       mc->is_default = true;
>>> +
>>> +    prop = object_class_property_add_enum(oc, "endianness", "EndianMode",
>>> +                                          &EndianMode_lookup,
>>> +                                          machine_get_endianness,
>>> +                                          machine_set_endianness);
>>> +    object_property_set_default_str(prop, TARGET_BIG_ENDIAN ? "big" : 
>>> "little");
>>> +    object_class_property_set_description(oc, "endianness",
>>> +            "Defines whether the machine runs in big or little endian 
>>> mode");
>> Better with Property?  You don't have to write get/set...
>>    static const Property props[] = {
>>      DEFINE_PROP_ENDIAN("endianness", S3Adsp1800MachineState, endianness,
>>                         TARGET_BIG_ENDIAN ? ENDIAN_MODE_BIG : 
>> ENDIAN_MODE_LITTLE),
>>    };
>>    device_class_set_props(dc, props);
>
> DEFINE_PROP_FOO() are restricted to QDev (DeviceClass). Here we have
> a MachineClass, which only inherits ObjectClass, not DeviceClass.
>
> Markus once explained me the difference between QDev properties
> and bare object ones; I asked why we couldn't make qdev properties
> generic to objects, but I don't remember the historical rationale.
> QDev predates QOM, QDev used static properties, QOM introduced
> dynamic ones? We definitively should document that...

Yes.

Qdev properties are defined in data at compile time, and are connected
to the device class.  Specifically, a DeviceClass has an array of
Property, where each element specifies a property of its DeviceState
instances.  The array never changes.

The DEFINE_PROP_FOO() macros expand into Property literals suitable for
the array.  Boilerplate is relatively light: no need to write setters or
getters unless you define a new FOO.

QOM properties are defined in code at runtime, and are connected to the
Object, i.e. the instance, not the class.  They should be created in
.instance_init(), but nothing prevents creation elsewhere.  Most of the
time, we create the exact same properties for all instances of an
ObjectClass, but not always.

Defining properties at runtime is more flexible than defining them in
data at compile time.  However:

* Static data is much easier to reason about than behavior of code.
  Qdev properties are statically known.  device_add FOO,help can
  reliably show them: it dumps the unchanging array.  QOM properties can
  be different each time you create an object.  device_add FOO,help
  needs to create a temporary instance, and dumps whatever properties
  this instance got.  The next instance may get different ones.

* The property descriptions are duplicated in every instance, which is a
  waste of space.  See "QOM class properties" below.

* The functions to create properties take getter and setter functions as
  arguments.  Functions you get to write basically for each property.
  Much more boilerplate than with qdev.

I challenged the need for this much flexibility at the time, without
success.  We actually use the flexibility only rarely.  I believe this
aspect of QOM's design was a mistake.

QOM actually has a second kind of property: QOM class properties are
also defined in code at runtime, but connected to the ObjectClass.  They
should be created in .class_init(), but nothing prevents creation
elsewhere.  Despite their name, they are properties of the instance,
just like ordinary QOM properties.  The difference is only the sharing.

Most properties should be class properties, but aren't.  This is because
class properties were added late, and are underdocumented.

Qdev is actually a leaky layer above QOM.  I became one when we rebased
it on top of QOM.

A qdev's .instance_init() iterates over the property array and adds a
QOM class property for each element[*].

This Property part of qdev isn't actually device-specific.  We could
lift it into Object.  But would that be an improvement?  I'm not sure;
QOM is confusing enough as it is.

>               We definitively should document that...

I know just enough about QOM to be dangerous :)



[*] It also adds a "legacy property", but I forgot what that is, and why
it exists.

Reply via email to