| // SPDX-License-Identifier: GPL-2.0 |
| |
| //! Kernel types. |
| |
| use alloc::boxed::Box; |
| use core::{ |
| cell::UnsafeCell, |
| mem::MaybeUninit, |
| ops::{Deref, DerefMut}, |
| }; |
| |
| /// Used to transfer ownership to and from foreign (non-Rust) languages. |
| /// |
| /// Ownership is transferred from Rust to a foreign language by calling [`Self::into_foreign`] and |
| /// later may be transferred back to Rust by calling [`Self::from_foreign`]. |
| /// |
| /// This trait is meant to be used in cases when Rust objects are stored in C objects and |
| /// eventually "freed" back to Rust. |
| pub trait ForeignOwnable: Sized { |
| /// Type of values borrowed between calls to [`ForeignOwnable::into_foreign`] and |
| /// [`ForeignOwnable::from_foreign`]. |
| type Borrowed<'a>; |
| |
| /// Converts a Rust-owned object to a foreign-owned one. |
| /// |
| /// The foreign representation is a pointer to void. |
| fn into_foreign(self) -> *const core::ffi::c_void; |
| |
| /// Borrows a foreign-owned object. |
| /// |
| /// # Safety |
| /// |
| /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for |
| /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. |
| /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow_mut`] |
| /// for this object must have been dropped. |
| unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Self::Borrowed<'a>; |
| |
| /// Mutably borrows a foreign-owned object. |
| /// |
| /// # Safety |
| /// |
| /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for |
| /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. |
| /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] and |
| /// [`ForeignOwnable::borrow_mut`] for this object must have been dropped. |
| unsafe fn borrow_mut(ptr: *const core::ffi::c_void) -> ScopeGuard<Self, fn(Self)> { |
| // SAFETY: The safety requirements ensure that `ptr` came from a previous call to |
| // `into_foreign`. |
| ScopeGuard::new_with_data(unsafe { Self::from_foreign(ptr) }, |d| { |
| d.into_foreign(); |
| }) |
| } |
| |
| /// Converts a foreign-owned object back to a Rust-owned one. |
| /// |
| /// # Safety |
| /// |
| /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for |
| /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. |
| /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] and |
| /// [`ForeignOwnable::borrow_mut`] for this object must have been dropped. |
| unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self; |
| } |
| |
| impl<T: 'static> ForeignOwnable for Box<T> { |
| type Borrowed<'a> = &'a T; |
| |
| fn into_foreign(self) -> *const core::ffi::c_void { |
| Box::into_raw(self) as _ |
| } |
| |
| unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> &'a T { |
| // SAFETY: The safety requirements for this function ensure that the object is still alive, |
| // so it is safe to dereference the raw pointer. |
| // The safety requirements of `from_foreign` also ensure that the object remains alive for |
| // the lifetime of the returned value. |
| unsafe { &*ptr.cast() } |
| } |
| |
| unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self { |
| // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous |
| // call to `Self::into_foreign`. |
| unsafe { Box::from_raw(ptr as _) } |
| } |
| } |
| |
| impl ForeignOwnable for () { |
| type Borrowed<'a> = (); |
| |
| fn into_foreign(self) -> *const core::ffi::c_void { |
| core::ptr::NonNull::dangling().as_ptr() |
| } |
| |
| unsafe fn borrow<'a>(_: *const core::ffi::c_void) -> Self::Borrowed<'a> {} |
| |
| unsafe fn from_foreign(_: *const core::ffi::c_void) -> Self {} |
| } |
| |
| /// Runs a cleanup function/closure when dropped. |
| /// |
| /// The [`ScopeGuard::dismiss`] function prevents the cleanup function from running. |
| /// |
| /// # Examples |
| /// |
| /// In the example below, we have multiple exit paths and we want to log regardless of which one is |
| /// taken: |
| /// ``` |
| /// # use kernel::ScopeGuard; |
| /// fn example1(arg: bool) { |
| /// let _log = ScopeGuard::new(|| pr_info!("example1 completed\n")); |
| /// |
| /// if arg { |
| /// return; |
| /// } |
| /// |
| /// pr_info!("Do something...\n"); |
| /// } |
| /// |
| /// # example1(false); |
| /// # example1(true); |
| /// ``` |
| /// |
| /// In the example below, we want to log the same message on all early exits but a different one on |
| /// the main exit path: |
| /// ``` |
| /// # use kernel::ScopeGuard; |
| /// fn example2(arg: bool) { |
| /// let log = ScopeGuard::new(|| pr_info!("example2 returned early\n")); |
| /// |
| /// if arg { |
| /// return; |
| /// } |
| /// |
| /// // (Other early returns...) |
| /// |
| /// log.dismiss(); |
| /// pr_info!("example2 no early return\n"); |
| /// } |
| /// |
| /// # example2(false); |
| /// # example2(true); |
| /// ``` |
| /// |
| /// In the example below, we need a mutable object (the vector) to be accessible within the log |
| /// function, so we wrap it in the [`ScopeGuard`]: |
| /// ``` |
| /// # use kernel::ScopeGuard; |
| /// fn example3(arg: bool) -> Result { |
| /// let mut vec = |
| /// ScopeGuard::new_with_data(Vec::new(), |v| pr_info!("vec had {} elements\n", v.len())); |
| /// |
| /// vec.try_push(10u8)?; |
| /// if arg { |
| /// return Ok(()); |
| /// } |
| /// vec.try_push(20u8)?; |
| /// Ok(()) |
| /// } |
| /// |
| /// # assert_eq!(example3(false), Ok(())); |
| /// # assert_eq!(example3(true), Ok(())); |
| /// ``` |
| /// |
| /// # Invariants |
| /// |
| /// The value stored in the struct is nearly always `Some(_)`, except between |
| /// [`ScopeGuard::dismiss`] and [`ScopeGuard::drop`]: in this case, it will be `None` as the value |
| /// will have been returned to the caller. Since [`ScopeGuard::dismiss`] consumes the guard, |
| /// callers won't be able to use it anymore. |
| pub struct ScopeGuard<T, F: FnOnce(T)>(Option<(T, F)>); |
| |
| impl<T, F: FnOnce(T)> ScopeGuard<T, F> { |
| /// Creates a new guarded object wrapping the given data and with the given cleanup function. |
| pub fn new_with_data(data: T, cleanup_func: F) -> Self { |
| // INVARIANT: The struct is being initialised with `Some(_)`. |
| Self(Some((data, cleanup_func))) |
| } |
| |
| /// Prevents the cleanup function from running and returns the guarded data. |
| pub fn dismiss(mut self) -> T { |
| // INVARIANT: This is the exception case in the invariant; it is not visible to callers |
| // because this function consumes `self`. |
| self.0.take().unwrap().0 |
| } |
| } |
| |
| impl ScopeGuard<(), fn(())> { |
| /// Creates a new guarded object with the given cleanup function. |
| pub fn new(cleanup: impl FnOnce()) -> ScopeGuard<(), impl FnOnce(())> { |
| ScopeGuard::new_with_data((), move |_| cleanup()) |
| } |
| } |
| |
| impl<T, F: FnOnce(T)> Deref for ScopeGuard<T, F> { |
| type Target = T; |
| |
| fn deref(&self) -> &T { |
| // The type invariants guarantee that `unwrap` will succeed. |
| &self.0.as_ref().unwrap().0 |
| } |
| } |
| |
| impl<T, F: FnOnce(T)> DerefMut for ScopeGuard<T, F> { |
| fn deref_mut(&mut self) -> &mut T { |
| // The type invariants guarantee that `unwrap` will succeed. |
| &mut self.0.as_mut().unwrap().0 |
| } |
| } |
| |
| impl<T, F: FnOnce(T)> Drop for ScopeGuard<T, F> { |
| fn drop(&mut self) { |
| // Run the cleanup function if one is still present. |
| if let Some((data, cleanup)) = self.0.take() { |
| cleanup(data) |
| } |
| } |
| } |
| |
| /// Stores an opaque value. |
| /// |
| /// This is meant to be used with FFI objects that are never interpreted by Rust code. |
| #[repr(transparent)] |
| pub struct Opaque<T>(MaybeUninit<UnsafeCell<T>>); |
| |
| impl<T> Opaque<T> { |
| /// Creates a new opaque value. |
| pub const fn new(value: T) -> Self { |
| Self(MaybeUninit::new(UnsafeCell::new(value))) |
| } |
| |
| /// Creates an uninitialised value. |
| pub const fn uninit() -> Self { |
| Self(MaybeUninit::uninit()) |
| } |
| |
| /// Returns a raw pointer to the opaque data. |
| pub fn get(&self) -> *mut T { |
| UnsafeCell::raw_get(self.0.as_ptr()) |
| } |
| } |
| |
| /// A sum type that always holds either a value of type `L` or `R`. |
| pub enum Either<L, R> { |
| /// Constructs an instance of [`Either`] containing a value of type `L`. |
| Left(L), |
| |
| /// Constructs an instance of [`Either`] containing a value of type `R`. |
| Right(R), |
| } |