Skip to content

Commit 08f983a

Browse files
ellcsojeda
authored andcommitted
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: #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>
1 parent 47ac09b commit 08f983a

File tree

2 files changed

+37
-27
lines changed

2 files changed

+37
-27
lines changed

rust/kernel/init.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@
213213
use crate::{
214214
alloc::{box_ext::BoxExt, AllocError, Flags},
215215
error::{self, Error},
216+
sync::Arc,
216217
sync::UniqueArc,
217218
types::{Opaque, ScopeGuard},
218219
};
@@ -1107,19 +1108,25 @@ unsafe impl<T, E> PinInit<T, E> for T {
11071108

11081109
/// Smart pointer that can initialize memory in-place.
11091110
pub trait InPlaceInit<T>: Sized {
1111+
/// Pinned version of `Self`.
1112+
///
1113+
/// If a type already implicitly pins its pointee, `Pin<Self>` is unnecessary. In this case use
1114+
/// `Self`, otherwise just use `Pin<Self>`.
1115+
type PinnedSelf;
1116+
11101117
/// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
11111118
/// type.
11121119
///
11131120
/// If `T: !Unpin` it will not be able to move afterwards.
1114-
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Pin<Self>, E>
1121+
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
11151122
where
11161123
E: From<AllocError>;
11171124

11181125
/// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
11191126
/// type.
11201127
///
11211128
/// If `T: !Unpin` it will not be able to move afterwards.
1122-
fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Pin<Self>>
1129+
fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self::PinnedSelf>
11231130
where
11241131
Error: From<E>,
11251132
{
@@ -1148,9 +1155,31 @@ pub trait InPlaceInit<T>: Sized {
11481155
}
11491156
}
11501157

1158+
impl<T> InPlaceInit<T> for Arc<T> {
1159+
type PinnedSelf = Self;
1160+
1161+
#[inline]
1162+
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
1163+
where
1164+
E: From<AllocError>,
1165+
{
1166+
UniqueArc::try_pin_init(init, flags).map(|u| u.into())
1167+
}
1168+
1169+
#[inline]
1170+
fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
1171+
where
1172+
E: From<AllocError>,
1173+
{
1174+
UniqueArc::try_init(init, flags).map(|u| u.into())
1175+
}
1176+
}
1177+
11511178
impl<T> InPlaceInit<T> for Box<T> {
1179+
type PinnedSelf = Pin<Self>;
1180+
11521181
#[inline]
1153-
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Pin<Self>, E>
1182+
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
11541183
where
11551184
E: From<AllocError>,
11561185
{
@@ -1179,8 +1208,10 @@ impl<T> InPlaceInit<T> for Box<T> {
11791208
}
11801209

11811210
impl<T> InPlaceInit<T> for UniqueArc<T> {
1211+
type PinnedSelf = Pin<Self>;
1212+
11821213
#[inline]
1183-
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Pin<Self>, E>
1214+
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
11841215
where
11851216
E: From<AllocError>,
11861217
{

rust/kernel/sync/arc.rs

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
//! 2. It does not support weak references, which allows it to be half the size.
1313
//! 3. It saturates the reference count instead of aborting when it goes over a threshold.
1414
//! 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.
1516
//!
1617
//! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html
1718
1819
use crate::{
1920
alloc::{box_ext::BoxExt, AllocError, Flags},
20-
error::{self, Error},
21+
bindings,
2122
init::{self, InPlaceInit, Init, PinInit},
2223
try_init,
2324
types::{ForeignOwnable, Opaque},
@@ -209,28 +210,6 @@ impl<T> Arc<T> {
209210
// `Arc` object.
210211
Ok(unsafe { Self::from_inner(Box::leak(inner).into()) })
211212
}
212-
213-
/// Use the given initializer to in-place initialize a `T`.
214-
///
215-
/// If `T: !Unpin` it will not be able to move afterwards.
216-
#[inline]
217-
pub fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self>
218-
where
219-
Error: From<E>,
220-
{
221-
UniqueArc::pin_init(init, flags).map(|u| u.into())
222-
}
223-
224-
/// Use the given initializer to in-place initialize a `T`.
225-
///
226-
/// This is equivalent to [`Arc<T>::pin_init`], since an [`Arc`] is always pinned.
227-
#[inline]
228-
pub fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self>
229-
where
230-
Error: From<E>,
231-
{
232-
UniqueArc::init(init, flags).map(|u| u.into())
233-
}
234213
}
235214

236215
impl<T: ?Sized> Arc<T> {

0 commit comments

Comments
 (0)