[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250807121011.2317762-1-vitaly.wool@konsulko.se>
Date: Thu, 7 Aug 2025 14:10:11 +0200
From: Vitaly Wool <vitaly.wool@...sulko.se>
To: rust-for-linux@...r.kernel.org
Cc: linux-kernel@...r.kernel.org,
Uladzislau Rezki <urezki@...il.com>,
Danilo Krummrich <dakr@...nel.org>,
Alice Ryhl <aliceryhl@...gle.com>,
Vlastimil Babka <vbabka@...e.cz>,
Lorenzo Stoakes <lorenzo.stoakes@...cle.com>,
"Liam R . Howlett" <Liam.Howlett@...cle.com>,
Miguel Ojeda <ojeda@...nel.org>,
Alex Gaynor <alex.gaynor@...il.com>,
Boqun Feng <boqun.feng@...il.com>,
Gary Guo <gary@...yguo.net>,
Bjorn Roy Baron <bjorn3_gh@...tonmail.com>,
Benno Lossin <lossin@...nel.org>,
Andreas Hindborg <a.hindborg@...nel.org>,
Trevor Gross <tmgross@...ch.edu>,
Vitaly Wool <vitaly.wool@...sulko.se>
Subject: [PATCH] rust: extend kbox with a new constructor
From: Alice Ryhl <aliceryhl@...gle.com>
Add a new constructor to KBox to facilitate KBox creation from a
pinned slice of elements. This allows to efficiently allocate memory for
e.g. arrays of structrures containing spinlocks or mutexes.
Signed-off-by: Alice Ryhl <aliceryhl@...gle.com>
Signed-off-by: Vitaly Wool <vitaly.wool@...sulko.se>
---
rust/kernel/alloc/kbox.rs | 51 +++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
index 1fef9beb57c8..74877afab0a3 100644
--- a/rust/kernel/alloc/kbox.rs
+++ b/rust/kernel/alloc/kbox.rs
@@ -290,6 +290,57 @@ pub fn pin(x: T, flags: Flags) -> Result<Pin<Box<T, A>>, AllocError>
Ok(Self::new(x, flags)?.into())
}
+ /// Construct a pinned slice of elements `Pin<Box<[T], A>>`. This is a convenient means for
+ /// creation of e.g. arrays of structrures containing spinlocks or mutexes.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #[pin_data]
+ /// struct Example {
+ /// c: u32,
+ /// #[pin]
+ /// d: SpinLock<Inner>,
+ /// }
+ ///
+ /// impl Example {
+ /// fn new() -> impl PinInit<Self> {
+ /// pin_init!(Self {
+ /// c: 10,
+ /// d <- new_spinlock!(Inner { a: 20, b: 30 }),
+ /// })
+ /// }
+ /// }
+ /// // Allocate a boxed slice of 10 `Example`s.
+ /// let s = KBox::pin_slice(
+ /// | _i | Example::new(),
+ /// 10,
+ /// GFP_KERNEL
+ /// )?;
+ /// assert_eq!(s[5].c, 10);
+ /// assert_eq!(s[3].d.lock().a, 20),
+ /// ```
+ pub fn pin_slice<F, I, E>(mut init: F, len: usize, flags: Flags) -> Result<Pin<Box<[T], A>>, E>
+ where
+ F: FnMut(usize) -> I,
+ I: PinInit<T, E>,
+ E: From<AllocError>,
+ {
+ let mut buffer = super::Vec::<T, A>::with_capacity(len, flags)?;
+ for i in 0..len {
+ let ptr = buffer.spare_capacity_mut().as_mut_ptr().cast();
+ // SAFETY: This address is available to be initialized, and it will either be dropped
+ // on a future error or returned as a pinned location.
+ unsafe { init(i).__pinned_init(ptr)? };
+ // SAFETY: We initialized one more value.
+ unsafe { buffer.inc_len(1) };
+ }
+ let (ptr, _, _) = buffer.into_raw_parts();
+ let slice = core::ptr::slice_from_raw_parts_mut(ptr, len);
+ // SAFETY: This memory holds a valid [T] allocated with the right allocator.
+ Ok(Pin::from(unsafe { Box::from_raw(slice) }))
+ }
+
/// Convert a [`Box<T,A>`] to a [`Pin<Box<T,A>>`]. If `T` does not implement
/// [`Unpin`], then `x` will be pinned in memory and can't be moved.
pub fn into_pin(this: Self) -> Pin<Self> {
--
2.39.2
Powered by blists - more mailing lists