In order to support RCU delay free (call_rcu() and kfree_rcu()), the
abstraction of the `rcu_head` is introduced. Types that want to support
RCU delay free can specify a `RcuHead<T>` in it, e.g.

    #[derive(HasField)]
    struct Foo {
        a: i32,
        b: i32,
        #[field]
        rcu_head: RcuHead,
    }

A wrapper `WithRcuHead<T>` is also provided for users that want to
specify a generic `T` with a rcu_head.

Signed-off-by: Boqun Feng <[email protected]>
---
 rust/kernel/sync/rcu.rs | 69 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 68 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/sync/rcu.rs b/rust/kernel/sync/rcu.rs
index a32bef6e490b..694ca2f54953 100644
--- a/rust/kernel/sync/rcu.rs
+++ b/rust/kernel/sync/rcu.rs
@@ -4,7 +4,14 @@
 //!
 //! C header: [`include/linux/rcupdate.h`](srctree/include/linux/rcupdate.h)
 
-use crate::{bindings, types::NotThreadSafe};
+use crate::{
+    bindings,
+    field::{Field, HasField},
+    macros::HasField,
+    types::{NotThreadSafe, Opaque},
+};
+
+use core::ops::Deref;
 
 /// Evidence that the RCU read side lock is held on the current thread/CPU.
 ///
@@ -50,3 +57,63 @@ fn drop(&mut self) {
 pub fn read_lock() -> Guard {
     Guard::new()
 }
+
+/// RCU head for call backs.
+///
+/// # Examples
+///
+/// Use `#[derive(HasField)]` macro to specify a struct has a RCU head.
+///
+/// ```
+/// use kernel::sync::rcu::RcuHead;
+///
+/// #[derive(HasField)]
+/// struct Foo {
+///     a: i32,
+///     #[field]
+///     rcu_head: RcuHead,
+///     b: i32,
+/// }
+///
+/// const _: () = {
+///     const fn assert_has_field<T: HasField<T, RcuHead>>() { }
+///     assert_has_field::<Foo>();
+/// };
+/// ```
+#[repr(transparent)]
+pub struct RcuHead(Opaque<bindings::callback_head>);
+
+impl<T> Field<T> for RcuHead {}
+
+// SAFETY: `callback_head` doesn't hold anything local to the current 
execution context, so it's
+// safe to transfer to another execution context.
+unsafe impl Send for RcuHead {}
+// SAFETY: `callback_head` should only be used when it's in the destructor, 
and accesses to it are
+// already unsafe, hence make it `Sync`.
+unsafe impl Sync for RcuHead {}
+
+/// A wrapper that adds an `RcuHead` on `T`.
+#[derive(HasField)]
+pub struct WithRcuHead<T> {
+    #[field]
+    head: RcuHead,
+    data: T,
+}
+
+impl<T> WithRcuHead<T> {
+    /// Creates a new wrapper on `T` with `RcuHead`.
+    pub fn new(data: T) -> Self {
+        Self {
+            head: RcuHead(Opaque::zeroed()),
+            data,
+        }
+    }
+}
+
+impl<T> Deref for WithRcuHead<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        &self.data
+    }
+}
-- 
2.50.1 (Apple Git-155)


Reply via email to