[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20250905171209.944599-2-lossin@kernel.org>
Date: Fri, 5 Sep 2025 19:12:07 +0200
From: Benno Lossin <lossin@...nel.org>
To: Miguel Ojeda <ojeda@...nel.org>,
Alex Gaynor <alex.gaynor@...il.com>,
Boqun Feng <boqun.feng@...il.com>,
Gary Guo <gary@...yguo.net>,
Björn Roy Baron <bjorn3_gh@...tonmail.com>,
Benno Lossin <lossin@...nel.org>,
Andreas Hindborg <a.hindborg@...nel.org>,
Alice Ryhl <aliceryhl@...gle.com>,
Trevor Gross <tmgross@...ch.edu>,
Danilo Krummrich <dakr@...nel.org>,
Tejun Heo <tj@...nel.org>,
Tamir Duberstein <tamird@...il.com>,
Dirk Behme <dirk.behme@...il.com>,
Alban Kurti <kurti@...icto.ai>,
Fiona Behrens <me@...enk.dev>
Cc: rust-for-linux@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH 2/2] rust: pin-init: add pin projections to `#[pin_data]`
Make the `#[pin_data]` macro generate a `*Projection` struct that holds
either `Pin<&mut Field>` or `&mut Field` for every field of the original
struct. Which version is chosen depends on weather there is a `#[pin]`
or not respectively. Access to this projected version is enabled through
generating `fn project(self: Pin<&mut Self>) -> SelfProjection<'_>`.
Link: https://github.com/Rust-for-Linux/pin-init/pull/75/commits/2d698367d646c7ede90e01aa22842c1002d017b3
[ Adapt workqueue to use the new projection instead of its own, custom
one - Benno ]
Signed-off-by: Benno Lossin <lossin@...nel.org>
---
rust/kernel/workqueue.rs | 10 ++-----
rust/pin-init/src/macros.rs | 60 +++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+), 8 deletions(-)
diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index b9343d5bc00f..6ca14c629643 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -356,18 +356,12 @@ struct ClosureWork<T> {
func: Option<T>,
}
-impl<T> ClosureWork<T> {
- fn project(self: Pin<&mut Self>) -> &mut Option<T> {
- // SAFETY: The `func` field is not structurally pinned.
- unsafe { &mut self.get_unchecked_mut().func }
- }
-}
-
impl<T: FnOnce()> WorkItem for ClosureWork<T> {
type Pointer = Pin<KBox<Self>>;
fn run(mut this: Pin<KBox<Self>>) {
- if let Some(func) = this.as_mut().project().take() {
+ if let Some(func) = this.as_mut().project().func.take() {
+ // if let Some(func) = this.as_mut().project_func().take() {
(func)()
}
}
diff --git a/rust/pin-init/src/macros.rs b/rust/pin-init/src/macros.rs
index 9ced630737b8..d225cc144904 100644
--- a/rust/pin-init/src/macros.rs
+++ b/rust/pin-init/src/macros.rs
@@ -831,6 +831,17 @@ macro_rules! __pin_data {
$($fields)*
}
+ $crate::__pin_data!(make_pin_projections:
+ @vis($vis),
+ @name($name),
+ @impl_generics($($impl_generics)*),
+ @ty_generics($($ty_generics)*),
+ @decl_generics($($decl_generics)*),
+ @where($($whr)*),
+ @pinned($($pinned)*),
+ @not_pinned($($not_pinned)*),
+ );
+
// We put the rest into this const item, because it then will not be accessible to anything
// outside.
const _: () = {
@@ -980,6 +991,55 @@ fn drop(&mut self) {
stringify!($($rest)*),
);
};
+ (make_pin_projections:
+ @vis($vis:vis),
+ @name($name:ident),
+ @impl_generics($($impl_generics:tt)*),
+ @ty_generics($($ty_generics:tt)*),
+ @decl_generics($($decl_generics:tt)*),
+ @where($($whr:tt)*),
+ @pinned($($(#[$($p_attr:tt)*])* $pvis:vis $p_field:ident : $p_type:ty),* $(,)?),
+ @not_pinned($($(#[$($attr:tt)*])* $fvis:vis $field:ident : $type:ty),* $(,)?),
+ ) => {
+ $crate::macros::paste! {
+ #[doc(hidden)]
+ $vis struct [< $name Projection >] <'__pin, $($decl_generics)*> {
+ $($(#[$($p_attr)*])* $pvis $p_field : ::core::pin::Pin<&'__pin mut $p_type>,)*
+ $($(#[$($attr)*])* $fvis $field : &'__pin mut $type,)*
+ ___pin_phantom_data: ::core::marker::PhantomData<&'__pin mut ()>,
+ }
+
+ impl<$($impl_generics)*> $name<$($ty_generics)*>
+ where $($whr)*
+ {
+ /// Pin-projects all fields of `Self`.
+ ///
+ /// These fields are structurally pinned:
+ $(#[doc = ::core::concat!(" - `", ::core::stringify!($p_field), "`")])*
+ ///
+ /// These fields are **not** structurally pinned:
+ $(#[doc = ::core::concat!(" - `", ::core::stringify!($field), "`")])*
+ $vis fn project<'__pin>(
+ self: ::core::pin::Pin<&'__pin mut Self>,
+ ) -> [< $name Projection >] <'__pin, $($ty_generics)*> {
+ // SAFETY: we only give access to `&mut` for fields not structurally pinned.
+ let this = unsafe { ::core::pin::Pin::get_unchecked_mut(self) };
+ [< $name Projection >] {
+ $(
+ // SAFETY: `$p_field` is structurally pinned.
+ $(#[$($p_attr)*])*
+ $p_field : unsafe { ::core::pin::Pin::new_unchecked(&mut this.$p_field) },
+ )*
+ $(
+ $(#[$($attr)*])*
+ $field : &mut this.$field,
+ )*
+ ___pin_phantom_data: ::core::marker::PhantomData,
+ }
+ }
+ }
+ }
+ };
(make_pin_data:
@pin_data($pin_data:ident),
@impl_generics($($impl_generics:tt)*),
--
2.50.1
Powered by blists - more mailing lists