1482 lines · 49.6 KB · Rust
RawDownload
// SPDX-License-Identifier: Apache-2.0 OR MIT //! API to safely and fallibly initialize pinned `struct`s using in-place constructors.//!//! It also allows in-place initialization of big `struct`s that would otherwise produce a stack//! overflow.//!//! Most `struct`s from the [`sync`] module need to be pinned, because they contain self-referential//! `struct`s from C. [Pinning][pinning] is Rust's way of ensuring data does not move.//!//! # 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>`],//!   [`UniqueArc<T>`], [`Box<T>`] or any other smart pointer that implements [`InPlaceInit`]).//!//! 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 API also supports in-place construction without pinning,//! the macros/types/functions are generally named like the pinned variants without the `pin`//! prefix.//!//! # Examples//!//! ## 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//! # #![allow(clippy::disallowed_names)]//! use kernel::sync::{new_mutex, Mutex};//! # use core::pin::Pin;//! #[pin_data]//! struct Foo {//!     #[pin]//!     a: Mutex<usize>,//!     b: u32,//! }//!//! let foo = pin_init!(Foo {//!     a <- new_mutex!(42, "Foo::a"),//!     b: 24,//! });//! ```//!//! `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//! # #![allow(clippy::disallowed_names)]//! # use kernel::sync::{new_mutex, Mutex};//! # use core::pin::Pin;//! # #[pin_data]//! # struct Foo {//! #     #[pin]//! #     a: Mutex<usize>,//! #     b: u32,//! # }//! # let foo = pin_init!(Foo {//! #     a <- new_mutex!(42, "Foo::a"),//! #     b: 24,//! # });//! let foo: Result<Pin<Box<Foo>>> = Box::pin_init(foo, GFP_KERNEL);//! ```//!//! For more information see the [`pin_init!`] macro.//!//! ## Using a custom function/macro that returns an initializer//!//! Many types from the kernel supply a function/macro that returns an initializer, because the//! above method only works for types where you can access the fields.//!//! ```rust//! # use kernel::sync::{new_mutex, Arc, Mutex};//! let mtx: Result<Arc<Mutex<usize>>> =//!     Arc::pin_init(new_mutex!(42, "example::mtx"), GFP_KERNEL);//! ```//!//! To declare an init macro/function you just return an [`impl PinInit<T, E>`]://!//! ```rust//! # #![allow(clippy::disallowed_names)]//! # use kernel::{sync::Mutex, new_mutex, init::PinInit, try_pin_init};//! #[pin_data]//! struct DriverData {//!     #[pin]//!     status: Mutex<i32>,//!     buffer: Box<[u8; 1_000_000]>,//! }//!//! impl DriverData {//!     fn new() -> impl PinInit<Self, Error> {//!         try_pin_init!(Self {//!             status <- new_mutex!(0, "DriverData::status"),//!             buffer: Box::init(kernel::init::zeroed(), GFP_KERNEL)?,//!         })//!     }//! }//! ```//!//! ## 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//! # #![allow(unreachable_pub, clippy::disallowed_names)]//! use kernel::{init, types::Opaque};//! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin};//! # mod bindings {//! #     #![allow(non_camel_case_types)]//! #     pub struct foo;//! #     pub unsafe fn init_foo(_ptr: *mut foo) {}//! #     pub unsafe fn destroy_foo(_ptr: *mut foo) {}//! #     pub unsafe fn enable_foo(_ptr: *mut foo, _flags: u32) -> i32 { 0 }//! # }//! # // `Error::from_errno` is `pub(crate)` in the `kernel` crate, thus provide a workaround.//! # trait FromErrno {//! #     fn from_errno(errno: core::ffi::c_int) -> Error {//! #         // Dummy error that can be constructed outside the `kernel` crate.//! #         Error::from(core::fmt::Error)//! #     }//! # }//! # impl FromErrno for Error {}//! /// # Invariants//! /////! /// `foo` is always initialized//! #[pin_data(PinnedDrop)]//! pub struct RawFoo {//!     #[pin]//!     foo: Opaque<bindings::foo>,//!     #[pin]//!     _p: PhantomPinned,//! }//!//! impl RawFoo {//!     pub fn new(flags: u32) -> impl PinInit<Self, Error> {//!         // 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 {//!             init::pin_init_from_closure(move |slot: *mut Self| {//!                 // `slot` contains uninit memory, avoid creating a reference.//!                 let foo = addr_of_mut!((*slot).foo);//!//!                 // Initialize the `foo`//!                 bindings::init_foo(Opaque::raw_get(foo));//!//!                 // Try to enable it.//!                 let err = bindings::enable_foo(Opaque::raw_get(foo), flags);//!                 if err != 0 {//!                     // Enabling has failed, first clean up the foo and then return the error.//!                     bindings::destroy_foo(Opaque::raw_get(foo));//!                     return Err(Error::from_errno(err));//!                 }//!//!                 // 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()) };//!     }//! }//! ```//!//! For the special case where initializing a field is a single FFI-function call that cannot fail,//! there exist the helper function [`Opaque::ffi_init`]. This function initialize a single//! [`Opaque`] field by just delegating to the supplied closure. You can use these in combination//! with [`pin_init!`].//!//! 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`]: kernel::sync//! [pinning]: https://doc.rust-lang.org/std/pin/index.html//! [structurally pinned fields]://!     https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field//! [stack]: crate::stack_pin_init//! [`Arc<T>`]: crate::sync::Arc//! [`impl PinInit<Foo>`]: PinInit//! [`impl PinInit<T, E>`]: PinInit//! [`impl Init<T, E>`]: Init//! [`Opaque`]: kernel::types::Opaque//! [`Opaque::ffi_init`]: kernel::types::Opaque::ffi_init//! [`pin_data`]: ::macros::pin_data//! [`pin_init!`]: crate::pin_init! use crate::{    alloc::{box_ext::BoxExt, AllocError, Flags},    error::{self, Error},    sync::Arc,    sync::UniqueArc,    types::{Opaque, ScopeGuard},};use alloc::boxed::Box;use core::{    cell::UnsafeCell,    convert::Infallible,    marker::PhantomData,    mem::MaybeUninit,    num::*,    pin::Pin,    ptr::{self, NonNull},}; #[doc(hidden)]pub mod __internal;#[doc(hidden)]pub mod macros; /// Initialize and pin a type directly on the stack.////// # Examples////// ```rust/// # #![allow(clippy::disallowed_names)]/// # use kernel::{init, macros::pin_data, pin_init, stack_pin_init, init::*, sync::Mutex, new_mutex};/// # use core::pin::Pin;/// #[pin_data]/// struct Foo {///     #[pin]///     a: Mutex<usize>,///     b: Bar,/// }////// #[pin_data]/// struct Bar {///     x: u32,/// }////// stack_pin_init!(let foo = pin_init!(Foo {///     a <- new_mutex!(42),///     b: Bar {///         x: 64,///     },/// }));/// let foo: Pin<&mut Foo> = foo;/// pr_info!("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!`].////// [`stack_try_pin_init!`]: crate::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::init::__internal::StackInit$(::<$t>)?::uninit());        let mut $var = match $crate::init::__internal::StackInit::init($var, val) {            Ok(res) => res,            Err(x) => {                let x: ::core::convert::Infallible = x;                match x {}            }        };    };} /// Initialize and pin a type directly on the stack.////// # Examples////// ```rust,ignore/// # #![allow(clippy::disallowed_names)]/// # use kernel::{init, pin_init, stack_try_pin_init, init::*, sync::Mutex, new_mutex};/// # use macros::pin_data;/// # use core::{alloc::AllocError, pin::Pin};/// #[pin_data]/// struct Foo {///     #[pin]///     a: Mutex<usize>,///     b: Box<Bar>,/// }////// struct Bar {///     x: u32,/// }////// stack_try_pin_init!(let foo: Result<Pin<&mut Foo>, AllocError> = pin_init!(Foo {///     a <- new_mutex!(42),///     b: Box::new(Bar {///         x: 64,///     }, GFP_KERNEL)?,/// }));/// let foo = foo.unwrap();/// pr_info!("a: {}", &*foo.a.lock());/// ```////// ```rust,ignore/// # #![allow(clippy::disallowed_names)]/// # use kernel::{init, pin_init, stack_try_pin_init, init::*, sync::Mutex, new_mutex};/// # use macros::pin_data;/// # use core::{alloc::AllocError, pin::Pin};/// #[pin_data]/// struct Foo {///     #[pin]///     a: Mutex<usize>,///     b: Box<Bar>,/// }////// struct Bar {///     x: u32,/// }////// stack_try_pin_init!(let foo: Pin<&mut Foo> =? pin_init!(Foo {///     a <- new_mutex!(42),///     b: Box::new(Bar {///         x: 64,///     }, GFP_KERNEL)?,/// }));/// pr_info!("a: {}", &*foo.a.lock());/// # Ok::<_, AllocError>(())/// ```////// # Syntax////// A normal `let` binding with optional type annotation. The expression is expected to implement/// [`PinInit`]/[`Init`]. This macro assigns a result to the given variable, adding a `?` after the/// `=` will propagate this error.#[macro_export]macro_rules! stack_try_pin_init {    (let $var:ident $(: $t:ty)? = $val:expr) => {        let val = $val;        let mut $var = ::core::pin::pin!($crate::init::__internal::StackInit$(::<$t>)?::uninit());        let mut $var = $crate::init::__internal::StackInit::init($var, val);    };    (let $var:ident $(: $t:ty)? =? $val:expr) => {        let val = $val;        let mut $var = ::core::pin::pin!($crate::init::__internal::StackInit$(::<$t>)?::uninit());        let mut $var = $crate::init::__internal::StackInit::init($var, val)?;    };} /// Construct an in-place, pinned initializer for `struct`s.////// This macro defaults the error to [`Infallible`]. If you need [`Error`], then use/// [`try_pin_init!`].////// The syntax is almost identical to that of a normal `struct` initializer:////// ```rust/// # #![allow(clippy::disallowed_names)]/// # use kernel::{init, pin_init, macros::pin_data, init::*};/// # use core::pin::Pin;/// #[pin_data]/// struct Foo {///     a: usize,///     b: Bar,/// }////// #[pin_data]/// struct Bar {///     x: u32,/// }////// # fn demo() -> impl PinInit<Foo> {/// let a = 42;////// let initializer = pin_init!(Foo {///     a,///     b: Bar {///         x: 64,///     },/// });/// # initializer }/// # Box::pin_init(demo(), GFP_KERNEL).unwrap();/// ```////// Arbitrary Rust expressions can be used to set the value of a variable.////// The fields are initialized in the order that they appear in the initializer. So it is possible/// to read already initialized fields using raw pointers.////// IMPORTANT: You are not allowed to create references to fields of the struct inside of the/// initializer.////// # Init-functions////// When working with this API it is often desired to let others construct your types without/// giving access to all fields. This is where you would normally write a plain function `new`/// that would return a new instance of your type. With this API that is also possible./// However, there are a few extra things to keep in mind.////// To create an initializer function, simply declare it like this:////// ```rust/// # #![allow(clippy::disallowed_names)]/// # use kernel::{init, pin_init, init::*};/// # use core::pin::Pin;/// # #[pin_data]/// # struct Foo {/// #     a: usize,/// #     b: Bar,/// # }/// # #[pin_data]/// # struct Bar {/// #     x: u32,/// # }/// impl Foo {///     fn new() -> impl PinInit<Self> {///         pin_init!(Self {///             a: 42,///             b: Bar {///                 x: 64,///             },///         })///     }/// }/// ```////// Users of `Foo` can now create it like this:////// ```rust/// # #![allow(clippy::disallowed_names)]/// # use kernel::{init, pin_init, macros::pin_data, init::*};/// # use core::pin::Pin;/// # #[pin_data]/// # struct Foo {/// #     a: usize,/// #     b: Bar,/// # }/// # #[pin_data]/// # struct Bar {/// #     x: u32,/// # }/// # impl Foo {/// #     fn new() -> impl PinInit<Self> {/// #         pin_init!(Self {/// #             a: 42,/// #             b: Bar {/// #                 x: 64,/// #             },/// #         })/// #     }/// # }/// let foo = Box::pin_init(Foo::new(), GFP_KERNEL);/// ```////// They can also easily embed it into their own `struct`s:////// ```rust/// # #![allow(clippy::disallowed_names)]/// # use kernel::{init, pin_init, macros::pin_data, init::*};/// # use core::pin::Pin;/// # #[pin_data]/// # struct Foo {/// #     a: usize,/// #     b: Bar,/// # }/// # #[pin_data]/// # struct Bar {/// #     x: u32,/// # }/// # impl Foo {/// #     fn new() -> impl PinInit<Self> {/// #         pin_init!(Self {/// #             a: 42,/// #             b: Bar {/// #                 x: 64,/// #             },/// #         })/// #     }/// # }/// #[pin_data]/// struct FooContainer {///     #[pin]///     foo1: Foo,///     #[pin]///     foo2: Foo,///     other: u32,/// }

Lines 1–500 of 1482.