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