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