Implement `ForeignOwnable` for `Owned<T>`. This allows use of `Owned<T>` in places such as the `XArray`.
Note that `T` does not need to implement `ForeignOwnable` for `Owned<T>` to implement `ForeignOwnable`. Signed-off-by: Andreas Hindborg <[email protected]> --- rust/kernel/owned.rs | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs index 85251c57f86c6..0b22de4aaf584 100644 --- a/rust/kernel/owned.rs +++ b/rust/kernel/owned.rs @@ -16,7 +16,10 @@ }; use kernel::{ sync::aref::ARef, - types::RefCounted, // + types::{ + ForeignOwnable, // + RefCounted, + }, // }; /// Types that specify their own way of performing allocation and destruction. Typically, this trait @@ -120,6 +123,7 @@ pub unsafe trait Ownable { /// /// - The [`Owned<T>`] has exclusive access to the instance of `T`. /// - The instance of `T` will stay alive at least as long as the [`Owned<T>`] is alive. +#[repr(transparent)] pub struct Owned<T: Ownable> { ptr: NonNull<T>, } @@ -201,6 +205,45 @@ fn drop(&mut self) { } } +// SAFETY: We derive the pointer to `T` from a valid `T`, so the returned +// pointer satisfy alignment requirements of `T`. +unsafe impl<T: Ownable + 'static> ForeignOwnable for Owned<T> { + const FOREIGN_ALIGN: usize = core::mem::align_of::<Owned<T>>(); + + type Borrowed<'a> = &'a T; + type BorrowedMut<'a> = Pin<&'a mut T>; + + fn into_foreign(self) -> *mut kernel::ffi::c_void { + let ptr = self.ptr.as_ptr().cast(); + core::mem::forget(self); + ptr + } + + unsafe fn from_foreign(ptr: *mut kernel::ffi::c_void) -> Self { + Self { + // SAFETY: By function safety contract, `ptr` came from + // `into_foreign` and cannot be null. + ptr: unsafe { NonNull::new_unchecked(ptr.cast()) }, + } + } + + unsafe fn borrow<'a>(ptr: *mut kernel::ffi::c_void) -> Self::Borrowed<'a> { + // SAFETY: By function safety requirements, `ptr` is valid for use as a + // reference for `'a`. + unsafe { &*ptr.cast() } + } + + unsafe fn borrow_mut<'a>(ptr: *mut kernel::ffi::c_void) -> Self::BorrowedMut<'a> { + // SAFETY: By function safety requirements, `ptr` is valid for use as a + // unique reference for `'a`. + let inner = unsafe { &mut *ptr.cast() }; + + // SAFETY: We never move out of inner, and we do not hand out mutable + // references when `T: !Unpin`. + unsafe { Pin::new_unchecked(inner) } + } +} + /// A trait for objects that can be wrapped in either one of the reference types [`Owned`] and /// [`ARef`]. /// -- 2.51.2
