1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Kernel types. 4 5 use alloc::boxed::Box; 6 use core::{ 7 cell::UnsafeCell, 8 mem::MaybeUninit, 9 ops::{Deref, DerefMut}, 10 }; 11 12 /// Used to transfer ownership to and from foreign (non-Rust) languages. 13 /// 14 /// Ownership is transferred from Rust to a foreign language by calling [`Self::into_foreign`] and 15 /// later may be transferred back to Rust by calling [`Self::from_foreign`]. 16 /// 17 /// This trait is meant to be used in cases when Rust objects are stored in C objects and 18 /// eventually "freed" back to Rust. 19 pub trait ForeignOwnable: Sized { 20 /// Type of values borrowed between calls to [`ForeignOwnable::into_foreign`] and 21 /// [`ForeignOwnable::from_foreign`]. 22 type Borrowed<'a>; 23 24 /// Converts a Rust-owned object to a foreign-owned one. 25 /// 26 /// The foreign representation is a pointer to void. 27 fn into_foreign(self) -> *const core::ffi::c_void; 28 29 /// Borrows a foreign-owned object. 30 /// 31 /// # Safety 32 /// 33 /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for 34 /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. 35 /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow_mut`] 36 /// for this object must have been dropped. 37 unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Self::Borrowed<'a>; 38 39 /// Mutably borrows a foreign-owned object. 40 /// 41 /// # Safety 42 /// 43 /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for 44 /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. 45 /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] and 46 /// [`ForeignOwnable::borrow_mut`] for this object must have been dropped. 47 unsafe fn borrow_mut(ptr: *const core::ffi::c_void) -> ScopeGuard<Self, fn(Self)> { 48 // SAFETY: The safety requirements ensure that `ptr` came from a previous call to 49 // `into_foreign`. 50 ScopeGuard::new_with_data(unsafe { Self::from_foreign(ptr) }, |d| { 51 d.into_foreign(); 52 }) 53 } 54 55 /// Converts a foreign-owned object back to a Rust-owned one. 56 /// 57 /// # Safety 58 /// 59 /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for 60 /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. 61 /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] and 62 /// [`ForeignOwnable::borrow_mut`] for this object must have been dropped. 63 unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self; 64 } 65 66 impl<T: 'static> ForeignOwnable for Box<T> { 67 type Borrowed<'a> = &'a T; 68 69 fn into_foreign(self) -> *const core::ffi::c_void { 70 Box::into_raw(self) as _ 71 } 72 73 unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> &'a T { 74 // SAFETY: The safety requirements for this function ensure that the object is still alive, 75 // so it is safe to dereference the raw pointer. 76 // The safety requirements of `from_foreign` also ensure that the object remains alive for 77 // the lifetime of the returned value. 78 unsafe { &*ptr.cast() } 79 } 80 81 unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self { 82 // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous 83 // call to `Self::into_foreign`. 84 unsafe { Box::from_raw(ptr as _) } 85 } 86 } 87 88 impl ForeignOwnable for () { 89 type Borrowed<'a> = (); 90 91 fn into_foreign(self) -> *const core::ffi::c_void { 92 core::ptr::NonNull::dangling().as_ptr() 93 } 94 95 unsafe fn borrow<'a>(_: *const core::ffi::c_void) -> Self::Borrowed<'a> {} 96 97 unsafe fn from_foreign(_: *const core::ffi::c_void) -> Self {} 98 } 99 100 /// Runs a cleanup function/closure when dropped. 101 /// 102 /// The [`ScopeGuard::dismiss`] function prevents the cleanup function from running. 103 /// 104 /// # Examples 105 /// 106 /// In the example below, we have multiple exit paths and we want to log regardless of which one is 107 /// taken: 108 /// ``` 109 /// # use kernel::ScopeGuard; 110 /// fn example1(arg: bool) { 111 /// let _log = ScopeGuard::new(|| pr_info!("example1 completed\n")); 112 /// 113 /// if arg { 114 /// return; 115 /// } 116 /// 117 /// pr_info!("Do something...\n"); 118 /// } 119 /// 120 /// # example1(false); 121 /// # example1(true); 122 /// ``` 123 /// 124 /// In the example below, we want to log the same message on all early exits but a different one on 125 /// the main exit path: 126 /// ``` 127 /// # use kernel::ScopeGuard; 128 /// fn example2(arg: bool) { 129 /// let log = ScopeGuard::new(|| pr_info!("example2 returned early\n")); 130 /// 131 /// if arg { 132 /// return; 133 /// } 134 /// 135 /// // (Other early returns...) 136 /// 137 /// log.dismiss(); 138 /// pr_info!("example2 no early return\n"); 139 /// } 140 /// 141 /// # example2(false); 142 /// # example2(true); 143 /// ``` 144 /// 145 /// In the example below, we need a mutable object (the vector) to be accessible within the log 146 /// function, so we wrap it in the [`ScopeGuard`]: 147 /// ``` 148 /// # use kernel::ScopeGuard; 149 /// fn example3(arg: bool) -> Result { 150 /// let mut vec = 151 /// ScopeGuard::new_with_data(Vec::new(), |v| pr_info!("vec had {} elements\n", v.len())); 152 /// 153 /// vec.try_push(10u8)?; 154 /// if arg { 155 /// return Ok(()); 156 /// } 157 /// vec.try_push(20u8)?; 158 /// Ok(()) 159 /// } 160 /// 161 /// # assert_eq!(example3(false), Ok(())); 162 /// # assert_eq!(example3(true), Ok(())); 163 /// ``` 164 /// 165 /// # Invariants 166 /// 167 /// The value stored in the struct is nearly always `Some(_)`, except between 168 /// [`ScopeGuard::dismiss`] and [`ScopeGuard::drop`]: in this case, it will be `None` as the value 169 /// will have been returned to the caller. Since [`ScopeGuard::dismiss`] consumes the guard, 170 /// callers won't be able to use it anymore. 171 pub struct ScopeGuard<T, F: FnOnce(T)>(Option<(T, F)>); 172 173 impl<T, F: FnOnce(T)> ScopeGuard<T, F> { 174 /// Creates a new guarded object wrapping the given data and with the given cleanup function. 175 pub fn new_with_data(data: T, cleanup_func: F) -> Self { 176 // INVARIANT: The struct is being initialised with `Some(_)`. 177 Self(Some((data, cleanup_func))) 178 } 179 180 /// Prevents the cleanup function from running and returns the guarded data. 181 pub fn dismiss(mut self) -> T { 182 // INVARIANT: This is the exception case in the invariant; it is not visible to callers 183 // because this function consumes `self`. 184 self.0.take().unwrap().0 185 } 186 } 187 188 impl ScopeGuard<(), fn(())> { 189 /// Creates a new guarded object with the given cleanup function. 190 pub fn new(cleanup: impl FnOnce()) -> ScopeGuard<(), impl FnOnce(())> { 191 ScopeGuard::new_with_data((), move |_| cleanup()) 192 } 193 } 194 195 impl<T, F: FnOnce(T)> Deref for ScopeGuard<T, F> { 196 type Target = T; 197 198 fn deref(&self) -> &T { 199 // The type invariants guarantee that `unwrap` will succeed. 200 &self.0.as_ref().unwrap().0 201 } 202 } 203 204 impl<T, F: FnOnce(T)> DerefMut for ScopeGuard<T, F> { 205 fn deref_mut(&mut self) -> &mut T { 206 // The type invariants guarantee that `unwrap` will succeed. 207 &mut self.0.as_mut().unwrap().0 208 } 209 } 210 211 impl<T, F: FnOnce(T)> Drop for ScopeGuard<T, F> { 212 fn drop(&mut self) { 213 // Run the cleanup function if one is still present. 214 if let Some((data, cleanup)) = self.0.take() { 215 cleanup(data) 216 } 217 } 218 } 219 220 /// Stores an opaque value. 221 /// 222 /// This is meant to be used with FFI objects that are never interpreted by Rust code. 223 #[repr(transparent)] 224 pub struct Opaque<T>(MaybeUninit<UnsafeCell<T>>); 225 226 impl<T> Opaque<T> { 227 /// Creates a new opaque value. 228 pub const fn new(value: T) -> Self { 229 Self(MaybeUninit::new(UnsafeCell::new(value))) 230 } 231 232 /// Creates an uninitialised value. 233 pub const fn uninit() -> Self { 234 Self(MaybeUninit::uninit()) 235 } 236 237 /// Returns a raw pointer to the opaque data. 238 pub fn get(&self) -> *mut T { 239 UnsafeCell::raw_get(self.0.as_ptr()) 240 } 241 } 242 243 /// A sum type that always holds either a value of type `L` or `R`. 244 pub enum Either<L, R> { 245 /// Constructs an instance of [`Either`] containing a value of type `L`. 246 Left(L), 247 248 /// Constructs an instance of [`Either`] containing a value of type `R`. 249 Right(R), 250 } 251