[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 26/41] rust: qom: add possibility of overriding unparent
From: |
Paolo Bonzini |
Subject: |
[PULL 26/41] rust: qom: add possibility of overriding unparent |
Date: |
Thu, 19 Dec 2024 09:32:13 +0100 |
Add a blanket definition of ClassInitImpl<ObjectClass> that thunks
ObjectImpl::UNPARENT and overrides it in ObjectClass if it is not
None.
ClassInitImpl<DeviceClass> can now call its superclass's ClassInitImpl,
so that the C and Rust hierarchies match more closely.
This is mostly done as an example of implementing the metaclass
hierarchy under ClassInitImpl.
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
rust/qemu-api/src/definitions.rs | 44 ++++++++++++++++++++++++++++---
rust/qemu-api/src/device_class.rs | 6 +++--
2 files changed, 45 insertions(+), 5 deletions(-)
diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/definitions.rs
index 13f8f6fd2a9..a2481c1fe70 100644
--- a/rust/qemu-api/src/definitions.rs
+++ b/rust/qemu-api/src/definitions.rs
@@ -6,7 +6,7 @@
use std::{ffi::CStr, os::raw::c_void};
-use crate::bindings::{Object, ObjectClass, TypeInfo};
+use crate::bindings::{self, Object, ObjectClass, TypeInfo};
unsafe extern "C" fn rust_instance_init<T: ObjectImpl>(obj: *mut Object) {
// SAFETY: obj is an instance of T, since rust_instance_init<T>
@@ -121,6 +121,9 @@ pub trait ObjectImpl: ObjectType +
ClassInitImpl<Self::Class> {
class_data: core::ptr::null_mut(),
interfaces: core::ptr::null_mut(),
};
+
+ // methods on ObjectClass
+ const UNPARENT: Option<fn(&Self)> = None;
}
/// Internal trait used to automatically fill in a class struct.
@@ -134,7 +137,8 @@ pub trait ObjectImpl: ObjectType +
ClassInitImpl<Self::Class> {
///
/// Each struct will implement this trait with `T` equal to each
/// superclass. For example, a device should implement at least
-/// `ClassInitImpl<`[`DeviceClass`](crate::bindings::DeviceClass)`>`.
+/// `ClassInitImpl<`[`DeviceClass`](crate::bindings::DeviceClass)`>` and
+/// `ClassInitImpl<`[`ObjectClass`](crate::bindings::ObjectClass)`>`.
/// Such implementations are made in one of two ways.
///
/// For most superclasses, `ClassInitImpl` is provided by the `qemu-api`
@@ -147,9 +151,13 @@ pub trait ObjectImpl: ObjectType +
ClassInitImpl<Self::Class> {
/// ```ignore
/// impl<T> ClassInitImpl<DeviceClass> for T
/// where
-/// T: DeviceImpl,
+/// T: ClassInitImpl<ObjectClass> + DeviceImpl,
/// ```
///
+/// The bound on `ClassInitImpl<ObjectClass>` is needed so that,
+/// after initializing the `DeviceClass` part of the class struct,
+/// the parent [`ObjectClass`] is initialized as well.
+///
/// The other case is when manual implementation of the trait is needed.
/// This covers the following cases:
///
@@ -235,3 +243,33 @@ extern "C" fn ctor_fn() {
}
};
}
+
+/// # Safety
+///
+/// We expect the FFI user of this function to pass a valid pointer that
+/// can be downcasted to type `T`. We also expect the device is
+/// readable/writeable from one thread at any time.
+unsafe extern "C" fn rust_unparent_fn<T: ObjectImpl>(dev: *mut Object) {
+ unsafe {
+ assert!(!dev.is_null());
+ let state = core::ptr::NonNull::new_unchecked(dev.cast::<T>());
+ T::UNPARENT.unwrap()(state.as_ref());
+ }
+}
+
+impl<T> ClassInitImpl<ObjectClass> for T
+where
+ T: ObjectImpl,
+{
+ fn class_init(oc: &mut ObjectClass) {
+ if <T as ObjectImpl>::UNPARENT.is_some() {
+ oc.unparent = Some(rust_unparent_fn::<T>);
+ }
+ }
+}
+
+unsafe impl ObjectType for Object {
+ type Class = ObjectClass;
+ const TYPE_NAME: &'static CStr =
+ unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_OBJECT) };
+}
diff --git a/rust/qemu-api/src/device_class.rs
b/rust/qemu-api/src/device_class.rs
index dcec5488291..a9965d1f123 100644
--- a/rust/qemu-api/src/device_class.rs
+++ b/rust/qemu-api/src/device_class.rs
@@ -5,7 +5,7 @@
use std::ffi::CStr;
use crate::{
- bindings::{self, DeviceClass, DeviceState, Error, Property,
VMStateDescription},
+ bindings::{self, DeviceClass, DeviceState, Error, ObjectClass, Property,
VMStateDescription},
definitions::ClassInitImpl,
prelude::*,
};
@@ -68,7 +68,7 @@ fn vmsd() -> Option<&'static VMStateDescription> {
impl<T> ClassInitImpl<DeviceClass> for T
where
- T: DeviceImpl,
+ T: ClassInitImpl<ObjectClass> + DeviceImpl,
{
fn class_init(dc: &mut DeviceClass) {
if <T as DeviceImpl>::REALIZE.is_some() {
@@ -88,6 +88,8 @@ fn class_init(dc: &mut DeviceClass) {
bindings::device_class_set_props_n(dc, prop.as_ptr(),
prop.len());
}
}
+
+ <T as ClassInitImpl<ObjectClass>>::class_init(&mut dc.parent_class);
}
}
--
2.47.1
- [PULL 14/41] migration: Use device_class_set_props_n, (continued)
- [PULL 14/41] migration: Use device_class_set_props_n, Paolo Bonzini, 2024/12/19
- [PULL 16/41] hw/arm/armsse: Use device_class_set_props_n, Paolo Bonzini, 2024/12/19
- [PULL 17/41] rust/qemu-api: Use device_class_set_props_n, Paolo Bonzini, 2024/12/19
- [PULL 18/41] hw/core: Replace device_class_set_props with a macro, Paolo Bonzini, 2024/12/19
- [PULL 19/41] target/riscv: Do not abuse DEFINE_PROP_END_OF_LIST, Paolo Bonzini, 2024/12/19
- [PULL 22/41] hw/core/qdev-properties: Constify Property argument to object_field_prop_ptr, Paolo Bonzini, 2024/12/19
- [PULL 21/41] include/hw/qdev-properties: Shrink struct Property, Paolo Bonzini, 2024/12/19
- [PULL 23/41] hw/core/qdev-properties: Constify Property argument to PropertyInfo.print, Paolo Bonzini, 2024/12/19
- [PULL 24/41] Constify all opaque Property pointers, Paolo Bonzini, 2024/12/19
- [PULL 20/41] include/hw/qdev-properties: Remove DEFINE_PROP_END_OF_LIST, Paolo Bonzini, 2024/12/19
- [PULL 26/41] rust: qom: add possibility of overriding unparent,
Paolo Bonzini <=
- [PULL 25/41] rust: qom: put class_init together from multiple ClassInitImpl<>, Paolo Bonzini, 2024/12/19
- [PULL 27/41] rust: rename qemu-api modules to follow C code a bit more, Paolo Bonzini, 2024/12/19
- [PULL 28/41] rust: re-export C types from qemu-api submodules, Paolo Bonzini, 2024/12/19
- [PULL 29/41] rust: tests: allow writing more than one test, Paolo Bonzini, 2024/12/19
- [PULL 30/41] rust: qom: add casting functionality, Paolo Bonzini, 2024/12/19
- [PULL 32/41] rust: qemu-api: add a module to wrap functions and zero-sized closures, Paolo Bonzini, 2024/12/19
- [PULL 33/41] kvm: consistently return 0/-errno from kvm_convert_memory, Paolo Bonzini, 2024/12/19
- [PULL 31/41] rust: qom: add initial subset of methods on Object, Paolo Bonzini, 2024/12/19
- [PULL 34/41] target/i386: Reset TSCs of parked vCPUs too on VM reset, Paolo Bonzini, 2024/12/19
- [PULL 35/41] rust: pl011: fix declaration of LineControl bits, Paolo Bonzini, 2024/12/19