1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Kernel types. 4 5 use core::{ 6 cell::UnsafeCell, 7 mem::MaybeUninit, 8 ops::{Deref, DerefMut}, 9 }; 10 11 /// Runs a cleanup function/closure when dropped. 12 /// 13 /// The [`ScopeGuard::dismiss`] function prevents the cleanup function from running. 14 /// 15 /// # Examples 16 /// 17 /// In the example below, we have multiple exit paths and we want to log regardless of which one is 18 /// taken: 19 /// ``` 20 /// # use kernel::ScopeGuard; 21 /// fn example1(arg: bool) { 22 /// let _log = ScopeGuard::new(|| pr_info!("example1 completed\n")); 23 /// 24 /// if arg { 25 /// return; 26 /// } 27 /// 28 /// pr_info!("Do something...\n"); 29 /// } 30 /// 31 /// # example1(false); 32 /// # example1(true); 33 /// ``` 34 /// 35 /// In the example below, we want to log the same message on all early exits but a different one on 36 /// the main exit path: 37 /// ``` 38 /// # use kernel::ScopeGuard; 39 /// fn example2(arg: bool) { 40 /// let log = ScopeGuard::new(|| pr_info!("example2 returned early\n")); 41 /// 42 /// if arg { 43 /// return; 44 /// } 45 /// 46 /// // (Other early returns...) 47 /// 48 /// log.dismiss(); 49 /// pr_info!("example2 no early return\n"); 50 /// } 51 /// 52 /// # example2(false); 53 /// # example2(true); 54 /// ``` 55 /// 56 /// In the example below, we need a mutable object (the vector) to be accessible within the log 57 /// function, so we wrap it in the [`ScopeGuard`]: 58 /// ``` 59 /// # use kernel::ScopeGuard; 60 /// fn example3(arg: bool) -> Result { 61 /// let mut vec = 62 /// ScopeGuard::new_with_data(Vec::new(), |v| pr_info!("vec had {} elements\n", v.len())); 63 /// 64 /// vec.try_push(10u8)?; 65 /// if arg { 66 /// return Ok(()); 67 /// } 68 /// vec.try_push(20u8)?; 69 /// Ok(()) 70 /// } 71 /// 72 /// # assert_eq!(example3(false), Ok(())); 73 /// # assert_eq!(example3(true), Ok(())); 74 /// ``` 75 /// 76 /// # Invariants 77 /// 78 /// The value stored in the struct is nearly always `Some(_)`, except between 79 /// [`ScopeGuard::dismiss`] and [`ScopeGuard::drop`]: in this case, it will be `None` as the value 80 /// will have been returned to the caller. Since [`ScopeGuard::dismiss`] consumes the guard, 81 /// callers won't be able to use it anymore. 82 pub struct ScopeGuard<T, F: FnOnce(T)>(Option<(T, F)>); 83 84 impl<T, F: FnOnce(T)> ScopeGuard<T, F> { 85 /// Creates a new guarded object wrapping the given data and with the given cleanup function. 86 pub fn new_with_data(data: T, cleanup_func: F) -> Self { 87 // INVARIANT: The struct is being initialised with `Some(_)`. 88 Self(Some((data, cleanup_func))) 89 } 90 91 /// Prevents the cleanup function from running and returns the guarded data. 92 pub fn dismiss(mut self) -> T { 93 // INVARIANT: This is the exception case in the invariant; it is not visible to callers 94 // because this function consumes `self`. 95 self.0.take().unwrap().0 96 } 97 } 98 99 impl ScopeGuard<(), fn(())> { 100 /// Creates a new guarded object with the given cleanup function. 101 pub fn new(cleanup: impl FnOnce()) -> ScopeGuard<(), impl FnOnce(())> { 102 ScopeGuard::new_with_data((), move |_| cleanup()) 103 } 104 } 105 106 impl<T, F: FnOnce(T)> Deref for ScopeGuard<T, F> { 107 type Target = T; 108 109 fn deref(&self) -> &T { 110 // The type invariants guarantee that `unwrap` will succeed. 111 &self.0.as_ref().unwrap().0 112 } 113 } 114 115 impl<T, F: FnOnce(T)> DerefMut for ScopeGuard<T, F> { 116 fn deref_mut(&mut self) -> &mut T { 117 // The type invariants guarantee that `unwrap` will succeed. 118 &mut self.0.as_mut().unwrap().0 119 } 120 } 121 122 impl<T, F: FnOnce(T)> Drop for ScopeGuard<T, F> { 123 fn drop(&mut self) { 124 // Run the cleanup function if one is still present. 125 if let Some((data, cleanup)) = self.0.take() { 126 cleanup(data) 127 } 128 } 129 } 130 131 /// Stores an opaque value. 132 /// 133 /// This is meant to be used with FFI objects that are never interpreted by Rust code. 134 #[repr(transparent)] 135 pub struct Opaque<T>(MaybeUninit<UnsafeCell<T>>); 136 137 impl<T> Opaque<T> { 138 /// Creates a new opaque value. 139 pub const fn new(value: T) -> Self { 140 Self(MaybeUninit::new(UnsafeCell::new(value))) 141 } 142 143 /// Creates an uninitialised value. 144 pub const fn uninit() -> Self { 145 Self(MaybeUninit::uninit()) 146 } 147 148 /// Returns a raw pointer to the opaque data. 149 pub fn get(&self) -> *mut T { 150 UnsafeCell::raw_get(self.0.as_ptr()) 151 } 152 } 153 154 /// A sum type that always holds either a value of type `L` or `R`. 155 pub enum Either<L, R> { 156 /// Constructs an instance of [`Either`] containing a value of type `L`. 157 Left(L), 158 159 /// Constructs an instance of [`Either`] containing a value of type `R`. 160 Right(R), 161 } 162