Commit | Line | Data |
---|---|---|
ba20915b WAF |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | ||
3 | //! Kernel types. | |
4 | ||
26949bac | 5 | use alloc::boxed::Box; |
4d4692a2 WAF |
6 | use core::{ |
7 | cell::UnsafeCell, | |
8 | mem::MaybeUninit, | |
9 | ops::{Deref, DerefMut}, | |
10 | }; | |
11 | ||
0fc4424d WAF |
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 | ||
26949bac WAF |
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 | ||
71185944 WAF |
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 | ||
4d4692a2 WAF |
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 | } | |
b9ecf9b9 WAF |
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 | ||
ba20915b WAF |
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 | } |