By analogy to AlwaysRefCounted and ARef, an Ownable type is a (typically C FFI) type that *may* be owned by Rust, but need not be. Unlike AlwaysRefCounted, this mechanism expects the reference to be unique within Rust, and does not allow cloning. Conceptually, this is similar to a KBox<T>, except that it delegates resource management to the T instead of using a generic allocator. Signed-off-by: Asahi Lina <lina@xxxxxxxxxxxxx> --- rust/kernel/types.rs | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index ec6457bb3084ae327c38ba4ba79b1601aef38244..0bee56153dcea47fb1321162df6b8765b5436e9f 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -479,6 +479,116 @@ fn drop(&mut self) { } } +/// Types that may be owned by Rust code or borrowed, but have a lifetime managed by C code. +/// +/// It allows such types to define their own custom destructor function to be called when +/// a Rust-owned reference is dropped. +/// +/// This is usually implemented by wrappers to existing structures on the C side of the code. +/// +/// # Safety +/// +/// Implementers must ensure that any objects borrowed directly as `&T` stay alive for the duration +/// of the lifetime, and that any objects owned by Rust as `Owned<T>`) stay alive while that owned +/// reference exists, until the [`Ownable::release()`] trait method is called. +pub unsafe trait Ownable { + /// Releases the object (frees it or returns it to foreign ownership). + /// + /// # Safety + /// + /// Callers must ensure that the object is no longer referenced after this call. + unsafe fn release(this: NonNull<Self>); +} + +/// A subtrait of Ownable that asserts that an `Owned<T>` Rust reference is not only unique +/// within Rust and keeps the `T` alive, but also guarantees that the C code follows the +/// usual mutable reference requirements. That is, the kernel will never mutate the +/// `T` (excluding internal mutability that follows the usual rules) while Rust owns it. +/// +/// When this type is implemented for an [`Ownable`] type, it allows `Owned<T>` to be +/// dereferenced into a &mut T. +/// +/// # Safety +/// +/// Implementers must ensure that the kernel never mutates the underlying type while +/// Rust owns it. +pub unsafe trait OwnableMut: Ownable {} + +/// An owned reference to an ownable kernel object. +/// +/// The object is automatically freed or released when an instance of [`Owned`] is +/// dropped. +/// +/// # Invariants +/// +/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`Owned`] instance. +pub struct Owned<T: Ownable> { + ptr: NonNull<T>, + _p: PhantomData<T>, +} + +// SAFETY: It is safe to send `Owned<T>` to another thread when the underlying `T` is `Send` because +// it effectively means sending a unique `&mut T` pointer (which is safe because `T` is `Send`). +unsafe impl<T: Ownable + Send> Send for Owned<T> {} + +// SAFETY: It is safe to send `&Owned<T>` to another thread when the underlying `T` is `Sync` +// because it effectively means sharing `&T` (which is safe because `T` is `Sync`). +unsafe impl<T: Ownable + Sync> Sync for Owned<T> {} + +impl<T: Ownable> Owned<T> { + /// Creates a new instance of [`Owned`]. + /// + /// It takes over ownership of the underlying object. + /// + /// # Safety + /// + /// Callers must ensure that the underlying object is acquired and can be considered owned by + /// Rust. + pub(crate) unsafe fn from_raw(ptr: NonNull<T>) -> Self { + // INVARIANT: The safety requirements guarantee that the new instance now owns the + // reference. + Self { + ptr, + _p: PhantomData, + } + } + + /// Consumes the `Owned`, returning a raw pointer. + /// + /// This function does not actually relinquish ownership of the object. + /// After calling this function, the caller is responsible for ownership previously managed + /// by the `Owned`. + #[allow(dead_code)] + pub(crate) fn into_raw(me: Self) -> NonNull<T> { + ManuallyDrop::new(me).ptr + } +} + +impl<T: Ownable> Deref for Owned<T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + // SAFETY: The type invariants guarantee that the object is valid. + unsafe { self.ptr.as_ref() } + } +} + +impl<T: Ownable + OwnableMut> DerefMut for Owned<T> { + fn deref_mut(&mut self) -> &mut Self::Target { + // SAFETY: The type invariants guarantee that the object is valid, + // and that we can safely return a mutable reference to it. + unsafe { self.ptr.as_mut() } + } +} + +impl<T: Ownable> Drop for Owned<T> { + fn drop(&mut self) { + // SAFETY: The type invariants guarantee that the `Owned` owns the object we're about to + // release. + unsafe { T::release(self.ptr) }; + } +} + /// A sum type that always holds either a value of type `L` or `R`. /// /// # Examples -- 2.47.1