1[](https://crates.io/crates/pin-init) 2[](https://docs.rs/pin-init/) 3[](https://deps.rs/repo/github/Rust-for-Linux/pin-init) 4 5[](#nightly-only) 6 7# `pin-init` 8 9> [!NOTE] 10> 11> This crate was originally named [`pinned-init`], but the migration to 12> `pin-init` is not yet complete. The `legcay` branch contains the current 13> version of the `pinned-init` crate & the `main` branch already incorporates 14> the rename to `pin-init`. 15> 16> There are still some changes needed on the kernel side before the migration 17> can be completed. 18 19[`pinned-init`]: https://crates.io/crates/pinned-init 20 21<!-- cargo-rdme start --> 22 23Library to safely and fallibly initialize pinned `struct`s using in-place constructors. 24 25[Pinning][pinning] is Rust's way of ensuring data does not move. 26 27It also allows in-place initialization of big `struct`s that would otherwise produce a stack 28overflow. 29 30This library's main use-case is in [Rust-for-Linux]. Although this version can be used 31standalone. 32 33There are cases when you want to in-place initialize a struct. For example when it is very big 34and moving it from the stack is not an option, because it is bigger than the stack itself. 35Another reason would be that you need the address of the object to initialize it. This stands 36in direct conflict with Rust's normal process of first initializing an object and then moving 37it into it's final memory location. For more information, see 38<https://rust-for-linux.com/the-safe-pinned-initialization-problem>. 39 40This library allows you to do in-place initialization safely. 41 42### Nightly Needed for `alloc` feature 43 44This library requires the [`allocator_api` unstable feature] when the `alloc` feature is 45enabled and thus this feature can only be used with a nightly compiler. When enabling the 46`alloc` feature, the user will be required to activate `allocator_api` as well. 47 48[`allocator_api` unstable feature]: https://doc.rust-lang.org/nightly/unstable-book/library-features/allocator-api.html 49 50The feature is enabled by default, thus by default `pin-init` will require a nightly compiler. 51However, using the crate on stable compilers is possible by disabling `alloc`. In practice this 52will require the `std` feature, because stable compilers have neither `Box` nor `Arc` in no-std 53mode. 54 55### Nightly needed for `unsafe-pinned` feature 56 57This feature enables the `Wrapper` implementation on the unstable `core::pin::UnsafePinned` type. 58This requires the [`unsafe_pinned` unstable feature](https://github.com/rust-lang/rust/issues/125735) 59and therefore a nightly compiler. Note that this feature is not enabled by default. 60 61## Overview 62 63To initialize a `struct` with an in-place constructor you will need two things: 64- an in-place constructor, 65- a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`], 66 [`Box<T>`] or any other smart pointer that supports this library). 67 68To get an in-place constructor there are generally three options: 69- directly creating an in-place constructor using the [`pin_init!`] macro, 70- a custom function/macro returning an in-place constructor provided by someone else, 71- using the unsafe function [`pin_init_from_closure()`] to manually create an initializer. 72 73Aside from pinned initialization, this library also supports in-place construction without 74pinning, the macros/types/functions are generally named like the pinned variants without the 75`pin_` prefix. 76 77## Examples 78 79Throughout the examples we will often make use of the `CMutex` type which can be found in 80`../examples/mutex.rs`. It is essentially a userland rebuild of the `struct mutex` type from 81the Linux kernel. It also uses a wait list and a basic spinlock. Importantly the wait list 82requires it to be pinned to be locked and thus is a prime candidate for using this library. 83 84### Using the [`pin_init!`] macro 85 86If you want to use [`PinInit`], then you will have to annotate your `struct` with 87`#[`[`pin_data`]`]`. It is a macro that uses `#[pin]` as a marker for 88[structurally pinned fields]. After doing this, you can then create an in-place constructor via 89[`pin_init!`]. The syntax is almost the same as normal `struct` initializers. The difference is 90that you need to write `<-` instead of `:` for fields that you want to initialize in-place. 91 92```rust 93use pin_init::{pin_data, pin_init, InPlaceInit}; 94 95#[pin_data] 96struct Foo { 97 #[pin] 98 a: CMutex<usize>, 99 b: u32, 100} 101 102let foo = pin_init!(Foo { 103 a <- CMutex::new(42), 104 b: 24, 105}); 106``` 107 108`foo` now is of the type [`impl PinInit<Foo>`]. We can now use any smart pointer that we like 109(or just the stack) to actually initialize a `Foo`: 110 111```rust 112let foo: Result<Pin<Box<Foo>>, AllocError> = Box::pin_init(foo); 113``` 114 115For more information see the [`pin_init!`] macro. 116 117### Using a custom function/macro that returns an initializer 118 119Many types that use this library supply a function/macro that returns an initializer, because 120the above method only works for types where you can access the fields. 121 122```rust 123let mtx: Result<Pin<Arc<CMutex<usize>>>, _> = Arc::pin_init(CMutex::new(42)); 124``` 125 126To declare an init macro/function you just return an [`impl PinInit<T, E>`]: 127 128```rust 129#[pin_data] 130struct DriverData { 131 #[pin] 132 status: CMutex<i32>, 133 buffer: Box<[u8; 1_000_000]>, 134} 135 136impl DriverData { 137 fn new() -> impl PinInit<Self, Error> { 138 try_pin_init!(Self { 139 status <- CMutex::new(0), 140 buffer: Box::init(pin_init::init_zeroed())?, 141 }? Error) 142 } 143} 144``` 145 146### Manual creation of an initializer 147 148Often when working with primitives the previous approaches are not sufficient. That is where 149[`pin_init_from_closure()`] comes in. This `unsafe` function allows you to create a 150[`impl PinInit<T, E>`] directly from a closure. Of course you have to ensure that the closure 151actually does the initialization in the correct way. Here are the things to look out for 152(we are calling the parameter to the closure `slot`): 153- when the closure returns `Ok(())`, then it has completed the initialization successfully, so 154 `slot` now contains a valid bit pattern for the type `T`, 155- when the closure returns `Err(e)`, then the caller may deallocate the memory at `slot`, so 156 you need to take care to clean up anything if your initialization fails mid-way, 157- you may assume that `slot` will stay pinned even after the closure returns until `drop` of 158 `slot` gets called. 159 160```rust 161use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure}; 162use core::{ 163 ptr::addr_of_mut, 164 marker::PhantomPinned, 165 cell::UnsafeCell, 166 pin::Pin, 167 mem::MaybeUninit, 168}; 169mod bindings { 170 #[repr(C)] 171 pub struct foo { 172 /* fields from C ... */ 173 } 174 extern "C" { 175 pub fn init_foo(ptr: *mut foo); 176 pub fn destroy_foo(ptr: *mut foo); 177 #[must_use = "you must check the error return code"] 178 pub fn enable_foo(ptr: *mut foo, flags: u32) -> i32; 179 } 180} 181 182/// # Invariants 183/// 184/// `foo` is always initialized 185#[pin_data(PinnedDrop)] 186pub struct RawFoo { 187 #[pin] 188 _p: PhantomPinned, 189 #[pin] 190 foo: UnsafeCell<MaybeUninit<bindings::foo>>, 191} 192 193impl RawFoo { 194 pub fn new(flags: u32) -> impl PinInit<Self, i32> { 195 // SAFETY: 196 // - when the closure returns `Ok(())`, then it has successfully initialized and 197 // enabled `foo`, 198 // - when it returns `Err(e)`, then it has cleaned up before 199 unsafe { 200 pin_init_from_closure(move |slot: *mut Self| { 201 // `slot` contains uninit memory, avoid creating a reference. 202 let foo = addr_of_mut!((*slot).foo); 203 let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>(); 204 205 // Initialize the `foo` 206 bindings::init_foo(foo); 207 208 // Try to enable it. 209 let err = bindings::enable_foo(foo, flags); 210 if err != 0 { 211 // Enabling has failed, first clean up the foo and then return the error. 212 bindings::destroy_foo(foo); 213 Err(err) 214 } else { 215 // All fields of `RawFoo` have been initialized, since `_p` is a ZST. 216 Ok(()) 217 } 218 }) 219 } 220 } 221} 222 223#[pinned_drop] 224impl PinnedDrop for RawFoo { 225 fn drop(self: Pin<&mut Self>) { 226 // SAFETY: Since `foo` is initialized, destroying is safe. 227 unsafe { bindings::destroy_foo(self.foo.get().cast::<bindings::foo>()) }; 228 } 229} 230``` 231 232For more information on how to use [`pin_init_from_closure()`], take a look at the uses inside 233the `kernel` crate. The [`sync`] module is a good starting point. 234 235[`sync`]: https://rust.docs.kernel.org/kernel/sync/index.html 236[pinning]: https://doc.rust-lang.org/std/pin/index.html 237[structurally pinned fields]: https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning 238[stack]: https://docs.rs/pin-init/latest/pin_init/macro.stack_pin_init.html 239[`impl PinInit<Foo>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html 240[`impl PinInit<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html 241[`impl Init<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.Init.html 242[Rust-for-Linux]: https://rust-for-linux.com/ 243 244<!-- cargo-rdme end --> 245 246<!-- These links are not picked up by cargo-rdme, since they are behind cfgs... --> 247[`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html 248[`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html 249