1750 lines · 57.9 KB · Rust
RawDownload
// SPDX-License-Identifier: Apache-2.0 OR MIT //! Library to safely and fallibly initialize pinned `struct`s using in-place constructors.//!//! [Pinning][pinning] is Rust's way of ensuring data does not move.//!//! It also allows in-place initialization of big `struct`s that would otherwise produce a stack//! overflow.//!//! This library's main use-case is in [Rust-for-Linux]. Although this version can be used//! standalone.//!//! There are cases when you want to in-place initialize a struct. For example when it is very big//! and moving it from the stack is not an option, because it is bigger than the stack itself.//! Another reason would be that you need the address of the object to initialize it. This stands//! in direct conflict with Rust's normal process of first initializing an object and then moving//! it into it's final memory location. For more information, see//! <https://rust-for-linux.com/the-safe-pinned-initialization-problem>.//!//! This library allows you to do in-place initialization safely.//!//! ## Nightly Needed for `alloc` feature//!//! This library requires the [`allocator_api` unstable feature] when the `alloc` feature is//! enabled and thus this feature can only be used with a nightly compiler. When enabling the//! `alloc` feature, the user will be required to activate `allocator_api` as well.//!//! [`allocator_api` unstable feature]: https://doc.rust-lang.org/nightly/unstable-book/library-features/allocator-api.html//!//! The feature is enabled by default, thus by default `pin-init` will require a nightly compiler.//! However, using the crate on stable compilers is possible by disabling `alloc`. In practice this//! will require the `std` feature, because stable compilers have neither `Box` nor `Arc` in no-std//! mode.//!//! ## Nightly needed for `unsafe-pinned` feature//!//! This feature enables the `Wrapper` implementation on the unstable `core::pin::UnsafePinned` type.//! This requires the [`unsafe_pinned` unstable feature](https://github.com/rust-lang/rust/issues/125735)//! and therefore a nightly compiler. Note that this feature is not enabled by default.//!//! # Overview//!//! To initialize a `struct` with an in-place constructor you will need two things://! - an in-place constructor,//! - a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`],//!   [`Box<T>`] or any other smart pointer that supports this library).//!//! To get an in-place constructor there are generally three options://! - directly creating an in-place constructor using the [`pin_init!`] macro,//! - a custom function/macro returning an in-place constructor provided by someone else,//! - using the unsafe function [`pin_init_from_closure()`] to manually create an initializer.//!//! Aside from pinned initialization, this library also supports in-place construction without//! pinning, the macros/types/functions are generally named like the pinned variants without the//! `pin_` prefix.//!//! # Examples//!//! Throughout the examples we will often make use of the `CMutex` type which can be found in//! `../examples/mutex.rs`. It is essentially a userland rebuild of the `struct mutex` type from//! the Linux kernel. It also uses a wait list and a basic spinlock. Importantly the wait list//! requires it to be pinned to be locked and thus is a prime candidate for using this library.//!//! ## Using the [`pin_init!`] macro//!//! If you want to use [`PinInit`], then you will have to annotate your `struct` with//! `#[`[`pin_data`]`]`. It is a macro that uses `#[pin]` as a marker for//! [structurally pinned fields]. After doing this, you can then create an in-place constructor via//! [`pin_init!`]. The syntax is almost the same as normal `struct` initializers. The difference is//! that you need to write `<-` instead of `:` for fields that you want to initialize in-place.//!//! ```rust//! # #![expect(clippy::disallowed_names)]//! # #![feature(allocator_api)]//! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;//! # use core::pin::Pin;//! use pin_init::{pin_data, pin_init, InPlaceInit};//!//! #[pin_data]//! struct Foo {//!     #[pin]//!     a: CMutex<usize>,//!     b: u32,//! }//!//! let foo = pin_init!(Foo {//!     a <- CMutex::new(42),//!     b: 24,//! });//! # let _ = Box::pin_init(foo);//! ```//!//! `foo` now is of the type [`impl PinInit<Foo>`]. We can now use any smart pointer that we like//! (or just the stack) to actually initialize a `Foo`://!//! ```rust//! # #![expect(clippy::disallowed_names)]//! # #![feature(allocator_api)]//! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;//! # use core::{alloc::AllocError, pin::Pin};//! # use pin_init::*;//! #//! # #[pin_data]//! # struct Foo {//! #     #[pin]//! #     a: CMutex<usize>,//! #     b: u32,//! # }//! #//! # let foo = pin_init!(Foo {//! #     a <- CMutex::new(42),//! #     b: 24,//! # });//! let foo: Result<Pin<Box<Foo>>, AllocError> = Box::pin_init(foo);//! ```//!//! For more information see the [`pin_init!`] macro.//!//! ## Using a custom function/macro that returns an initializer//!//! Many types that use this library supply a function/macro that returns an initializer, because//! the above method only works for types where you can access the fields.//!//! ```rust//! # #![feature(allocator_api)]//! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;//! # use pin_init::*;//! # use std::sync::Arc;//! # use core::pin::Pin;//! let mtx: Result<Pin<Arc<CMutex<usize>>>, _> = Arc::pin_init(CMutex::new(42));//! ```//!//! To declare an init macro/function you just return an [`impl PinInit<T, E>`]://!//! ```rust//! # #![feature(allocator_api)]//! # use pin_init::*;//! # #[path = "../examples/error.rs"] mod error; use error::Error;//! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;//! #[pin_data]//! struct DriverData {//!     #[pin]//!     status: CMutex<i32>,//!     buffer: Box<[u8; 1_000_000]>,//! }//!//! impl DriverData {//!     fn new() -> impl PinInit<Self, Error> {//!         pin_init!(Self {//!             status <- CMutex::new(0),//!             buffer: Box::init(pin_init::init_zeroed())?,//!         }? Error)//!     }//! }//! ```//!//! ## Manual creation of an initializer//!//! Often when working with primitives the previous approaches are not sufficient. That is where//! [`pin_init_from_closure()`] comes in. This `unsafe` function allows you to create a//! [`impl PinInit<T, E>`] directly from a closure. Of course you have to ensure that the closure//! actually does the initialization in the correct way. Here are the things to look out for//! (we are calling the parameter to the closure `slot`)://! - when the closure returns `Ok(())`, then it has completed the initialization successfully, so//!   `slot` now contains a valid bit pattern for the type `T`,//! - when the closure returns `Err(e)`, then the caller may deallocate the memory at `slot`, so//!   you need to take care to clean up anything if your initialization fails mid-way,//! - you may assume that `slot` will stay pinned even after the closure returns until `drop` of//!   `slot` gets called.//!//! ```rust//! # #![feature(extern_types)]//! use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};//! use core::{//!     marker::PhantomPinned,//!     cell::UnsafeCell,//!     pin::Pin,//!     mem::MaybeUninit,//! };//! mod bindings {//!     #[repr(C)]//!     pub struct foo {//!         /* fields from C ... *///!     }//!     extern "C" {//!         pub fn init_foo(ptr: *mut foo);//!         pub fn destroy_foo(ptr: *mut foo);//!         #[must_use = "you must check the error return code"]//!         pub fn enable_foo(ptr: *mut foo, flags: u32) -> i32;//!     }//! }//!//! /// # Invariants//! /////! /// `foo` is always initialized//! #[pin_data(PinnedDrop)]//! pub struct RawFoo {//!     #[pin]//!     _p: PhantomPinned,//!     #[pin]//!     foo: UnsafeCell<MaybeUninit<bindings::foo>>,//! }//!//! impl RawFoo {//!     pub fn new(flags: u32) -> impl PinInit<Self, i32> {//!         // SAFETY://!         // - when the closure returns `Ok(())`, then it has successfully initialized and//!         //   enabled `foo`,//!         // - when it returns `Err(e)`, then it has cleaned up before//!         unsafe {//!             pin_init_from_closure(move |slot: *mut Self| {//!                 // `slot` contains uninit memory, avoid creating a reference.//!                 let foo = &raw mut (*slot).foo;//!                 let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>();//!//!                 // Initialize the `foo`//!                 bindings::init_foo(foo);//!//!                 // Try to enable it.//!                 let err = bindings::enable_foo(foo, flags);//!                 if err != 0 {//!                     // Enabling has failed, first clean up the foo and then return the error.//!                     bindings::destroy_foo(foo);//!                     Err(err)//!                 } else {//!                     // All fields of `RawFoo` have been initialized, since `_p` is a ZST.//!                     Ok(())//!                 }//!             })//!         }//!     }//! }//!//! #[pinned_drop]//! impl PinnedDrop for RawFoo {//!     fn drop(self: Pin<&mut Self>) {//!         // SAFETY: Since `foo` is initialized, destroying is safe.//!         unsafe { bindings::destroy_foo(self.foo.get().cast::<bindings::foo>()) };//!     }//! }//! ```//!//! For more information on how to use [`pin_init_from_closure()`], take a look at the uses inside//! the `kernel` crate. The [`sync`] module is a good starting point.//!//! [`sync`]: https://rust.docs.kernel.org/kernel/sync/index.html//! [pinning]: https://doc.rust-lang.org/std/pin/index.html//! [structurally pinned fields]://!     https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning//! [stack]: crate::stack_pin_init#![cfg_attr(    kernel,    doc = "[`Arc<T>`]: https://rust.docs.kernel.org/kernel/sync/struct.Arc.html")]#![cfg_attr(    kernel,    doc = "[`Box<T>`]: https://rust.docs.kernel.org/kernel/alloc/kbox/struct.Box.html")]#![cfg_attr(not(kernel), doc = "[`Arc<T>`]: alloc::alloc::sync::Arc")]#![cfg_attr(not(kernel), doc = "[`Box<T>`]: alloc::alloc::boxed::Box")]//! [`impl PinInit<Foo>`]: crate::PinInit//! [`impl PinInit<T, E>`]: crate::PinInit//! [`impl Init<T, E>`]: crate::Init//! [Rust-for-Linux]: https://rust-for-linux.com/ #![forbid(missing_docs, unsafe_op_in_unsafe_fn)]#![cfg_attr(not(feature = "std"), no_std)]#![cfg_attr(feature = "alloc", feature(allocator_api))]#![cfg_attr(    all(feature = "unsafe-pinned", CONFIG_RUSTC_HAS_UNSAFE_PINNED),    feature(unsafe_pinned))]#![cfg_attr(all(USE_RUSTC_FEATURES, doc), allow(internal_features))]#![cfg_attr(all(USE_RUSTC_FEATURES, doc), feature(rustdoc_internals))] use core::{    cell::UnsafeCell,    convert::Infallible,    marker::PhantomData,    mem::MaybeUninit,    num::*,    pin::Pin,    ptr::{self, NonNull},}; // This is used by doc-tests -- the proc-macros expand to `::pin_init::...` and without this the// doc-tests wouldn't have an extern crate named `pin_init`.#[allow(unused_extern_crates)]extern crate self as pin_init; #[doc(hidden)]pub mod __internal; #[cfg(any(feature = "std", feature = "alloc"))]mod alloc;#[cfg(any(feature = "std", feature = "alloc"))]pub use alloc::InPlaceInit; /// Used to specify the pinning information of the fields of a struct.////// This is somewhat similar in purpose as/// [pin-project-lite](https://crates.io/crates/pin-project-lite)./// Place this macro on a struct definition and then `#[pin]` in front of the attributes of each/// field you want to structurally pin.////// This macro enables the use of the [`pin_init!`] macro. When pin-initializing a `struct`,/// then `#[pin]` directs the type of initializer that is required.////// If your `struct` implements `Drop`, then you need to add `PinnedDrop` as arguments to this/// macro, and change your `Drop` implementation to `PinnedDrop` annotated with/// `#[`[`macro@pinned_drop`]`]`, since dropping pinned values requires extra care.////// # Examples////// ```/// # #![feature(allocator_api)]/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;/// use pin_init::pin_data;////// enum Command {///     /* ... *//// }////// #[pin_data]/// struct DriverData {///     #[pin]///     queue: CMutex<Vec<Command>>,///     buf: Box<[u8; 1024 * 1024]>,/// }/// ```////// ```/// # #![feature(allocator_api)]/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;/// # mod bindings { pub struct info; pub unsafe fn destroy_info(_: *mut info) {} }/// use core::pin::Pin;/// use pin_init::{pin_data, pinned_drop, PinnedDrop};////// enum Command {///     /* ... *//// }////// #[pin_data(PinnedDrop)]/// struct DriverData {///     #[pin]///     queue: CMutex<Vec<Command>>,///     buf: Box<[u8; 1024 * 1024]>,///     raw_info: *mut bindings::info,/// }////// #[pinned_drop]/// impl PinnedDrop for DriverData {///     fn drop(self: Pin<&mut Self>) {///         unsafe { bindings::destroy_info(self.raw_info) };///     }/// }/// ```pub use ::pin_init_internal::pin_data; /// Used to implement `PinnedDrop` safely.////// Only works on structs that are annotated via `#[`[`macro@pin_data`]`]`.////// # Examples////// ```/// # #![feature(allocator_api)]/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;/// # mod bindings { pub struct info; pub unsafe fn destroy_info(_: *mut info) {} }/// use core::pin::Pin;/// use pin_init::{pin_data, pinned_drop, PinnedDrop};////// enum Command {///     /* ... *//// }////// #[pin_data(PinnedDrop)]/// struct DriverData {///     #[pin]///     queue: CMutex<Vec<Command>>,///     buf: Box<[u8; 1024 * 1024]>,///     raw_info: *mut bindings::info,/// }////// #[pinned_drop]/// impl PinnedDrop for DriverData {///     fn drop(self: Pin<&mut Self>) {///         unsafe { bindings::destroy_info(self.raw_info) };///     }/// }/// ```pub use ::pin_init_internal::pinned_drop; /// Derives the [`Zeroable`] trait for the given `struct` or `union`.////// This can only be used for `struct`s/`union`s where every field implements the [`Zeroable`]/// trait.////// # Examples////// ```/// use pin_init::Zeroable;////// #[derive(Zeroable)]/// pub struct DriverData {///     pub(crate) id: i64,///     buf_ptr: *mut u8,///     len: usize,/// }/// ```////// ```/// use pin_init::Zeroable;////// #[derive(Zeroable)]/// pub union SignCast {///     signed: i64,///     unsigned: u64,/// }/// ```pub use ::pin_init_internal::Zeroable; /// Derives the [`Zeroable`] trait for the given `struct` or `union` if all fields implement/// [`Zeroable`].////// Contrary to the derive macro named [`macro@Zeroable`], this one silently fails when a field/// doesn't implement [`Zeroable`].////// # Examples////// ```/// use pin_init::MaybeZeroable;////// // implements `Zeroable`/// #[derive(MaybeZeroable)]/// pub struct DriverData {///     pub(crate) id: i64,///     buf_ptr: *mut u8,///     len: usize,/// }////// // does not implement `Zeroable`/// #[derive(MaybeZeroable)]/// pub struct DriverData2 {///     pub(crate) id: i64,///     buf_ptr: *mut u8,///     len: usize,///     // this field doesn't implement `Zeroable`///     other_data: &'static i32,/// }/// ```pub use ::pin_init_internal::MaybeZeroable; /// Initialize and pin a type directly on the stack.////// # Examples////// ```rust/// # #![expect(clippy::disallowed_names)]/// # #![feature(allocator_api)]/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;/// # use pin_init::*;/// # use core::pin::Pin;/// #[pin_data]/// struct Foo {///     #[pin]///     a: CMutex<usize>,///     b: Bar,/// }////// #[pin_data]/// struct Bar {///     x: u32,/// }////// stack_pin_init!(let foo = pin_init!(Foo {///     a <- CMutex::new(42),///     b: Bar {///         x: 64,///     },/// }));/// let foo: Pin<&mut Foo> = foo;/// println!("a: {}", &*foo.a.lock());/// ```////// # Syntax////// A normal `let` binding with optional type annotation. The expression is expected to implement/// [`PinInit`]/[`Init`] with the error type [`Infallible`]. If you want to use a different error/// type, then use [`stack_try_pin_init!`].#[macro_export]macro_rules! stack_pin_init {    (let $var:ident $(: $t:ty)? = $val:expr) => {        let val = $val;        let mut $var = ::core::pin::pin!($crate::__internal::StackInit$(::<$t>)?::uninit());        let mut $var = match $crate::__internal::StackInit::init($var, val) {            Ok(res) => res,            Err(x) => {                let x: ::core::convert::Infallible = x;                match x {}

Lines 1–500 of 1750.