Skip to content

Commit 766a400

Browse files
committed
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 <[email protected]>
1 parent 64ebb0e commit 766a400

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
@@ -428,6 +428,114 @@ impl<T: AlwaysRefCounted> Drop for ARef<T> {
428428
}
429429
}
430430

431+
/// Types that may be owned by Rust code or borrowed, but have a lifetime managed by C code.
432+
///
433+
/// It allows such types to define their own custom destructor function to be called when
434+
/// a Rust-owned reference is dropped.
435+
///
436+
/// This is usually implemented by wrappers to existing structures on the C side of the code.
437+
///
438+
/// # Safety
439+
///
440+
/// Implementers must ensure that any objects borrowed directly stay alive for the duration
441+
/// of the borrow lifetime, and that any objects deemed owned by Rust stay alive while
442+
/// that owned reference exists, until the [`Ownable::release()`] function is called.
443+
pub unsafe trait Ownable {
444+
/// Releases the object (frees it or returns it to foreign ownership).
445+
///
446+
/// # Safety
447+
///
448+
/// Callers must ensure that the object is no longer referenced after this call.
449+
unsafe fn release(this: NonNull<Self>);
450+
}
451+
452+
/// A subtrait of Ownable that asserts that an Owned<T> Rust reference is not only unique
453+
/// within Rust, but also follows the same rules in kernel C code. That is, the kernel
454+
/// will never mutate the contents of the object while Rust owns it.
455+
///
456+
/// When this type is implemented for an Ownable type, it allows Owned<T> to be dereferenced
457+
/// into a &mut T.
458+
459+
/// # Safety
460+
///
461+
/// Implementers must ensure that the kernel never mutates the underlying type while
462+
/// Rust owns it.
463+
pub unsafe trait OwnableMut: Ownable {}
464+
465+
/// An owned reference to an ownable kernel object.
466+
///
467+
/// The object is automatically freed or released when an instance of [`Owned`] is
468+
/// dropped.
469+
///
470+
/// # Invariants
471+
///
472+
/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`Owned`] instance.
473+
pub struct Owned<T: Ownable> {
474+
ptr: NonNull<T>,
475+
_p: PhantomData<T>,
476+
}
477+
478+
// SAFETY: It is safe to send `Owned<T>` to another thread when the underlying `T` is `Send` because
479+
// it effectively means sharing `&mut T` (which is safe because `T` is `Send`).
480+
unsafe impl<T: Ownable + Send> Send for Owned<T> {}
481+
482+
// SAFETY: It is safe to send `&Owned<T>` to another thread when the underlying `T` is `Sync`
483+
// because it effectively means sharing `&T` (which is safe because `T` is `Sync`).
484+
unsafe impl<T: Ownable + Sync> Sync for Owned<T> {}
485+
486+
impl<T: Ownable> Owned<T> {
487+
/// Creates a new instance of [`Owned`].
488+
///
489+
/// It takes over ownership of the underlying object.
490+
///
491+
/// # Safety
492+
///
493+
/// Callers must ensure that the underlying object is acquired and can be considered owned by
494+
/// Rust.
495+
pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
496+
// INVARIANT: The safety requirements guarantee that the new instance now owns the
497+
// reference.
498+
Self {
499+
ptr,
500+
_p: PhantomData,
501+
}
502+
}
503+
504+
/// Consumes the `Owned`, returning a raw pointer.
505+
///
506+
/// This function does not actually relinquish ownership of the object.
507+
/// After calling this function, the caller is responsible for ownership previously managed
508+
/// by the `Owned`.
509+
pub fn into_raw(me: Self) -> NonNull<T> {
510+
ManuallyDrop::new(me).ptr
511+
}
512+
}
513+
514+
impl<T: Ownable> Deref for Owned<T> {
515+
type Target = T;
516+
517+
fn deref(&self) -> &Self::Target {
518+
// SAFETY: The type invariants guarantee that the object is valid.
519+
unsafe { self.ptr.as_ref() }
520+
}
521+
}
522+
523+
impl<T: Ownable + OwnableMut> DerefMut for Owned<T> {
524+
fn deref_mut(&mut self) -> &mut Self::Target {
525+
// SAFETY: The type invariants guarantee that the object is valid,
526+
// and that we can safely return a mutable reference to it.
527+
unsafe { self.ptr.as_mut() }
528+
}
529+
}
530+
531+
impl<T: Ownable> Drop for Owned<T> {
532+
fn drop(&mut self) {
533+
// SAFETY: The type invariants guarantee that the `Owned` owns the object we're about to
534+
// release.
535+
unsafe { T::release(self.ptr) };
536+
}
537+
}
538+
431539
/// A sum type that always holds either a value of type `L` or `R`.
432540
///
433541
/// # Examples

0 commit comments

Comments
 (0)