rust: qom: wrap Object with Opaque<>

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2025-02-14 12:09:53 +01:00
parent 9c9a6a889c
commit 7fb4a99df1
4 changed files with 26 additions and 20 deletions

View file

@ -46,9 +46,6 @@ unsafe impl Sync for MemoryRegion {}
unsafe impl Send for ObjectClass {}
unsafe impl Sync for ObjectClass {}
unsafe impl Send for Object {}
unsafe impl Sync for Object {}
unsafe impl Send for SysBusDevice {}
unsafe impl Sync for SysBusDevice {}

View file

@ -157,7 +157,7 @@ impl MemoryRegion {
let cstr = CString::new(name).unwrap();
memory_region_init_io(
slot,
owner.cast::<Object>(),
owner.cast::<bindings::Object>(),
ops,
owner.cast::<c_void>(),
cstr.as_ptr(),

View file

@ -52,7 +52,7 @@ pub trait ResettablePhasesImpl {
/// 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_resettable_enter_fn<T: ResettablePhasesImpl>(
obj: *mut Object,
obj: *mut bindings::Object,
typ: ResetType,
) {
let state = NonNull::new(obj).unwrap().cast::<T>();
@ -65,7 +65,7 @@ unsafe extern "C" fn rust_resettable_enter_fn<T: ResettablePhasesImpl>(
/// 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_resettable_hold_fn<T: ResettablePhasesImpl>(
obj: *mut Object,
obj: *mut bindings::Object,
typ: ResetType,
) {
let state = NonNull::new(obj).unwrap().cast::<T>();
@ -78,7 +78,7 @@ unsafe extern "C" fn rust_resettable_hold_fn<T: ResettablePhasesImpl>(
/// 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_resettable_exit_fn<T: ResettablePhasesImpl>(
obj: *mut Object,
obj: *mut bindings::Object,
typ: ResetType,
) {
let state = NonNull::new(obj).unwrap().cast::<T>();

View file

@ -101,16 +101,24 @@ use std::{
ptr::NonNull,
};
pub use bindings::{Object, ObjectClass};
pub use bindings::ObjectClass;
use crate::{
bindings::{
self, object_class_dynamic_cast, object_dynamic_cast, object_get_class,
object_get_typename, object_new, object_ref, object_unref, TypeInfo,
},
cell::bql_locked,
cell::{bql_locked, Opaque},
};
/// A safe wrapper around [`bindings::Object`].
#[repr(transparent)]
#[derive(Debug, qemu_api_macros::Wrapper)]
pub struct Object(Opaque<bindings::Object>);
unsafe impl Send for Object {}
unsafe impl Sync for Object {}
/// Marker trait: `Self` can be statically upcasted to `P` (i.e. `P` is a direct
/// or indirect parent of `Self`).
///
@ -199,7 +207,7 @@ impl<T: fmt::Display + ObjectType> fmt::Display for ParentField<T> {
}
}
unsafe extern "C" fn rust_instance_init<T: ObjectImpl>(obj: *mut Object) {
unsafe extern "C" fn rust_instance_init<T: ObjectImpl>(obj: *mut bindings::Object) {
let mut state = NonNull::new(obj).unwrap().cast::<T>();
// SAFETY: obj is an instance of T, since rust_instance_init<T>
// is called from QOM core as the instance_init function
@ -209,7 +217,7 @@ unsafe extern "C" fn rust_instance_init<T: ObjectImpl>(obj: *mut Object) {
}
}
unsafe extern "C" fn rust_instance_post_init<T: ObjectImpl>(obj: *mut Object) {
unsafe extern "C" fn rust_instance_post_init<T: ObjectImpl>(obj: *mut bindings::Object) {
let state = NonNull::new(obj).unwrap().cast::<T>();
// SAFETY: obj is an instance of T, since rust_instance_post_init<T>
// is called from QOM core as the instance_post_init function
@ -230,7 +238,7 @@ unsafe extern "C" fn rust_class_init<T: ObjectType + ObjectImpl>(
<T as ObjectImpl>::CLASS_INIT(unsafe { klass.as_mut() })
}
unsafe extern "C" fn drop_object<T: ObjectImpl>(obj: *mut Object) {
unsafe extern "C" fn drop_object<T: ObjectImpl>(obj: *mut bindings::Object) {
// SAFETY: obj is an instance of T, since drop_object<T> is called
// from the QOM core function object_deinit() as the instance_finalize
// function for class T. Note that while object_deinit() will drop the
@ -280,14 +288,14 @@ pub unsafe trait ObjectType: Sized {
/// Return the receiver as an Object. This is always safe, even
/// if this type represents an interface.
fn as_object(&self) -> &Object {
unsafe { &*self.as_object_ptr() }
unsafe { &*self.as_ptr().cast() }
}
/// Return the receiver as a const raw pointer to Object.
/// This is preferrable to `as_object_mut_ptr()` if a C
/// function only needs a `const Object *`.
fn as_object_ptr(&self) -> *const Object {
self.as_ptr().cast()
fn as_object_ptr(&self) -> *const bindings::Object {
self.as_object().as_ptr()
}
/// Return the receiver as a mutable raw pointer to Object.
@ -297,8 +305,8 @@ pub unsafe trait ObjectType: Sized {
/// This cast is always safe, but because the result is mutable
/// and the incoming reference is not, this should only be used
/// for calls to C functions, and only if needed.
unsafe fn as_object_mut_ptr(&self) -> *mut Object {
self.as_object_ptr() as *mut _
unsafe fn as_object_mut_ptr(&self) -> *mut bindings::Object {
self.as_object().as_mut_ptr()
}
}
@ -621,7 +629,7 @@ pub trait ObjectImpl: ObjectType + IsA<Object> {
/// 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 extern "C" fn rust_unparent_fn<T: ObjectImpl>(dev: *mut bindings::Object) {
let state = NonNull::new(dev).unwrap().cast::<T>();
T::UNPARENT.unwrap()(unsafe { state.as_ref() });
}
@ -796,8 +804,9 @@ pub trait ObjectClassMethods: IsA<Object> {
// SAFETY: the object created by object_new is allocated on
// the heap and has a reference count of 1
unsafe {
let obj = &*object_new(Self::TYPE_NAME.as_ptr());
Owned::from_raw(obj.unsafe_cast::<Self>())
let raw_obj = object_new(Self::TYPE_NAME.as_ptr());
let obj = Object::from_raw(raw_obj).unsafe_cast::<Self>();
Owned::from_raw(obj)
}
}
}