rust: revocable: Use AtomicFlag to replace AtomicBool Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
diff --git a/rust/kernel/revocable.rs b/rust/kernel/revocable.rs index db4aa46..51dbf71 100644 --- a/rust/kernel/revocable.rs +++ b/rust/kernel/revocable.rs
@@ -5,13 +5,16 @@ //! The [`Revocable`] type wraps other types and allows access to them to be revoked. The existence //! of a [`RevocableGuard`] ensures that objects remain valid. -use crate::{bindings, prelude::*, sync::rcu, types::Opaque}; -use core::{ - marker::PhantomData, - ops::Deref, - ptr::drop_in_place, - sync::atomic::{AtomicBool, Ordering}, +use crate::{ + bindings, + prelude::*, + sync::{ + atomic::{AtomicFlag, Relaxed}, + rcu, + }, + types::Opaque, }; +use core::{marker::PhantomData, ops::Deref, ptr::drop_in_place}; /// An object that can become inaccessible at runtime. /// @@ -63,7 +66,7 @@ /// ``` #[pin_data(PinnedDrop)] pub struct Revocable<T> { - is_available: AtomicBool, + is_available: AtomicFlag, #[pin] data: Opaque<T>, } @@ -82,7 +85,7 @@ impl<T> Revocable<T> { /// Creates a new revocable instance of the given data. pub fn new(data: impl PinInit<T>) -> impl PinInit<Self> { pin_init!(Self { - is_available: AtomicBool::new(true), + is_available: AtomicFlag::new(true), data <- Opaque::pin_init(data), }) } @@ -96,7 +99,7 @@ pub fn new(data: impl PinInit<T>) -> impl PinInit<Self> { /// because another CPU may be waiting to complete the revocation of this object. pub fn try_access(&self) -> Option<RevocableGuard<'_, T>> { let guard = rcu::read_lock(); - if self.is_available.load(Ordering::Relaxed) { + if self.is_available.test(Relaxed) { // Since `self.is_available` is true, data is initialised and has to remain valid // because the RCU read side lock prevents it from being dropped. Some(RevocableGuard::new(self.data.get(), guard)) @@ -114,7 +117,7 @@ pub fn try_access(&self) -> Option<RevocableGuard<'_, T>> { /// allowed to sleep because another CPU may be waiting to complete the revocation of this /// object. pub fn try_access_with_guard<'a>(&'a self, _guard: &'a rcu::Guard) -> Option<&'a T> { - if self.is_available.load(Ordering::Relaxed) { + if self.is_available.test(Relaxed) { // SAFETY: Since `self.is_available` is true, data is initialised and has to remain // valid because the RCU read side lock prevents it from being dropped. Some(unsafe { &*self.data.get() }) @@ -155,7 +158,7 @@ pub unsafe fn access(&self) -> &T { /// /// Callers must ensure that there are no more concurrent users of the revocable object. unsafe fn revoke_internal<const SYNC: bool>(&self) { - if self.is_available.swap(false, Ordering::Relaxed) { + if self.is_available.xchg(false, Relaxed) { if SYNC { // SAFETY: Just an FFI call, there are no further requirements. unsafe { bindings::synchronize_rcu() }; @@ -203,7 +206,7 @@ fn drop(self: Pin<&mut Self>) { // dropped). // SAFETY: We are not moving out of `p`, only dropping in place let p = unsafe { self.get_unchecked_mut() }; - if *p.is_available.get_mut() { + if p.is_available.test(Relaxed) { // SAFETY: We know `self.data` is valid because no other CPU has changed // `is_available` to `false` yet, and no other CPU can do it anymore because this CPU // holds the only reference (mutable) to `self` now.