Skip to content

Commit 6de1dbb

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 59f3222 commit 6de1dbb

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
@@ -423,6 +423,114 @@ impl<T> Wrapper<T> for Opaque<T> {
423423
}
424424
}
425425

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