2022-11-10 17:41:39 +01:00
// SPDX-License-Identifier: GPL-2.0
//! Kernel types.
2023-01-30 03:44:02 -03:00
use alloc ::boxed ::Box ;
2023-01-30 03:44:00 -03:00
use core ::{
cell ::UnsafeCell ,
mem ::MaybeUninit ,
ops ::{ Deref , DerefMut } ,
} ;
2023-01-30 03:44:01 -03:00
/// 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 ;
}
2023-01-30 03:44:02 -03:00
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 _ ) }
}
}
2023-01-30 03:44:03 -03:00
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 { }
}
2023-01-30 03:44:00 -03:00
/// 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 )
}
}
}
2022-11-10 17:41:40 +01:00
/// 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 ( ) )
}
}
2022-11-10 17:41:39 +01:00
/// 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 ) ,
}