Implement `ForeignOwnable` for `Owned`. This allows use of `Owned` in places such as the `XArray`. Note that `T` does not need to implement `ForeignOwnable` for `Owned` to implement `ForeignOwnable`. Signed-off-by: Andreas Hindborg Reviewed-by: Gary Guo --- rust/kernel/owned.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs index 7fe9ec3e55126..93a5dfcc1e6f5 100644 --- a/rust/kernel/owned.rs +++ b/rust/kernel/owned.rs @@ -15,6 +15,8 @@ ptr::NonNull, // }; +use kernel::types::ForeignOwnable; + /// Types that specify their own way of performing allocation and destruction. Typically, this trait /// is implemented on types from the C side. /// @@ -186,3 +188,51 @@ fn drop(&mut self) { unsafe { T::release(self.ptr) }; } } + +// SAFETY: We derive the pointer to `T` from a valid `T`, so the returned +// pointer satisfy alignment requirements of `T`. +unsafe impl ForeignOwnable for Owned { + const FOREIGN_ALIGN: usize = core::mem::align_of::(); + + type Borrowed<'a> + = &'a T + where + Self: 'a; + type BorrowedMut<'a> + = Pin<&'a mut T> + where + Self: 'a; + + #[inline] + fn into_foreign(self) -> *mut kernel::ffi::c_void { + Owned::into_raw(self).as_ptr().cast() + } + + #[inline] + unsafe fn from_foreign(ptr: *mut kernel::ffi::c_void) -> Self { + // SAFETY: By function safety contract, `ptr` came from `into_foreign` and cannot be null. + let ptr = unsafe { NonNull::new_unchecked(ptr.cast()) }; + + // SAFETY: By the function safety contract, `ptr` was returned by `into_foreign`, which gave + // up exclusive ownership of a valid, pinned `T`; we retake that ownership here. + unsafe { Owned::from_raw(ptr) } + } + + #[inline] + 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() } + } + + #[inline] + 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) } + } +} -- 2.51.2