Skip to content

Commit 8b84b12

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 <[email protected]>
1 parent a29c333 commit 8b84b12

1 file changed

Lines changed: 110 additions & 1 deletion

File tree

rust/kernel/types.rs

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ use crate::ffi::c_void;
66
use core::{
77
cell::UnsafeCell,
88
marker::{PhantomData, PhantomPinned},
9-
mem::MaybeUninit,
9+
mem::{ManuallyDrop, MaybeUninit},
1010
ops::{Deref, DerefMut},
11+
ptr::NonNull,
1112
};
1213
use pin_init::{PinInit, Wrapper, Zeroable};
1314

@@ -423,6 +424,114 @@ impl<T> Wrapper<T> for Opaque<T> {
423424
}
424425
}
425426

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

0 commit comments

Comments
 (0)