Skip to content

Commit 02c01c0

Browse files
BennoLossinojeda
authored andcommitted
rust: pin-init: synchronize documentation with the user-space version
Synchronize documentation and examples with the user-space version. Signed-off-by: Benno Lossin <benno.lossin@proton.me> Reviewed-by: Fiona Behrens <me@kloenk.dev> Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org> Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Link: https://lore.kernel.org/r/20250308110339.2997091-18-benno.lossin@proton.me Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
1 parent 9b2299a commit 02c01c0

File tree

3 files changed

+115
-54
lines changed

3 files changed

+115
-54
lines changed

rust/pin-init/src/__internal.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
// SPDX-License-Identifier: Apache-2.0 OR MIT
22

3-
//! This module contains API-internal items for pin-init.
3+
//! This module contains library internal items.
44
//!
5-
//! These items must not be used outside of
6-
//! - `kernel/init.rs`
7-
//! - `macros/pin_data.rs`
8-
//! - `macros/pinned_drop.rs`
5+
//! These items must not be used outside of this crate and the pin-init-internal crate located at
6+
//! `../internal`.
97
108
use super::*;
119

rust/pin-init/src/lib.rs

Lines changed: 102 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,37 @@
11
// SPDX-License-Identifier: Apache-2.0 OR MIT
22

3-
//! API to safely and fallibly initialize pinned `struct`s using in-place constructors.
3+
//! Library to safely and fallibly initialize pinned `struct`s using in-place constructors.
4+
//!
5+
//! [Pinning][pinning] is Rust's way of ensuring data does not move.
46
//!
57
//! It also allows in-place initialization of big `struct`s that would otherwise produce a stack
68
//! overflow.
79
//!
10+
//! This library's main use-case is in [Rust-for-Linux]. Although this version can be used
11+
//! standalone.
12+
//!
13+
//! There are cases when you want to in-place initialize a struct. For example when it is very big
14+
//! and moving it from the stack is not an option, because it is bigger than the stack itself.
15+
//! Another reason would be that you need the address of the object to initialize it. This stands
16+
//! in direct conflict with Rust's normal process of first initializing an object and then moving
17+
//! it into it's final memory location. For more information, see
18+
//! <https://rust-for-linux.com/the-safe-pinned-initialization-problem>.
19+
//!
20+
//! This library allows you to do in-place initialization safely.
21+
//!
22+
//! ## Nightly Needed for `alloc` feature
23+
//!
24+
//! This library requires the [`allocator_api` unstable feature] when the `alloc` feature is
25+
//! enabled and thus this feature can only be used with a nightly compiler. When enabling the
26+
//! `alloc` feature, the user will be required to activate `allocator_api` as well.
27+
//!
28+
//! [`allocator_api` unstable feature]: https://doc.rust-lang.org/nightly/unstable-book/library-features/allocator-api.html
29+
//!
30+
//! The feature is enabled by default, thus by default `pin-init` will require a nightly compiler.
31+
//! However, using the crate on stable compilers is possible by disabling `alloc`. In practice this
32+
//! will require the `std` feature, because stable compilers have neither `Box` nor `Arc` in no-std
33+
//! mode.
34+
//!
835
//! # Overview
936
//!
1037
//! To initialize a `struct` with an in-place constructor you will need two things:
@@ -17,12 +44,17 @@
1744
//! - a custom function/macro returning an in-place constructor provided by someone else,
1845
//! - using the unsafe function [`pin_init_from_closure()`] to manually create an initializer.
1946
//!
20-
//! Aside from pinned initialization, this API also supports in-place construction without pinning,
21-
//! the macros/types/functions are generally named like the pinned variants without the `pin`
22-
//! prefix.
47+
//! Aside from pinned initialization, this library also supports in-place construction without
48+
//! pinning, the macros/types/functions are generally named like the pinned variants without the
49+
//! `pin_` prefix.
2350
//!
2451
//! # Examples
2552
//!
53+
//! Throughout the examples we will often make use of the `CMutex` type which can be found in
54+
//! `../examples/mutex.rs`. It is essentially a userland rebuild of the `struct mutex` type from
55+
//! the Linux kernel. It also uses a wait list and a basic spinlock. Importantly the wait list
56+
//! requires it to be pinned to be locked and thus is a prime candidate for using this library.
57+
//!
2658
//! ## Using the [`pin_init!`] macro
2759
//!
2860
//! If you want to use [`PinInit`], then you will have to annotate your `struct` with
@@ -36,7 +68,7 @@
3668
//! # #![feature(allocator_api)]
3769
//! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
3870
//! # use core::pin::Pin;
39-
//! use pin_init::*;
71+
//! use pin_init::{pin_data, pin_init, InPlaceInit};
4072
//!
4173
//! #[pin_data]
4274
//! struct Foo {
@@ -80,8 +112,8 @@
80112
//!
81113
//! ## Using a custom function/macro that returns an initializer
82114
//!
83-
//! Many types from the kernel supply a function/macro that returns an initializer, because the
84-
//! above method only works for types where you can access the fields.
115+
//! Many types that use this library supply a function/macro that returns an initializer, because
116+
//! the above method only works for types where you can access the fields.
85117
//!
86118
//! ```rust,ignore
87119
//! # #![feature(allocator_api)]
@@ -132,7 +164,7 @@
132164
//!
133165
//! ```rust,ignore
134166
//! # #![feature(extern_types)]
135-
//! use pin_init::*;
167+
//! use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};
136168
//! use core::{
137169
//! ptr::addr_of_mut,
138170
//! marker::PhantomPinned,
@@ -141,8 +173,11 @@
141173
//! mem::MaybeUninit,
142174
//! };
143175
//! mod bindings {
176+
//! #[repr(C)]
177+
//! pub struct foo {
178+
//! /* fields from C ... */
179+
//! }
144180
//! extern "C" {
145-
//! pub type foo;
146181
//! pub fn init_foo(ptr: *mut foo);
147182
//! pub fn destroy_foo(ptr: *mut foo);
148183
//! #[must_use = "you must check the error return code"]
@@ -200,6 +235,10 @@
200235
//! }
201236
//! ```
202237
//!
238+
//! For more information on how to use [`pin_init_from_closure()`], take a look at the uses inside
239+
//! the `kernel` crate. The [`sync`] module is a good starting point.
240+
//!
241+
//! [`sync`]: https://rust.docs.kernel.org/kernel/sync/index.html
203242
//! [pinning]: https://doc.rust-lang.org/std/pin/index.html
204243
//! [structurally pinned fields]:
205244
//! https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
@@ -214,11 +253,10 @@
214253
)]
215254
#![cfg_attr(not(kernel), doc = "[`Arc<T>`]: alloc::alloc::sync::Arc")]
216255
#![cfg_attr(not(kernel), doc = "[`Box<T>`]: alloc::alloc::boxed::Box")]
217-
//! [`impl PinInit<Foo>`]: PinInit
218-
//! [`impl PinInit<T, E>`]: PinInit
219-
//! [`impl Init<T, E>`]: Init
220-
//! [`pin_data`]: crate::pin_data
221-
//! [`pin_init!`]: crate::pin_init!
256+
//! [`impl PinInit<Foo>`]: crate::PinInit
257+
//! [`impl PinInit<T, E>`]: crate::PinInit
258+
//! [`impl Init<T, E>`]: crate::Init
259+
//! [Rust-for-Linux]: https://rust-for-linux.com/
222260
223261
#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
224262
#![cfg_attr(
@@ -404,8 +442,6 @@ pub use ::pin_init_internal::Zeroable;
404442
/// A normal `let` binding with optional type annotation. The expression is expected to implement
405443
/// [`PinInit`]/[`Init`] with the error type [`Infallible`]. If you want to use a different error
406444
/// type, then use [`stack_try_pin_init!`].
407-
///
408-
/// [`stack_try_pin_init!`]: crate::stack_try_pin_init!
409445
#[macro_export]
410446
macro_rules! stack_pin_init {
411447
(let $var:ident $(: $t:ty)? = $val:expr) => {
@@ -542,10 +578,10 @@ macro_rules! stack_try_pin_init {
542578
///
543579
/// # Init-functions
544580
///
545-
/// When working with this API it is often desired to let others construct your types without
546-
/// giving access to all fields. This is where you would normally write a plain function `new`
547-
/// that would return a new instance of your type. With this API that is also possible.
548-
/// However, there are a few extra things to keep in mind.
581+
/// When working with this library it is often desired to let others construct your types without
582+
/// giving access to all fields. This is where you would normally write a plain function `new` that
583+
/// would return a new instance of your type. With this library that is also possible. However,
584+
/// there are a few extra things to keep in mind.
549585
///
550586
/// To create an initializer function, simply declare it like this:
551587
///
@@ -674,22 +710,22 @@ macro_rules! stack_try_pin_init {
674710
/// #[pin]
675711
/// pin: PhantomPinned,
676712
/// }
677-
/// pin_init!(&this in Buf {
713+
///
714+
/// let init = pin_init!(&this in Buf {
678715
/// buf: [0; 64],
679716
/// // SAFETY: TODO.
680717
/// ptr: unsafe { addr_of_mut!((*this.as_ptr()).buf).cast() },
681718
/// pin: PhantomPinned,
682719
/// });
683-
/// pin_init!(Buf {
720+
/// let init = pin_init!(Buf {
684721
/// buf: [1; 64],
685722
/// ..Zeroable::zeroed()
686723
/// });
687724
/// ```
688725
///
689-
/// [`try_pin_init!`]: crate::try_pin_init
690726
/// [`NonNull<Self>`]: core::ptr::NonNull
691727
// For a detailed example of how this macro works, see the module documentation of the hidden
692-
// module `__internal` inside of `init/__internal.rs`.
728+
// module `macros` inside of `macros.rs`.
693729
#[macro_export]
694730
macro_rules! pin_init {
695731
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
@@ -719,7 +755,8 @@ macro_rules! pin_init {
719755
/// ```rust,ignore
720756
/// # #![feature(allocator_api)]
721757
/// # #[path = "../examples/error.rs"] mod error; use error::Error;
722-
/// use pin_init::*;
758+
/// use pin_init::{pin_data, try_pin_init, PinInit, InPlaceInit, zeroed};
759+
///
723760
/// #[pin_data]
724761
/// struct BigBuf {
725762
/// big: Box<[u8; 1024 * 1024 * 1024]>,
@@ -730,7 +767,7 @@ macro_rules! pin_init {
730767
/// impl BigBuf {
731768
/// fn new() -> impl PinInit<Self, Error> {
732769
/// try_pin_init!(Self {
733-
/// big: Box::init(init::zeroed())?,
770+
/// big: Box::init(zeroed())?,
734771
/// small: [0; 1024 * 1024],
735772
/// ptr: core::ptr::null_mut(),
736773
/// }? Error)
@@ -739,7 +776,7 @@ macro_rules! pin_init {
739776
/// # let _ = Box::pin_init(BigBuf::new());
740777
/// ```
741778
// For a detailed example of how this macro works, see the module documentation of the hidden
742-
// module `__internal` inside of `init/__internal.rs`.
779+
// module `macros` inside of `macros.rs`.
743780
#[macro_export]
744781
macro_rules! try_pin_init {
745782
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
@@ -772,9 +809,30 @@ macro_rules! try_pin_init {
772809
/// This initializer is for initializing data in-place that might later be moved. If you want to
773810
/// pin-initialize, use [`pin_init!`].
774811
///
775-
/// [`try_init!`]: crate::try_init!
812+
/// # Examples
813+
///
814+
/// ```rust
815+
/// # #![feature(allocator_api)]
816+
/// # #[path = "../examples/error.rs"] mod error; use error::Error;
817+
/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
818+
/// # use pin_init::InPlaceInit;
819+
/// use pin_init::{init, Init, zeroed};
820+
///
821+
/// struct BigBuf {
822+
/// small: [u8; 1024 * 1024],
823+
/// }
824+
///
825+
/// impl BigBuf {
826+
/// fn new() -> impl Init<Self> {
827+
/// init!(Self {
828+
/// small <- zeroed(),
829+
/// })
830+
/// }
831+
/// }
832+
/// # let _ = Box::init(BigBuf::new());
833+
/// ```
776834
// For a detailed example of how this macro works, see the module documentation of the hidden
777-
// module `__internal` inside of `init/__internal.rs`.
835+
// module `macros` inside of `macros.rs`.
778836
#[macro_export]
779837
macro_rules! init {
780838
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
@@ -804,7 +862,9 @@ macro_rules! init {
804862
/// ```rust,ignore
805863
/// # #![feature(allocator_api)]
806864
/// # use core::alloc::AllocError;
807-
/// use pin_init::*;
865+
/// # use pin_init::InPlaceInit;
866+
/// use pin_init::{try_init, Init, zeroed};
867+
///
808868
/// struct BigBuf {
809869
/// big: Box<[u8; 1024 * 1024 * 1024]>,
810870
/// small: [u8; 1024 * 1024],
@@ -818,10 +878,10 @@ macro_rules! init {
818878
/// }? AllocError)
819879
/// }
820880
/// }
881+
/// # let _ = Box::init(BigBuf::new());
821882
/// ```
822-
/// [`try_pin_init!`]: crate::try_pin_init
823883
// For a detailed example of how this macro works, see the module documentation of the hidden
824-
// module `__internal` inside of `init/__internal.rs`.
884+
// module `macros` inside of `macros.rs`.
825885
#[macro_export]
826886
macro_rules! try_init {
827887
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
@@ -847,7 +907,8 @@ macro_rules! try_init {
847907
///
848908
/// This will succeed:
849909
/// ```ignore
850-
/// use pin_init::assert_pinned;
910+
/// use pin_init::{pin_data, assert_pinned};
911+
///
851912
/// #[pin_data]
852913
/// struct MyStruct {
853914
/// #[pin]
@@ -859,7 +920,8 @@ macro_rules! try_init {
859920
///
860921
/// This will fail:
861922
/// ```compile_fail,ignore
862-
/// use pin_init::assert_pinned;
923+
/// use pin_init::{pin_data, assert_pinned};
924+
///
863925
/// #[pin_data]
864926
/// struct MyStruct {
865927
/// some_field: u64,
@@ -872,7 +934,9 @@ macro_rules! try_init {
872934
/// work around this, you may pass the `inline` parameter to the macro. The `inline` parameter can
873935
/// only be used when the macro is invoked from a function body.
874936
/// ```ignore
875-
/// use pin_init::assert_pinned;
937+
/// # use core::pin::Pin;
938+
/// use pin_init::{pin_data, assert_pinned};
939+
///
876940
/// #[pin_data]
877941
/// struct Foo<T> {
878942
/// #[pin]
@@ -1056,14 +1120,15 @@ pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
10561120
///
10571121
/// ```rust,ignore
10581122
/// # #![expect(clippy::disallowed_names)]
1059-
/// use pin_init::{init_from_closure, zeroed};
1123+
/// use pin_init::{init, zeroed, Init};
1124+
///
10601125
/// struct Foo {
10611126
/// buf: [u8; 1_000_000],
10621127
/// }
10631128
///
10641129
/// impl Foo {
10651130
/// fn setup(&mut self) {
1066-
/// pr_info!("Setting up foo");
1131+
/// println!("Setting up foo");
10671132
/// }
10681133
/// }
10691134
///
@@ -1302,8 +1367,6 @@ pub trait InPlaceWrite<T> {
13021367
/// # Safety
13031368
///
13041369
/// This trait must be implemented via the [`pinned_drop`] proc-macro attribute on the impl.
1305-
///
1306-
/// [`pinned_drop`]: crate::pinned_drop
13071370
pub unsafe trait PinnedDrop: __internal::HasPinData {
13081371
/// Executes the pinned destructor of this type.
13091372
///

0 commit comments

Comments
 (0)