Skip to content

Commit 72d9950

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 e0a3d4d commit 72d9950

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
@@ -543,6 +543,114 @@ impl<T: AlwaysRefCounted> Drop for ARef<T> {
543543
}
544544
}
545545

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

0 commit comments

Comments
 (0)