|
104 | 104 | //! }
|
105 | 105 | //! ```
|
106 | 106 | //!
|
| 107 | +//! ## Manual creation of an initializer |
| 108 | +//! |
| 109 | +//! Often when working with primitives the previous approaches are not sufficient. That is where |
| 110 | +//! [`pin_init_from_closure()`] comes in. This `unsafe` function allows you to create a |
| 111 | +//! [`impl PinInit<T, E>`] directly from a closure. Of course you have to ensure that the closure |
| 112 | +//! actually does the initialization in the correct way. Here are the things to look out for |
| 113 | +//! (we are calling the parameter to the closure `slot`): |
| 114 | +//! - when the closure returns `Ok(())`, then it has completed the initialization successfully, so |
| 115 | +//! `slot` now contains a valid bit pattern for the type `T`, |
| 116 | +//! - when the closure returns `Err(e)`, then the caller may deallocate the memory at `slot`, so |
| 117 | +//! you need to take care to clean up anything if your initialization fails mid-way, |
| 118 | +//! - you may assume that `slot` will stay pinned even after the closure returns until `drop` of |
| 119 | +//! `slot` gets called. |
| 120 | +//! |
| 121 | +//! ```rust |
| 122 | +//! use kernel::{prelude::*, init}; |
| 123 | +//! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin}; |
| 124 | +//! # mod bindings { |
| 125 | +//! # pub struct foo; |
| 126 | +//! # pub unsafe fn init_foo(_ptr: *mut foo) {} |
| 127 | +//! # pub unsafe fn destroy_foo(_ptr: *mut foo) {} |
| 128 | +//! # pub unsafe fn enable_foo(_ptr: *mut foo, _flags: u32) -> i32 { 0 } |
| 129 | +//! # } |
| 130 | +//! /// # Invariants |
| 131 | +//! /// |
| 132 | +//! /// `foo` is always initialized |
| 133 | +//! #[pin_data(PinnedDrop)] |
| 134 | +//! pub struct RawFoo { |
| 135 | +//! #[pin] |
| 136 | +//! foo: Opaque<bindings::foo>, |
| 137 | +//! #[pin] |
| 138 | +//! _p: PhantomPinned, |
| 139 | +//! } |
| 140 | +//! |
| 141 | +//! impl RawFoo { |
| 142 | +//! pub fn new(flags: u32) -> impl PinInit<Self, Error> { |
| 143 | +//! // SAFETY: |
| 144 | +//! // - when the closure returns `Ok(())`, then it has successfully initialized and |
| 145 | +//! // enabled `foo`, |
| 146 | +//! // - when it returns `Err(e)`, then it has cleaned up before |
| 147 | +//! unsafe { |
| 148 | +//! init::pin_init_from_closure(move |slot: *mut Self| { |
| 149 | +//! // `slot` contains uninit memory, avoid creating a reference. |
| 150 | +//! let foo = addr_of_mut!((*slot).foo); |
| 151 | +//! |
| 152 | +//! // Initialize the `foo` |
| 153 | +//! bindings::init_foo(Opaque::raw_get(foo)); |
| 154 | +//! |
| 155 | +//! // Try to enable it. |
| 156 | +//! let err = bindings::enable_foo(Opaque::raw_get(foo), flags); |
| 157 | +//! if err != 0 { |
| 158 | +//! // Enabling has failed, first clean up the foo and then return the error. |
| 159 | +//! bindings::destroy_foo(Opaque::raw_get(foo)); |
| 160 | +//! return Err(Error::from_kernel_errno(err)); |
| 161 | +//! } |
| 162 | +//! |
| 163 | +//! // All fields of `RawFoo` have been initialized, since `_p` is a ZST. |
| 164 | +//! Ok(()) |
| 165 | +//! }) |
| 166 | +//! } |
| 167 | +//! } |
| 168 | +//! } |
| 169 | +//! |
| 170 | +//! #[pinned_drop] |
| 171 | +//! impl PinnedDrop for RawFoo { |
| 172 | +//! fn drop(self: Pin<&mut Self>) { |
| 173 | +//! // SAFETY: Since `foo` is initialized, destroying is safe. |
| 174 | +//! unsafe { bindings::destroy_foo(self.foo.get()) }; |
| 175 | +//! } |
| 176 | +//! } |
| 177 | +//! ``` |
| 178 | +//! |
107 | 179 | //! [`sync`]: kernel::sync
|
108 | 180 | //! [pinning]: https://doc.rust-lang.org/std/pin/index.html
|
109 | 181 | //! [structurally pinned fields]:
|
@@ -1084,3 +1156,42 @@ impl<T> InPlaceInit<T> for UniqueArc<T> {
|
1084 | 1156 | Ok(unsafe { this.assume_init() })
|
1085 | 1157 | }
|
1086 | 1158 | }
|
| 1159 | + |
| 1160 | +/// Trait facilitating pinned destruction. |
| 1161 | +/// |
| 1162 | +/// Use [`pinned_drop`] to implement this trait safely: |
| 1163 | +/// |
| 1164 | +/// ```rust |
| 1165 | +/// # use kernel::sync::Mutex; |
| 1166 | +/// use kernel::macros::pinned_drop; |
| 1167 | +/// use core::pin::Pin; |
| 1168 | +/// #[pin_data(PinnedDrop)] |
| 1169 | +/// struct Foo { |
| 1170 | +/// #[pin] |
| 1171 | +/// mtx: Mutex<usize>, |
| 1172 | +/// } |
| 1173 | +/// |
| 1174 | +/// #[pinned_drop] |
| 1175 | +/// impl PinnedDrop for Foo { |
| 1176 | +/// fn drop(self: Pin<&mut Self>) { |
| 1177 | +/// pr_info!("Foo is being dropped!"); |
| 1178 | +/// } |
| 1179 | +/// } |
| 1180 | +/// ``` |
| 1181 | +/// |
| 1182 | +/// # Safety |
| 1183 | +/// |
| 1184 | +/// This trait must be implemented via the [`pinned_drop`] proc-macro attribute on the impl. |
| 1185 | +/// |
| 1186 | +/// [`pinned_drop`]: kernel::macros::pinned_drop |
| 1187 | +pub unsafe trait PinnedDrop: __internal::HasPinData { |
| 1188 | + /// Executes the pinned destructor of this type. |
| 1189 | + /// |
| 1190 | + /// While this function is marked safe, it is actually unsafe to call it manually. For this |
| 1191 | + /// reason it takes an additional parameter. This type can only be constructed by `unsafe` code |
| 1192 | + /// and thus prevents this function from being called where it should not. |
| 1193 | + /// |
| 1194 | + /// This extra parameter will be generated by the `#[pinned_drop]` proc-macro attribute |
| 1195 | + /// automatically. |
| 1196 | + fn drop(self: Pin<&mut Self>, only_call_from_drop: __internal::OnlyCallFromDrop); |
| 1197 | +} |
0 commit comments