qemu-devel
[Top][All Lists]
Advanced

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

Re: [PATCH 24/26] rust: qom: move device_id to PL011 class side


From: Paolo Bonzini
Subject: Re: [PATCH 24/26] rust: qom: move device_id to PL011 class side
Date: Wed, 18 Dec 2024 08:14:44 +0100



Il mer 18 dic 2024, 07:39 Zhao Liu <zhao1.liu@intel.com> ha scritto:
I supposed a case, where there is such a QOM (QEMU Object Model)
structure relationship:

* DummyState / DummyClass: defined in Rust side, and registered the
  TypeInfo by `Object` macro.

  - So its class_init will be called by C QOM code.

* DummyChildState / DummyChildClass: defined in Rust side as the
  child-object of DummyState, and registered the TypeInfo by `Object`
  macro. And suppose it can inherit the trait of DummyClass -
  ClassInitImpl<DummyClass> (but I found a gap here, as detailed later;
  I expect it should be able to inherit normally).

 - So its class_init will be called by C QOM code. In C code call chain,
   its parent's class_init should be called by C before its own
   class_init.
 - However, note that according to the Rust class initialization call
   chain, it should also call the parent's class_init within its own
   class_init.
 - :( the parent's class_init gets called twice.

No, I don't think so. You have the same thing already with PL011State/PL011Luminary.

There, you have

* object_class_init
* device_class_init
* sysbus_device_class_init
* <PL011State as ClassInitImpl<PL011Class>>::class_init
  * <PL011State as ClassInitImpl<SysBusDeviceClass>>::class_init
    * <PL011State as ClassInitImpl<DeviceClass>>::class_init
      * <PL011State as ClassInitImpl<ObjectClass>>::class_init
* <PL011Luminary as ClassInitImpl<PL011Class>>::class_init
  * <PL011Luminary as ClassInitImpl<SysBusDeviceClass>>::class_init
    * <PL011Luminary as ClassInitImpl<DeviceClass>>::class_init
      * <PL011Luminary as ClassInitImpl<ObjectClass>>::class_init

But note that these calls are all different and indeed the last three are empty (all vtable entries are None). This is like a C class_init implementation that does not set any of sdc, dc or oc.

Moving on to another topic, about the gap (or question :-)) where a
child class inherits the ClassInitImpl trait from the parent, please see
my test case example below: Doing something similar to SysBusDevice and
DeviceState using a generic T outside of the QOM library would violate
the orphan rule.

Ugh, you're right. Maybe ClassInitImpl should just be merged into ObjectImpl etc. as a default method implementation. I will check.

> > But, when there is deeper class inheritance, it seems impossible to
> > prevent class_init from being called both by the C side's QOM code and by
> > this kind of recursive case on the Rust side.
> >
>
> Note that here you have two parameters: what class is being filled (the
> argument C of ClassInitImpl<C>) *and* what type is being initialized
> (that's Self).
>
> The "recursion" is only on the argument C, and matches the way C code
> implements class_init.

For Rust side, PL011Class' class_init calls SysBusDeviceClass' class_init,
and SysBusDeviceClass will also call DeviceClass' class_init. So this is
also recursion, right?

No, Self is not PL011Class. Self is PL011State (or PL011Luminary/ and it always remains the same. What changes is *what part* of the class is overwritten, but the order of calls from qom/object.c follows the same logic in both C and Rust.

> Maybe the confusion is because I implemented class_init twice instead of
> using a separate trait "PL011Impl"?

Ah, yes! But I think the Rust call chain should not use class_init anymore
but should use a different method. This way, the original class_init would
only serve the C QOM. A separate trait might break the inheritance
relationship similar to ClassInitImpl.

Do you still think that this is the case? I will look into how to avoid the problem with the orphan rule, but otherwise I think things are fine.

Paolo 

reply via email to

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