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)