diff options
author | Benno Lossin <benno.lossin@proton.me> | 2025-03-08 11:04:52 +0000 |
---|---|---|
committer | Miguel Ojeda <ojeda@kernel.org> | 2025-03-16 21:59:19 +0100 |
commit | 31547c988257b3ddd1badb23c166c42b5310735c (patch) | |
tree | b1cfa07f1f422cafe0b6ca48ebb9f92699b835f7 /rust | |
parent | 129e97be8e2856884e01340e4070c003345e1cdc (diff) |
rust: pin-init: remove kernel-crate dependency
In order to make pin-init a standalone crate, remove dependencies on
kernel-specific code such as `ScopeGuard` and `KBox`.
`ScopeGuard` is only used in the `[pin_]init_array_from_fn` functions
and can easily be replaced by a primitive construct.
`KBox` is only used for type variance of unsized types and can also
easily be replaced.
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-13-benno.lossin@proton.me
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Diffstat (limited to 'rust')
-rw-r--r-- | rust/pin-init/src/__internal.rs | 5 | ||||
-rw-r--r-- | rust/pin-init/src/lib.rs | 41 |
2 files changed, 18 insertions, 28 deletions
diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs index 0db800819681..8a53f55e1bbf 100644 --- a/rust/pin-init/src/__internal.rs +++ b/rust/pin-init/src/__internal.rs @@ -11,6 +11,9 @@ use super::*; /// See the [nomicon] for what subtyping is. See also [this table]. /// +/// The reason for not using `PhantomData<*mut T>` is that that type never implements [`Send`] and +/// [`Sync`]. Hence `fn(*mut T) -> *mut T` is used, as that type always implements them. +/// /// [nomicon]: https://doc.rust-lang.org/nomicon/subtyping.html /// [this table]: https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns pub(super) type Invariant<T> = PhantomData<fn(*mut T) -> *mut T>; @@ -105,7 +108,7 @@ pub unsafe trait InitData: Copy { } } -pub struct AllData<T: ?Sized>(PhantomData<fn(KBox<T>) -> KBox<T>>); +pub struct AllData<T: ?Sized>(Invariant<T>); impl<T: ?Sized> Clone for AllData<T> { fn clone(&self) -> Self { diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs index 47954bc1dc2f..5f1afd3abb56 100644 --- a/rust/pin-init/src/lib.rs +++ b/rust/pin-init/src/lib.rs @@ -212,7 +212,6 @@ //! [`pin_data`]: ::macros::pin_data //! [`pin_init!`]: crate::pin_init! -use crate::{alloc::KBox, types::ScopeGuard}; use core::{ cell::UnsafeCell, convert::Infallible, @@ -944,7 +943,7 @@ pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized { } /// An initializer returned by [`PinInit::pin_chain`]. -pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, KBox<T>)>); +pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, T)>); // SAFETY: The `__pinned_init` function is implemented such that it // - returns `Ok(())` on successful initialization, @@ -1043,7 +1042,7 @@ pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> { } /// An initializer returned by [`Init::chain`]. -pub struct ChainInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, KBox<T>)>); +pub struct ChainInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, T)>); // SAFETY: The `__init` function is implemented such that it // - returns `Ok(())` on successful initialization, @@ -1140,25 +1139,19 @@ where { let init = move |slot: *mut [T; N]| { let slot = slot.cast::<T>(); - // Counts the number of initialized elements and when dropped drops that many elements from - // `slot`. - let mut init_count = ScopeGuard::new_with_data(0, |i| { - // We now free every element that has been initialized before. - // SAFETY: The loop initialized exactly the values from 0..i and since we - // return `Err` below, the caller will consider the memory at `slot` as - // uninitialized. - unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) }; - }); for i in 0..N { let init = make_init(i); // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`. let ptr = unsafe { slot.add(i) }; // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init` // requirements. - unsafe { init.__init(ptr) }?; - *init_count += 1; + if let Err(e) = unsafe { init.__init(ptr) } { + // SAFETY: The loop has initialized the elements `slot[0..i]` and since we return + // `Err` below, `slot` will be considered uninitialized memory. + unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) }; + return Err(e); + } } - init_count.dismiss(); Ok(()) }; // SAFETY: The initializer above initializes every element of the array. On failure it drops @@ -1189,25 +1182,19 @@ where { let init = move |slot: *mut [T; N]| { let slot = slot.cast::<T>(); - // Counts the number of initialized elements and when dropped drops that many elements from - // `slot`. - let mut init_count = ScopeGuard::new_with_data(0, |i| { - // We now free every element that has been initialized before. - // SAFETY: The loop initialized exactly the values from 0..i and since we - // return `Err` below, the caller will consider the memory at `slot` as - // uninitialized. - unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) }; - }); for i in 0..N { let init = make_init(i); // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`. let ptr = unsafe { slot.add(i) }; // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init` // requirements. - unsafe { init.__pinned_init(ptr) }?; - *init_count += 1; + if let Err(e) = unsafe { init.__pinned_init(ptr) } { + // SAFETY: The loop has initialized the elements `slot[0..i]` and since we return + // `Err` below, `slot` will be considered uninitialized memory. + unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) }; + return Err(e); + } } - init_count.dismiss(); Ok(()) }; // SAFETY: The initializer above initializes every element of the array. On failure it drops |