Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Benno Lossin and committed by
Miguel Ojeda
31547c98 129e97be

+18 -28
+4 -1
rust/pin-init/src/__internal.rs
··· 11 11 12 12 /// See the [nomicon] for what subtyping is. See also [this table]. 13 13 /// 14 + /// The reason for not using `PhantomData<*mut T>` is that that type never implements [`Send`] and 15 + /// [`Sync`]. Hence `fn(*mut T) -> *mut T` is used, as that type always implements them. 16 + /// 14 17 /// [nomicon]: https://doc.rust-lang.org/nomicon/subtyping.html 15 18 /// [this table]: https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns 16 19 pub(super) type Invariant<T> = PhantomData<fn(*mut T) -> *mut T>; ··· 108 105 } 109 106 } 110 107 111 - pub struct AllData<T: ?Sized>(PhantomData<fn(KBox<T>) -> KBox<T>>); 108 + pub struct AllData<T: ?Sized>(Invariant<T>); 112 109 113 110 impl<T: ?Sized> Clone for AllData<T> { 114 111 fn clone(&self) -> Self {
+14 -27
rust/pin-init/src/lib.rs
··· 212 212 //! [`pin_data`]: ::macros::pin_data 213 213 //! [`pin_init!`]: crate::pin_init! 214 214 215 - use crate::{alloc::KBox, types::ScopeGuard}; 216 215 use core::{ 217 216 cell::UnsafeCell, 218 217 convert::Infallible, ··· 943 944 } 944 945 945 946 /// An initializer returned by [`PinInit::pin_chain`]. 946 - pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, KBox<T>)>); 947 + pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, T)>); 947 948 948 949 // SAFETY: The `__pinned_init` function is implemented such that it 949 950 // - returns `Ok(())` on successful initialization, ··· 1042 1043 } 1043 1044 1044 1045 /// An initializer returned by [`Init::chain`]. 1045 - pub struct ChainInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, KBox<T>)>); 1046 + pub struct ChainInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, T)>); 1046 1047 1047 1048 // SAFETY: The `__init` function is implemented such that it 1048 1049 // - returns `Ok(())` on successful initialization, ··· 1139 1140 { 1140 1141 let init = move |slot: *mut [T; N]| { 1141 1142 let slot = slot.cast::<T>(); 1142 - // Counts the number of initialized elements and when dropped drops that many elements from 1143 - // `slot`. 1144 - let mut init_count = ScopeGuard::new_with_data(0, |i| { 1145 - // We now free every element that has been initialized before. 1146 - // SAFETY: The loop initialized exactly the values from 0..i and since we 1147 - // return `Err` below, the caller will consider the memory at `slot` as 1148 - // uninitialized. 1149 - unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) }; 1150 - }); 1151 1143 for i in 0..N { 1152 1144 let init = make_init(i); 1153 1145 // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`. 1154 1146 let ptr = unsafe { slot.add(i) }; 1155 1147 // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init` 1156 1148 // requirements. 1157 - unsafe { init.__init(ptr) }?; 1158 - *init_count += 1; 1149 + if let Err(e) = unsafe { init.__init(ptr) } { 1150 + // SAFETY: The loop has initialized the elements `slot[0..i]` and since we return 1151 + // `Err` below, `slot` will be considered uninitialized memory. 1152 + unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) }; 1153 + return Err(e); 1154 + } 1159 1155 } 1160 - init_count.dismiss(); 1161 1156 Ok(()) 1162 1157 }; 1163 1158 // SAFETY: The initializer above initializes every element of the array. On failure it drops ··· 1182 1189 { 1183 1190 let init = move |slot: *mut [T; N]| { 1184 1191 let slot = slot.cast::<T>(); 1185 - // Counts the number of initialized elements and when dropped drops that many elements from 1186 - // `slot`. 1187 - let mut init_count = ScopeGuard::new_with_data(0, |i| { 1188 - // We now free every element that has been initialized before. 1189 - // SAFETY: The loop initialized exactly the values from 0..i and since we 1190 - // return `Err` below, the caller will consider the memory at `slot` as 1191 - // uninitialized. 1192 - unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) }; 1193 - }); 1194 1192 for i in 0..N { 1195 1193 let init = make_init(i); 1196 1194 // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`. 1197 1195 let ptr = unsafe { slot.add(i) }; 1198 1196 // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init` 1199 1197 // requirements. 1200 - unsafe { init.__pinned_init(ptr) }?; 1201 - *init_count += 1; 1198 + if let Err(e) = unsafe { init.__pinned_init(ptr) } { 1199 + // SAFETY: The loop has initialized the elements `slot[0..i]` and since we return 1200 + // `Err` below, `slot` will be considered uninitialized memory. 1201 + unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) }; 1202 + return Err(e); 1203 + } 1202 1204 } 1203 - init_count.dismiss(); 1204 1205 Ok(()) 1205 1206 }; 1206 1207 // SAFETY: The initializer above initializes every element of the array. On failure it drops