[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250626165927.66498-2-marcelomoreira1905@gmail.com>
Date: Thu, 26 Jun 2025 13:59:26 -0300
From: Marcelo Moreira <marcelomoreira1905@...il.com>
To: rust-for-linux@...r.kernel.org
Cc: linux-kernel@...r.kernel.org,
lossin@...nel.org,
dakr@...nel.org,
ojeda@...nel.org,
skhan@...uxfoundation.org,
linux-kernel-mentees@...ts.linuxfoundation.org,
~lkcamp/patches@...ts.sr.ht
Subject: [PATCH v5 1/2] rust: revocable: Refactor revocation mechanism to remove generic revoke_internal
The revocation mechanism is refactored by removing the generic
`revoke_internal` function. Its logic is now directly integrated into
two distinct public functions: `revoke()` and `revoke_nosync()`.
`revoke_nosync()` is an `unsafe` function that requires the caller to
guarantee no concurrent users, thus avoiding an RCU grace period.
`revoke()` is a safe function that internally waits for the RCU grace
period to ensure all concurrent accesses have completed before dropping
the wrapped object.
This change improves API clarity and simplifies associated `SAFETY`
comments by making the synchronization behavior explicit in the function
signatures.
Suggested-by: Benno Lossin <lossin@...nel.org>
Suggested-by: Danilo Krummrich <dakr@...nel.org>
Signed-off-by: Marcelo Moreira <marcelomoreira1905@...il.com>
---
rust/kernel/revocable.rs | 48 ++++++++++++++++++----------------------
1 file changed, 21 insertions(+), 27 deletions(-)
diff --git a/rust/kernel/revocable.rs b/rust/kernel/revocable.rs
index 06a3cdfce344..f10ce5c1ed77 100644
--- a/rust/kernel/revocable.rs
+++ b/rust/kernel/revocable.rs
@@ -151,26 +151,6 @@ pub unsafe fn access(&self) -> &T {
unsafe { &*self.data.get() }
}
- /// # Safety
- ///
- /// Callers must ensure that there are no more concurrent users of the revocable object.
- unsafe fn revoke_internal<const SYNC: bool>(&self) -> bool {
- let revoke = self.is_available.swap(false, Ordering::Relaxed);
-
- if revoke {
- if SYNC {
- // SAFETY: Just an FFI call, there are no further requirements.
- unsafe { bindings::synchronize_rcu() };
- }
-
- // SAFETY: We know `self.data` is valid because only one CPU can succeed the
- // `compare_exchange` above that takes `is_available` from `true` to `false`.
- unsafe { drop_in_place(self.data.get()) };
- }
-
- revoke
- }
-
/// Revokes access to and drops the wrapped object.
///
/// Access to the object is revoked immediately to new callers of [`Revocable::try_access`],
@@ -183,10 +163,15 @@ unsafe fn revoke_internal<const SYNC: bool>(&self) -> bool {
///
/// Callers must ensure that there are no more concurrent users of the revocable object.
pub unsafe fn revoke_nosync(&self) -> bool {
- // SAFETY: By the safety requirement of this function, the caller ensures that nobody is
- // accessing the data anymore and hence we don't have to wait for the grace period to
- // finish.
- unsafe { self.revoke_internal::<false>() }
+ let revoke = self.is_available.swap(false, Ordering::Relaxed);
+
+ if revoke {
+ // SAFETY: `self.data` is valid for writes because of `Self`'s type invariants,
+ // as `self.is_available` is false due to the atomic swap, and by the safety
+ // requirements of this function, no thread is accessing `data` anymore.
+ unsafe { drop_in_place(self.data.get()) };
+ }
+ revoke
}
/// Revokes access to and drops the wrapped object.
@@ -200,9 +185,18 @@ pub unsafe fn revoke_nosync(&self) -> bool {
/// Returns `true` if `&self` has been revoked with this call, `false` if it was revoked
/// already.
pub fn revoke(&self) -> bool {
- // SAFETY: By passing `true` we ask `revoke_internal` to wait for the grace period to
- // finish.
- unsafe { self.revoke_internal::<true>() }
+ let revoke = self.is_available.swap(false, Ordering::Relaxed);
+
+ if revoke {
+ // SAFETY: Just an FFI call, there are no further requirements.
+ unsafe { bindings::synchronize_rcu() };
+
+ // SAFETY: `self.data` is valid for writes because of `Self`'s type invariants,
+ // as `self.is_available` is false due to the atomic swap, and `synchronize_rcu`
+ // ensures all prior RCU read-side critical sections have completed.
+ unsafe { drop_in_place(self.data.get()) };
+ }
+ revoke
}
}
--
2.50.0
Powered by blists - more mailing lists