From 114ca41fe7922ce85fcac30fa2b06b42b4956520 Mon Sep 17 00:00:00 2001 From: Benno Lossin Date: Sat, 8 Mar 2025 11:04:34 +0000 Subject: 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` 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 Reviewed-by: Fiona Behrens Tested-by: Andreas Hindborg Link: https://lore.kernel.org/r/20250308110339.2997091-9-benno.lossin@proton.me Signed-off-by: Miguel Ojeda --- rust/kernel/sync/arc.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) (limited to 'rust/kernel/sync') diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index 3cefda7a4372..31c26b692c6d 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -19,7 +19,8 @@ use crate::{ alloc::{AllocError, Flags, KBox}, bindings, - init::{self, InPlaceInit, Init, PinInit}, + init::{self, InPlaceWrite, Init, PinInit}, + init_ext::InPlaceInit, try_init, types::{ForeignOwnable, Opaque}, }; @@ -202,6 +203,26 @@ unsafe impl Send for Arc {} // the reference count reaches zero and `T` is dropped. unsafe impl Sync for Arc {} +impl InPlaceInit for Arc { + type PinnedSelf = Self; + + #[inline] + fn try_pin_init(init: impl PinInit, flags: Flags) -> Result + where + E: From, + { + UniqueArc::try_pin_init(init, flags).map(|u| u.into()) + } + + #[inline] + fn try_init(init: impl Init, flags: Flags) -> Result + where + E: From, + { + UniqueArc::try_init(init, flags).map(|u| u.into()) + } +} + impl Arc { /// Constructs a new reference counted instance of `T`. pub fn new(contents: T, flags: Flags) -> Result { @@ -659,6 +680,48 @@ pub struct UniqueArc { inner: Arc, } +impl InPlaceInit for UniqueArc { + type PinnedSelf = Pin; + + #[inline] + fn try_pin_init(init: impl PinInit, flags: Flags) -> Result + where + E: From, + { + UniqueArc::new_uninit(flags)?.write_pin_init(init) + } + + #[inline] + fn try_init(init: impl Init, flags: Flags) -> Result + where + E: From, + { + UniqueArc::new_uninit(flags)?.write_init(init) + } +} + +impl InPlaceWrite for UniqueArc> { + type Initialized = UniqueArc; + + fn write_init(mut self, init: impl Init) -> Result { + let slot = self.as_mut_ptr(); + // SAFETY: When init errors/panics, slot will get deallocated but not dropped, + // slot is valid. + unsafe { init.__init(slot)? }; + // SAFETY: All fields have been initialized. + Ok(unsafe { self.assume_init() }) + } + + fn write_pin_init(mut self, init: impl PinInit) -> Result, E> { + let slot = self.as_mut_ptr(); + // SAFETY: When init errors/panics, slot will get deallocated but not dropped, + // slot is valid and will not be moved, because we pin it later. + unsafe { init.__pinned_init(slot)? }; + // SAFETY: All fields have been initialized. + Ok(unsafe { self.assume_init() }.into()) + } +} + impl UniqueArc { /// Tries to allocate a new [`UniqueArc`] instance. pub fn new(value: T, flags: Flags) -> Result { -- cgit