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