Skip to content

Commit 63fcaa9

Browse files
hoshinolinajannau
authored andcommitted
rust: 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. Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent 36b2021 commit 63fcaa9

1 file changed

Lines changed: 108 additions & 0 deletions

File tree

rust/kernel/types.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,114 @@ impl<T: AlwaysRefCounted> Drop for ARef<T> {
564564
}
565565
}
566566

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

0 commit comments

Comments
 (0)