Skip to content

Commit 73a75b5

Browse files
asahilinaOliver Mangold
authored andcommitted
rust: types: Add Ownable/Owned types
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. Link: https://lore.kernel.org/all/20250202-rust-page-v1-1-e3170d7fe55e@asahilina.net/ Signed-off-by: Asahi Lina <lina@asahilina.net> Co-developed-by: Oliver Mangold <oliver.mangold@pm.me> Signed-off-by: Oliver Mangold <oliver.mangold@pm.me>
1 parent ee6a1e1 commit 73a75b5

File tree

1 file changed

+109
-0
lines changed

1 file changed

+109
-0
lines changed

rust/kernel/types.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,115 @@ impl<T: AlwaysRefCounted> Drop for ARef<T> {
551551
}
552552
}
553553

554+
/// Types that may be owned by Rust code or borrowed, but have a lifetime managed by C code.
555+
///
556+
/// It allows such types to define their own custom destructor function to be called when
557+
/// a Rust-owned reference is dropped.
558+
///
559+
/// This is usually implemented by wrappers to existing structures on the C side of the code.
560+
///
561+
/// # Safety
562+
///
563+
/// Implementers must ensure that any objects borrowed directly as `&T` stay alive for the duration
564+
/// of the lifetime, and that any objects owned by Rust as `Owned<T>`) stay alive while that owned
565+
/// reference exists, until the [`Ownable::release()`] trait method is called.
566+
pub unsafe trait Ownable {
567+
/// Releases the object (frees it or returns it to foreign ownership).
568+
///
569+
/// # Safety
570+
///
571+
/// Callers must ensure that the object is no longer referenced after this call.
572+
unsafe fn release(this: NonNull<Self>);
573+
}
574+
575+
/// A subtrait of Ownable that asserts that an `Owned<T>` Rust reference is not only unique
576+
/// within Rust and keeps the `T` alive, but also guarantees that the C code follows the
577+
/// usual mutable reference requirements. That is, the kernel will never mutate the
578+
/// `T` (excluding internal mutability that follows the usual rules) while Rust owns it.
579+
///
580+
/// When this type is implemented for an [`Ownable`] type, it allows `Owned<T>` to be
581+
/// dereferenced into a &mut T.
582+
///
583+
/// # Safety
584+
///
585+
/// Implementers must ensure that the kernel never mutates the underlying type while
586+
/// Rust owns it.
587+
pub unsafe trait OwnableMut: Ownable {}
588+
589+
/// An owned reference to an ownable kernel object.
590+
///
591+
/// The object is automatically freed or released when an instance of [`Owned`] is
592+
/// dropped.
593+
///
594+
/// # Invariants
595+
///
596+
/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`Owned`] instance.
597+
pub struct Owned<T: Ownable> {
598+
ptr: NonNull<T>,
599+
_p: PhantomData<T>,
600+
}
601+
602+
// SAFETY: It is safe to send `Owned<T>` to another thread when the underlying `T` is `Send` because
603+
// it effectively means sending a unique `&mut T` pointer (which is safe because `T` is `Send`).
604+
unsafe impl<T: Ownable + Send> Send for Owned<T> {}
605+
606+
// SAFETY: It is safe to send `&Owned<T>` to another thread when the underlying `T` is `Sync`
607+
// because it effectively means sharing `&T` (which is safe because `T` is `Sync`).
608+
unsafe impl<T: Ownable + Sync> Sync for Owned<T> {}
609+
610+
impl<T: Ownable> Owned<T> {
611+
/// Creates a new instance of [`Owned`].
612+
///
613+
/// It takes over ownership of the underlying object.
614+
///
615+
/// # Safety
616+
///
617+
/// Callers must ensure that the underlying object is acquired and can be considered owned by
618+
/// Rust.
619+
pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
620+
// INVARIANT: The safety requirements guarantee that the new instance now owns the
621+
// reference.
622+
Self {
623+
ptr,
624+
_p: PhantomData,
625+
}
626+
}
627+
628+
/// Consumes the `Owned`, returning a raw pointer.
629+
///
630+
/// This function does not actually relinquish ownership of the object.
631+
/// After calling this function, the caller is responsible for ownership previously managed
632+
/// by the `Owned`.
633+
pub fn into_raw(me: Self) -> NonNull<T> {
634+
ManuallyDrop::new(me).ptr
635+
}
636+
}
637+
638+
impl<T: Ownable> Deref for Owned<T> {
639+
type Target = T;
640+
641+
fn deref(&self) -> &Self::Target {
642+
// SAFETY: The type invariants guarantee that the object is valid.
643+
unsafe { self.ptr.as_ref() }
644+
}
645+
}
646+
647+
impl<T: Ownable + OwnableMut> DerefMut for Owned<T> {
648+
fn deref_mut(&mut self) -> &mut Self::Target {
649+
// SAFETY: The type invariants guarantee that the object is valid,
650+
// and that we can safely return a mutable reference to it.
651+
unsafe { self.ptr.as_mut() }
652+
}
653+
}
654+
655+
impl<T: Ownable> Drop for Owned<T> {
656+
fn drop(&mut self) {
657+
// SAFETY: The type invariants guarantee that the `Owned` owns the object we're about to
658+
// release.
659+
unsafe { T::release(self.ptr) };
660+
}
661+
}
662+
554663
/// A sum type that always holds either a value of type `L` or `R`.
555664
///
556665
/// # Examples

0 commit comments

Comments
 (0)