1 // SPDX-License-Identifier: Apache-2.0 OR MIT 2 3 //! This module contains API-internal items for pin-init. 4 //! 5 //! These items must not be used outside of 6 //! - `kernel/init.rs` 7 //! - `macros/pin_data.rs` 8 //! - `macros/pinned_drop.rs` 9 10 use super::*; 11 12 /// See the [nomicon] for what subtyping is. See also [this table]. 13 /// 14 /// [nomicon]: https://doc.rust-lang.org/nomicon/subtyping.html 15 /// [this table]: https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns 16 type Invariant<T> = PhantomData<fn(*mut T) -> *mut T>; 17 18 /// This is the module-internal type implementing `PinInit` and `Init`. It is unsafe to create this 19 /// type, since the closure needs to fulfill the same safety requirement as the 20 /// `__pinned_init`/`__init` functions. 21 pub(crate) struct InitClosure<F, T: ?Sized, E>(pub(crate) F, pub(crate) Invariant<(E, T)>); 22 23 // SAFETY: While constructing the `InitClosure`, the user promised that it upholds the 24 // `__init` invariants. 25 unsafe impl<T: ?Sized, F, E> Init<T, E> for InitClosure<F, T, E> 26 where 27 F: FnOnce(*mut T) -> Result<(), E>, 28 { 29 #[inline] 30 unsafe fn __init(self, slot: *mut T) -> Result<(), E> { 31 (self.0)(slot) 32 } 33 } 34 35 /// This trait is only implemented via the `#[pin_data]` proc-macro. It is used to facilitate 36 /// the pin projections within the initializers. 37 /// 38 /// # Safety 39 /// 40 /// Only the `init` module is allowed to use this trait. 41 pub unsafe trait HasPinData { 42 type PinData: PinData; 43 44 unsafe fn __pin_data() -> Self::PinData; 45 } 46 47 /// Marker trait for pinning data of structs. 48 /// 49 /// # Safety 50 /// 51 /// Only the `init` module is allowed to use this trait. 52 pub unsafe trait PinData: Copy { 53 type Datee: ?Sized + HasPinData; 54 55 /// Type inference helper function. 56 fn make_closure<F, O, E>(self, f: F) -> F 57 where 58 F: FnOnce(*mut Self::Datee) -> Result<O, E>, 59 { 60 f 61 } 62 } 63 64 /// This trait is automatically implemented for every type. It aims to provide the same type 65 /// inference help as `HasPinData`. 66 /// 67 /// # Safety 68 /// 69 /// Only the `init` module is allowed to use this trait. 70 pub unsafe trait HasInitData { 71 type InitData: InitData; 72 73 unsafe fn __init_data() -> Self::InitData; 74 } 75 76 /// Same function as `PinData`, but for arbitrary data. 77 /// 78 /// # Safety 79 /// 80 /// Only the `init` module is allowed to use this trait. 81 pub unsafe trait InitData: Copy { 82 type Datee: ?Sized + HasInitData; 83 84 /// Type inference helper function. 85 fn make_closure<F, O, E>(self, f: F) -> F 86 where 87 F: FnOnce(*mut Self::Datee) -> Result<O, E>, 88 { 89 f 90 } 91 } 92 93 pub struct AllData<T: ?Sized>(PhantomData<fn(Box<T>) -> Box<T>>); 94 95 impl<T: ?Sized> Clone for AllData<T> { 96 fn clone(&self) -> Self { 97 *self 98 } 99 } 100 101 impl<T: ?Sized> Copy for AllData<T> {} 102 103 unsafe impl<T: ?Sized> InitData for AllData<T> { 104 type Datee = T; 105 } 106 107 unsafe impl<T: ?Sized> HasInitData for T { 108 type InitData = AllData<T>; 109 110 unsafe fn __init_data() -> Self::InitData { 111 AllData(PhantomData) 112 } 113 } 114 115 /// Stack initializer helper type. Use [`stack_pin_init`] instead of this primitive. 116 /// 117 /// # Invariants 118 /// 119 /// If `self.is_init` is true, then `self.value` is initialized. 120 /// 121 /// [`stack_pin_init`]: kernel::stack_pin_init 122 pub struct StackInit<T> { 123 value: MaybeUninit<T>, 124 is_init: bool, 125 } 126 127 impl<T> Drop for StackInit<T> { 128 #[inline] 129 fn drop(&mut self) { 130 if self.is_init { 131 // SAFETY: As we are being dropped, we only call this once. And since `self.is_init` is 132 // true, `self.value` is initialized. 133 unsafe { self.value.assume_init_drop() }; 134 } 135 } 136 } 137 138 impl<T> StackInit<T> { 139 /// Creates a new [`StackInit<T>`] that is uninitialized. Use [`stack_pin_init`] instead of this 140 /// primitive. 141 /// 142 /// [`stack_pin_init`]: kernel::stack_pin_init 143 #[inline] 144 pub fn uninit() -> Self { 145 Self { 146 value: MaybeUninit::uninit(), 147 is_init: false, 148 } 149 } 150 151 /// Initializes the contents and returns the result. 152 #[inline] 153 pub fn init<E>(self: Pin<&mut Self>, init: impl PinInit<T, E>) -> Result<Pin<&mut T>, E> { 154 // SAFETY: We never move out of `this`. 155 let this = unsafe { Pin::into_inner_unchecked(self) }; 156 // The value is currently initialized, so it needs to be dropped before we can reuse 157 // the memory (this is a safety guarantee of `Pin`). 158 if this.is_init { 159 this.is_init = false; 160 // SAFETY: `this.is_init` was true and therefore `this.value` is initialized. 161 unsafe { this.value.assume_init_drop() }; 162 } 163 // SAFETY: The memory slot is valid and this type ensures that it will stay pinned. 164 unsafe { init.__pinned_init(this.value.as_mut_ptr())? }; 165 // INVARIANT: `this.value` is initialized above. 166 this.is_init = true; 167 // SAFETY: The slot is now pinned, since we will never give access to `&mut T`. 168 Ok(unsafe { Pin::new_unchecked(this.value.assume_init_mut()) }) 169 } 170 } 171 172 /// When a value of this type is dropped, it drops a `T`. 173 /// 174 /// Can be forgotten to prevent the drop. 175 pub struct DropGuard<T: ?Sized> { 176 ptr: *mut T, 177 do_drop: Cell<bool>, 178 } 179 180 impl<T: ?Sized> DropGuard<T> { 181 /// Creates a new [`DropGuard<T>`]. It will [`ptr::drop_in_place`] `ptr` when it gets dropped. 182 /// 183 /// # Safety 184 /// 185 /// `ptr` must be a valid pointer. 186 /// 187 /// It is the callers responsibility that `self` will only get dropped if the pointee of `ptr`: 188 /// - has not been dropped, 189 /// - is not accessible by any other means, 190 /// - will not be dropped by any other means. 191 #[inline] 192 pub unsafe fn new(ptr: *mut T) -> Self { 193 Self { 194 ptr, 195 do_drop: Cell::new(true), 196 } 197 } 198 199 /// Prevents this guard from dropping the supplied pointer. 200 /// 201 /// # Safety 202 /// 203 /// This function is unsafe in order to prevent safe code from forgetting this guard. It should 204 /// only be called by the macros in this module. 205 #[inline] 206 pub unsafe fn forget(&self) { 207 self.do_drop.set(false); 208 } 209 } 210 211 impl<T: ?Sized> Drop for DropGuard<T> { 212 #[inline] 213 fn drop(&mut self) { 214 if self.do_drop.get() { 215 // SAFETY: A `DropGuard` can only be constructed using the unsafe `new` function 216 // ensuring that this operation is safe. 217 unsafe { ptr::drop_in_place(self.ptr) } 218 } 219 } 220 } 221 222 /// Token used by `PinnedDrop` to prevent calling the function without creating this unsafely 223 /// created struct. This is needed, because the `drop` function is safe, but should not be called 224 /// manually. 225 pub struct OnlyCallFromDrop(()); 226 227 impl OnlyCallFromDrop { 228 /// # Safety 229 /// 230 /// This function should only be called from the [`Drop::drop`] function and only be used to 231 /// delegate the destruction to the pinned destructor [`PinnedDrop::drop`] of the same type. 232 pub unsafe fn new() -> Self { 233 Self(()) 234 } 235 } 236