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: Implement the smart pointer `InPlaceInit` for `Arc`

For pinned and unpinned initialization of structs, a trait named
`InPlaceInit` exists for uniform access. `Arc` did not implement
`InPlaceInit` yet, although the functions already existed. The main
reason for that, was that the trait itself returned a `Pin<Self>`. The
`Arc` implementation of the kernel is already implicitly pinned.

To enable `Arc` to implement `InPlaceInit` and to have uniform access,
for in-place and pinned in-place initialization, an associated type is
introduced for `InPlaceInit`. The new implementation of `InPlaceInit`
for `Arc` sets `Arc` as the associated type. Older implementations use
an explicit `Pin<T>` as the associated type. The implemented methods for
`Arc` are mostly moved from a direct implementation on `Arc`. There
should be no user impact. The implementation for `ListArc` is omitted,
because it is not merged yet.

Link: https://github.com/Rust-for-Linux/linux/issues/1079
Signed-off-by: Alex Mantel <alexmantel93@mailbox.org>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Link: https://lore.kernel.org/r/20240727042442.682109-1-alexmantel93@mailbox.org
[ Removed "Rusts" (Benno). - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>

authored by

Alex Mantel and committed by
Miguel Ojeda
08f983a5 47ac09b9

+38 -28
+36 -5
rust/kernel/init.rs
··· 213 213 use crate::{ 214 214 alloc::{box_ext::BoxExt, AllocError, Flags}, 215 215 error::{self, Error}, 216 + sync::Arc, 216 217 sync::UniqueArc, 217 218 types::{Opaque, ScopeGuard}, 218 219 }; ··· 1108 1107 1109 1108 /// Smart pointer that can initialize memory in-place. 1110 1109 pub trait InPlaceInit<T>: Sized { 1110 + /// Pinned version of `Self`. 1111 + /// 1112 + /// If a type already implicitly pins its pointee, `Pin<Self>` is unnecessary. In this case use 1113 + /// `Self`, otherwise just use `Pin<Self>`. 1114 + type PinnedSelf; 1115 + 1111 1116 /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this 1112 1117 /// type. 1113 1118 /// 1114 1119 /// If `T: !Unpin` it will not be able to move afterwards. 1115 - fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Pin<Self>, E> 1120 + fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E> 1116 1121 where 1117 1122 E: From<AllocError>; 1118 1123 ··· 1126 1119 /// type. 1127 1120 /// 1128 1121 /// If `T: !Unpin` it will not be able to move afterwards. 1129 - fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Pin<Self>> 1122 + fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self::PinnedSelf> 1130 1123 where 1131 1124 Error: From<E>, 1132 1125 { ··· 1155 1148 } 1156 1149 } 1157 1150 1158 - impl<T> InPlaceInit<T> for Box<T> { 1151 + impl<T> InPlaceInit<T> for Arc<T> { 1152 + type PinnedSelf = Self; 1153 + 1159 1154 #[inline] 1160 - fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Pin<Self>, E> 1155 + fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E> 1156 + where 1157 + E: From<AllocError>, 1158 + { 1159 + UniqueArc::try_pin_init(init, flags).map(|u| u.into()) 1160 + } 1161 + 1162 + #[inline] 1163 + fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E> 1164 + where 1165 + E: From<AllocError>, 1166 + { 1167 + UniqueArc::try_init(init, flags).map(|u| u.into()) 1168 + } 1169 + } 1170 + 1171 + impl<T> InPlaceInit<T> for Box<T> { 1172 + type PinnedSelf = Pin<Self>; 1173 + 1174 + #[inline] 1175 + fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E> 1161 1176 where 1162 1177 E: From<AllocError>, 1163 1178 { ··· 1208 1179 } 1209 1180 1210 1181 impl<T> InPlaceInit<T> for UniqueArc<T> { 1182 + type PinnedSelf = Pin<Self>; 1183 + 1211 1184 #[inline] 1212 - fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Pin<Self>, E> 1185 + fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E> 1213 1186 where 1214 1187 E: From<AllocError>, 1215 1188 {
+2 -23
rust/kernel/sync/arc.rs
··· 12 12 //! 2. It does not support weak references, which allows it to be half the size. 13 13 //! 3. It saturates the reference count instead of aborting when it goes over a threshold. 14 14 //! 4. It does not provide a `get_mut` method, so the ref counted object is pinned. 15 + //! 5. The object in [`Arc`] is pinned implicitly. 15 16 //! 16 17 //! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html 17 18 18 19 use crate::{ 19 20 alloc::{box_ext::BoxExt, AllocError, Flags}, 20 - error::{self, Error}, 21 + bindings, 21 22 init::{self, InPlaceInit, Init, PinInit}, 22 23 try_init, 23 24 types::{ForeignOwnable, Opaque}, ··· 209 208 // SAFETY: We just created `inner` with a reference count of 1, which is owned by the new 210 209 // `Arc` object. 211 210 Ok(unsafe { Self::from_inner(Box::leak(inner).into()) }) 212 - } 213 - 214 - /// Use the given initializer to in-place initialize a `T`. 215 - /// 216 - /// If `T: !Unpin` it will not be able to move afterwards. 217 - #[inline] 218 - pub fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self> 219 - where 220 - Error: From<E>, 221 - { 222 - UniqueArc::pin_init(init, flags).map(|u| u.into()) 223 - } 224 - 225 - /// Use the given initializer to in-place initialize a `T`. 226 - /// 227 - /// This is equivalent to [`Arc<T>::pin_init`], since an [`Arc`] is always pinned. 228 - #[inline] 229 - pub fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self> 230 - where 231 - Error: From<E>, 232 - { 233 - UniqueArc::init(init, flags).map(|u| u.into()) 234 211 } 235 212 } 236 213