summaryrefslogtreecommitdiff
path: root/rust/kernel/init.rs
diff options
context:
space:
mode:
authorBenno Lossin <benno.lossin@proton.me>2025-03-08 11:04:34 +0000
committerMiguel Ojeda <ojeda@kernel.org>2025-03-16 21:59:18 +0100
commit114ca41fe7922ce85fcac30fa2b06b42b4956520 (patch)
treee044016281c0165d1d417bae499d663328cdd746 /rust/kernel/init.rs
parent578eb8b6db13cd923f1ffa80b9e8d32dcc06d35d (diff)
rust: pin-init: move `InPlaceInit` and impls of `InPlaceWrite` into the kernel crate
In order to make pin-init a standalone crate, move kernel-specific code directly into the kernel crate. This includes the `InPlaceInit<T>` trait, its implementations and the implementations of `InPlaceWrite` for `Arc` and `UniqueArc`. All of these use the kernel's error type which will become unavailable in pin-init. Signed-off-by: Benno Lossin <benno.lossin@proton.me> Reviewed-by: Fiona Behrens <me@kloenk.dev> Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Link: https://lore.kernel.org/r/20250308110339.2997091-9-benno.lossin@proton.me Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Diffstat (limited to 'rust/kernel/init.rs')
-rw-r--r--rust/kernel/init.rs55
1 files changed, 55 insertions, 0 deletions
diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs
index d80eccf29100..d8eb6d7873b7 100644
--- a/rust/kernel/init.rs
+++ b/rust/kernel/init.rs
@@ -134,6 +134,61 @@
//! }
//! ```
+use crate::{
+ alloc::{AllocError, Flags},
+ error::{self, Error},
+ init::{init_from_closure, pin_init_from_closure, Init, PinInit},
+};
+
+/// Smart pointer that can initialize memory in-place.
+pub trait InPlaceInit<T>: Sized {
+ /// Pinned version of `Self`.
+ ///
+ /// If a type already implicitly pins its pointee, `Pin<Self>` is unnecessary. In this case use
+ /// `Self`, otherwise just use `Pin<Self>`.
+ type PinnedSelf;
+
+ /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
+ /// type.
+ ///
+ /// If `T: !Unpin` it will not be able to move afterwards.
+ fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
+ where
+ E: From<AllocError>;
+
+ /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
+ /// type.
+ ///
+ /// If `T: !Unpin` it will not be able to move afterwards.
+ fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self::PinnedSelf>
+ where
+ Error: From<E>,
+ {
+ // SAFETY: We delegate to `init` and only change the error type.
+ let init = unsafe {
+ pin_init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
+ };
+ Self::try_pin_init(init, flags)
+ }
+
+ /// Use the given initializer to in-place initialize a `T`.
+ fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
+ where
+ E: From<AllocError>;
+
+ /// Use the given initializer to in-place initialize a `T`.
+ fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self>
+ where
+ Error: From<E>,
+ {
+ // SAFETY: We delegate to `init` and only change the error type.
+ let init = unsafe {
+ init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
+ };
+ Self::try_init(init, flags)
+ }
+}
+
/// Construct an in-place fallible initializer for `struct`s.
///
/// This macro defaults the error to [`Error`]. If you need [`Infallible`], then use