xref: /linux/rust/pin-init/README.md (revision 09808839c7aa6695ceff5cd822c18b0d9550184d)
1[![Crates.io](https://img.shields.io/crates/v/pin-init.svg)](https://crates.io/crates/pin-init)
2[![Documentation](https://docs.rs/pin-init/badge.svg)](https://docs.rs/pin-init/)
3[![Dependency status](https://deps.rs/repo/github/Rust-for-Linux/pin-init/status.svg)](https://deps.rs/repo/github/Rust-for-Linux/pin-init)
4![License](https://img.shields.io/crates/l/pin-init)
5[![Toolchain](https://img.shields.io/badge/toolchain-nightly-red)](#nightly-only)
6![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/Rust-for-Linux/pin-init/test.yml)
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 `legacy` 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        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    marker::PhantomPinned,
164    cell::UnsafeCell,
165    pin::Pin,
166    mem::MaybeUninit,
167};
168mod bindings {
169    #[repr(C)]
170    pub struct foo {
171        /* fields from C ... */
172    }
173    extern "C" {
174        pub fn init_foo(ptr: *mut foo);
175        pub fn destroy_foo(ptr: *mut foo);
176        #[must_use = "you must check the error return code"]
177        pub fn enable_foo(ptr: *mut foo, flags: u32) -> i32;
178    }
179}
180
181/// # Invariants
182///
183/// `foo` is always initialized
184#[pin_data(PinnedDrop)]
185pub struct RawFoo {
186    #[pin]
187    _p: PhantomPinned,
188    #[pin]
189    foo: UnsafeCell<MaybeUninit<bindings::foo>>,
190}
191
192impl RawFoo {
193    pub fn new(flags: u32) -> impl PinInit<Self, i32> {
194        // SAFETY:
195        // - when the closure returns `Ok(())`, then it has successfully initialized and
196        //   enabled `foo`,
197        // - when it returns `Err(e)`, then it has cleaned up before
198        unsafe {
199            pin_init_from_closure(move |slot: *mut Self| {
200                // `slot` contains uninit memory, avoid creating a reference.
201                let foo = &raw mut (*slot).foo;
202                let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>();
203
204                // Initialize the `foo`
205                bindings::init_foo(foo);
206
207                // Try to enable it.
208                let err = bindings::enable_foo(foo, flags);
209                if err != 0 {
210                    // Enabling has failed, first clean up the foo and then return the error.
211                    bindings::destroy_foo(foo);
212                    Err(err)
213                } else {
214                    // All fields of `RawFoo` have been initialized, since `_p` is a ZST.
215                    Ok(())
216                }
217            })
218        }
219    }
220}
221
222#[pinned_drop]
223impl PinnedDrop for RawFoo {
224    fn drop(self: Pin<&mut Self>) {
225        // SAFETY: Since `foo` is initialized, destroying is safe.
226        unsafe { bindings::destroy_foo(self.foo.get().cast::<bindings::foo>()) };
227    }
228}
229```
230
231For more information on how to use [`pin_init_from_closure()`], take a look at the uses inside
232the `kernel` crate. The [`sync`] module is a good starting point.
233
234[`sync`]: https://rust.docs.kernel.org/kernel/sync/index.html
235[pinning]: https://doc.rust-lang.org/std/pin/index.html
236[structurally pinned fields]: https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning
237[stack]: https://docs.rs/pin-init/latest/pin_init/macro.stack_pin_init.html
238[`impl PinInit<Foo>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html
239[`impl PinInit<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html
240[`impl Init<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.Init.html
241[Rust-for-Linux]: https://rust-for-linux.com/
242
243<!-- cargo-rdme end -->
244
245<!-- These links are not picked up by cargo-rdme, since they are behind cfgs... -->
246[`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html
247[`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html
248