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: 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>

authored by

Benno Lossin and committed by
Miguel Ojeda
114ca41f 578eb8b6

+127 -124
+2 -1
rust/kernel/alloc/kbox.rs
··· 15 15 use core::ptr::NonNull; 16 16 use core::result::Result; 17 17 18 - use crate::init::{InPlaceInit, InPlaceWrite, Init, PinInit}; 18 + use crate::init::{InPlaceWrite, Init, PinInit}; 19 + use crate::init_ext::InPlaceInit; 19 20 use crate::types::ForeignOwnable; 20 21 21 22 /// The kernel's [`Box`] type -- a heap allocation for a single value of type `T`.
+55
rust/kernel/init.rs
··· 134 134 //! } 135 135 //! ``` 136 136 137 + use crate::{ 138 + alloc::{AllocError, Flags}, 139 + error::{self, Error}, 140 + init::{init_from_closure, pin_init_from_closure, Init, PinInit}, 141 + }; 142 + 143 + /// Smart pointer that can initialize memory in-place. 144 + pub trait InPlaceInit<T>: Sized { 145 + /// Pinned version of `Self`. 146 + /// 147 + /// If a type already implicitly pins its pointee, `Pin<Self>` is unnecessary. In this case use 148 + /// `Self`, otherwise just use `Pin<Self>`. 149 + type PinnedSelf; 150 + 151 + /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this 152 + /// type. 153 + /// 154 + /// If `T: !Unpin` it will not be able to move afterwards. 155 + fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E> 156 + where 157 + E: From<AllocError>; 158 + 159 + /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this 160 + /// type. 161 + /// 162 + /// If `T: !Unpin` it will not be able to move afterwards. 163 + fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self::PinnedSelf> 164 + where 165 + Error: From<E>, 166 + { 167 + // SAFETY: We delegate to `init` and only change the error type. 168 + let init = unsafe { 169 + pin_init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e))) 170 + }; 171 + Self::try_pin_init(init, flags) 172 + } 173 + 174 + /// Use the given initializer to in-place initialize a `T`. 175 + fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E> 176 + where 177 + E: From<AllocError>; 178 + 179 + /// Use the given initializer to in-place initialize a `T`. 180 + fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self> 181 + where 182 + Error: From<E>, 183 + { 184 + // SAFETY: We delegate to `init` and only change the error type. 185 + let init = unsafe { 186 + init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e))) 187 + }; 188 + Self::try_init(init, flags) 189 + } 190 + } 191 + 137 192 /// Construct an in-place fallible initializer for `struct`s. 138 193 /// 139 194 /// This macro defaults the error to [`Error`]. If you need [`Infallible`], then use
+2 -1
rust/kernel/prelude.rs
··· 36 36 37 37 pub use super::{str::CStr, ThisModule}; 38 38 39 - pub use super::init::{InPlaceInit, InPlaceWrite, Init, PinInit}; 39 + pub use super::init::{InPlaceWrite, Init, PinInit}; 40 + pub use super::init_ext::InPlaceInit; 40 41 41 42 pub use super::current;
+64 -1
rust/kernel/sync/arc.rs
··· 19 19 use crate::{ 20 20 alloc::{AllocError, Flags, KBox}, 21 21 bindings, 22 - init::{self, InPlaceInit, Init, PinInit}, 22 + init::{self, InPlaceWrite, Init, PinInit}, 23 + init_ext::InPlaceInit, 23 24 try_init, 24 25 types::{ForeignOwnable, Opaque}, 25 26 }; ··· 202 201 // `Arc<T>` on that thread, so the thread may ultimately access `T` using a mutable reference when 203 202 // the reference count reaches zero and `T` is dropped. 204 203 unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {} 204 + 205 + impl<T> InPlaceInit<T> for Arc<T> { 206 + type PinnedSelf = Self; 207 + 208 + #[inline] 209 + fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E> 210 + where 211 + E: From<AllocError>, 212 + { 213 + UniqueArc::try_pin_init(init, flags).map(|u| u.into()) 214 + } 215 + 216 + #[inline] 217 + fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E> 218 + where 219 + E: From<AllocError>, 220 + { 221 + UniqueArc::try_init(init, flags).map(|u| u.into()) 222 + } 223 + } 205 224 206 225 impl<T> Arc<T> { 207 226 /// Constructs a new reference counted instance of `T`. ··· 678 657 /// ``` 679 658 pub struct UniqueArc<T: ?Sized> { 680 659 inner: Arc<T>, 660 + } 661 + 662 + impl<T> InPlaceInit<T> for UniqueArc<T> { 663 + type PinnedSelf = Pin<Self>; 664 + 665 + #[inline] 666 + fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E> 667 + where 668 + E: From<AllocError>, 669 + { 670 + UniqueArc::new_uninit(flags)?.write_pin_init(init) 671 + } 672 + 673 + #[inline] 674 + fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E> 675 + where 676 + E: From<AllocError>, 677 + { 678 + UniqueArc::new_uninit(flags)?.write_init(init) 679 + } 680 + } 681 + 682 + impl<T> InPlaceWrite<T> for UniqueArc<MaybeUninit<T>> { 683 + type Initialized = UniqueArc<T>; 684 + 685 + fn write_init<E>(mut self, init: impl Init<T, E>) -> Result<Self::Initialized, E> { 686 + let slot = self.as_mut_ptr(); 687 + // SAFETY: When init errors/panics, slot will get deallocated but not dropped, 688 + // slot is valid. 689 + unsafe { init.__init(slot)? }; 690 + // SAFETY: All fields have been initialized. 691 + Ok(unsafe { self.assume_init() }) 692 + } 693 + 694 + fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E> { 695 + let slot = self.as_mut_ptr(); 696 + // SAFETY: When init errors/panics, slot will get deallocated but not dropped, 697 + // slot is valid and will not be moved, because we pin it later. 698 + unsafe { init.__pinned_init(slot)? }; 699 + // SAFETY: All fields have been initialized. 700 + Ok(unsafe { self.assume_init() }.into()) 701 + } 681 702 } 682 703 683 704 impl<T> UniqueArc<T> {
+4 -121
rust/pin-init/src/lib.rs
··· 10 10 //! To initialize a `struct` with an in-place constructor you will need two things: 11 11 //! - an in-place constructor, 12 12 //! - a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`], 13 - //! [`UniqueArc<T>`], [`KBox<T>`] or any other smart pointer that implements [`InPlaceInit`]). 13 + //! [`KBox<T>`] or any other smart pointer that supports this library). 14 14 //! 15 15 //! To get an in-place constructor there are generally three options: 16 16 //! - directly creating an in-place constructor using the [`pin_init!`] macro, ··· 212 212 //! [`pin_init!`]: crate::pin_init! 213 213 214 214 use crate::{ 215 - alloc::{AllocError, Flags, KBox}, 216 - error::{self, Error}, 217 - sync::Arc, 218 - sync::UniqueArc, 215 + alloc::KBox, 219 216 types::{Opaque, ScopeGuard}, 220 217 }; 221 218 use core::{ ··· 888 891 /// A pin-initializer for the type `T`. 889 892 /// 890 893 /// To use this initializer, you will need a suitable memory location that can hold a `T`. This can 891 - /// be [`KBox<T>`], [`Arc<T>`], [`UniqueArc<T>`] or even the stack (see [`stack_pin_init!`]). Use 892 - /// the [`InPlaceInit::pin_init`] function of a smart pointer like [`Arc<T>`] on this. 894 + /// be [`KBox<T>`], [`Arc<T>`] or even the stack (see [`stack_pin_init!`]). 893 895 /// 894 896 /// Also see the [module description](self). 895 897 /// ··· 906 910 /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`. 907 911 /// 908 912 /// [`Arc<T>`]: crate::sync::Arc 909 - /// [`Arc::pin_init`]: crate::sync::Arc::pin_init 910 913 #[must_use = "An initializer must be used in order to create its value."] 911 914 pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized { 912 915 /// Initializes `slot`. ··· 971 976 /// An initializer for `T`. 972 977 /// 973 978 /// To use this initializer, you will need a suitable memory location that can hold a `T`. This can 974 - /// be [`KBox<T>`], [`Arc<T>`], [`UniqueArc<T>`] or even the stack (see [`stack_pin_init!`]). Use 975 - /// the [`InPlaceInit::init`] function of a smart pointer like [`Arc<T>`] on this. Because 979 + /// be [`KBox<T>`], [`Arc<T>`] or even the stack (see [`stack_pin_init!`]). Because 976 980 /// [`PinInit<T, E>`] is a super trait, you can use every function that takes it as well. 977 981 /// 978 982 /// Also see the [module description](self). ··· 1232 1238 } 1233 1239 } 1234 1240 1235 - /// Smart pointer that can initialize memory in-place. 1236 - pub trait InPlaceInit<T>: Sized { 1237 - /// Pinned version of `Self`. 1238 - /// 1239 - /// If a type already implicitly pins its pointee, `Pin<Self>` is unnecessary. In this case use 1240 - /// `Self`, otherwise just use `Pin<Self>`. 1241 - type PinnedSelf; 1242 - 1243 - /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this 1244 - /// type. 1245 - /// 1246 - /// If `T: !Unpin` it will not be able to move afterwards. 1247 - fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E> 1248 - where 1249 - E: From<AllocError>; 1250 - 1251 - /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this 1252 - /// type. 1253 - /// 1254 - /// If `T: !Unpin` it will not be able to move afterwards. 1255 - fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self::PinnedSelf> 1256 - where 1257 - Error: From<E>, 1258 - { 1259 - // SAFETY: We delegate to `init` and only change the error type. 1260 - let init = unsafe { 1261 - pin_init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e))) 1262 - }; 1263 - Self::try_pin_init(init, flags) 1264 - } 1265 - 1266 - /// Use the given initializer to in-place initialize a `T`. 1267 - fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E> 1268 - where 1269 - E: From<AllocError>; 1270 - 1271 - /// Use the given initializer to in-place initialize a `T`. 1272 - fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self> 1273 - where 1274 - Error: From<E>, 1275 - { 1276 - // SAFETY: We delegate to `init` and only change the error type. 1277 - let init = unsafe { 1278 - init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e))) 1279 - }; 1280 - Self::try_init(init, flags) 1281 - } 1282 - } 1283 - 1284 - impl<T> InPlaceInit<T> for Arc<T> { 1285 - type PinnedSelf = Self; 1286 - 1287 - #[inline] 1288 - fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E> 1289 - where 1290 - E: From<AllocError>, 1291 - { 1292 - UniqueArc::try_pin_init(init, flags).map(|u| u.into()) 1293 - } 1294 - 1295 - #[inline] 1296 - fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E> 1297 - where 1298 - E: From<AllocError>, 1299 - { 1300 - UniqueArc::try_init(init, flags).map(|u| u.into()) 1301 - } 1302 - } 1303 - 1304 - impl<T> InPlaceInit<T> for UniqueArc<T> { 1305 - type PinnedSelf = Pin<Self>; 1306 - 1307 - #[inline] 1308 - fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E> 1309 - where 1310 - E: From<AllocError>, 1311 - { 1312 - UniqueArc::new_uninit(flags)?.write_pin_init(init) 1313 - } 1314 - 1315 - #[inline] 1316 - fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E> 1317 - where 1318 - E: From<AllocError>, 1319 - { 1320 - UniqueArc::new_uninit(flags)?.write_init(init) 1321 - } 1322 - } 1323 - 1324 1241 /// Smart pointer containing uninitialized memory and that can write a value. 1325 1242 pub trait InPlaceWrite<T> { 1326 1243 /// The type `Self` turns into when the contents are initialized. ··· 1246 1341 /// 1247 1342 /// Does not drop the current value and considers it as uninitialized memory. 1248 1343 fn write_pin_init<E>(self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E>; 1249 - } 1250 - 1251 - impl<T> InPlaceWrite<T> for UniqueArc<MaybeUninit<T>> { 1252 - type Initialized = UniqueArc<T>; 1253 - 1254 - fn write_init<E>(mut self, init: impl Init<T, E>) -> Result<Self::Initialized, E> { 1255 - let slot = self.as_mut_ptr(); 1256 - // SAFETY: When init errors/panics, slot will get deallocated but not dropped, 1257 - // slot is valid. 1258 - unsafe { init.__init(slot)? }; 1259 - // SAFETY: All fields have been initialized. 1260 - Ok(unsafe { self.assume_init() }) 1261 - } 1262 - 1263 - fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E> { 1264 - let slot = self.as_mut_ptr(); 1265 - // SAFETY: When init errors/panics, slot will get deallocated but not dropped, 1266 - // slot is valid and will not be moved, because we pin it later. 1267 - unsafe { init.__pinned_init(slot)? }; 1268 - // SAFETY: All fields have been initialized. 1269 - Ok(unsafe { self.assume_init() }.into()) 1270 - } 1271 1344 } 1272 1345 1273 1346 /// Trait facilitating pinned destruction.