summaryrefslogtreecommitdiff
path: root/rust/kernel/sync
diff options
context:
space:
mode:
Diffstat (limited to 'rust/kernel/sync')
-rw-r--r--rust/kernel/sync/arc.rs20
-rw-r--r--rust/kernel/sync/aref.rs50
-rw-r--r--rust/kernel/sync/rcu.rs20
3 files changed, 80 insertions, 10 deletions
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index 5ac4961b7cd2..8ae0fe6f19ec 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -154,7 +154,7 @@ impl<T: ?Sized> ArcInner<T> {
///
/// # Safety
///
- /// `ptr` must have been returned by a previous call to [`Arc::into_raw`], and the `Arc` must
+ /// `ptr` must have been returned by a previous call to [`Arc::into_raw`], and the [`Arc`] must
/// not yet have been destroyed.
unsafe fn container_of(ptr: *const T) -> NonNull<ArcInner<T>> {
let refcount_layout = Layout::new::<Refcount>();
@@ -253,7 +253,7 @@ impl<T: ?Sized> Arc<T> {
/// Convert the [`Arc`] into a raw pointer.
///
- /// The raw pointer has ownership of the refcount that this Arc object owned.
+ /// The raw pointer has ownership of the refcount that this [`Arc`] object owned.
pub fn into_raw(self) -> *const T {
let ptr = self.ptr.as_ptr();
core::mem::forget(self);
@@ -261,7 +261,7 @@ impl<T: ?Sized> Arc<T> {
unsafe { core::ptr::addr_of!((*ptr).data) }
}
- /// Return a raw pointer to the data in this arc.
+ /// Return a raw pointer to the data in this [`Arc`].
pub fn as_ptr(this: &Self) -> *const T {
let ptr = this.ptr.as_ptr();
@@ -305,7 +305,7 @@ impl<T: ?Sized> Arc<T> {
/// Converts this [`Arc`] into a [`UniqueArc`], or destroys it if it is not unique.
///
- /// When this destroys the `Arc`, it does so while properly avoiding races. This means that
+ /// When this destroys the [`Arc`], it does so while properly avoiding races. This means that
/// this method will never call the destructor of the value.
///
/// # Examples
@@ -345,11 +345,11 @@ impl<T: ?Sized> Arc<T> {
// If the refcount reaches a non-zero value, then we have destroyed this `Arc` and will
// return without further touching the `Arc`. If the refcount reaches zero, then there are
- // no other arcs, and we can create a `UniqueArc`.
+ // no other `Arc`s, and we can create a `UniqueArc`.
if refcount.dec_and_test() {
refcount.set(1);
- // INVARIANT: We own the only refcount to this arc, so we may create a `UniqueArc`. We
+ // INVARIANT: We own the only refcount to this `Arc`, so we may create a `UniqueArc`. We
// must pin the `UniqueArc` because the values was previously in an `Arc`, and they pin
// their values.
Some(Pin::from(UniqueArc {
@@ -717,7 +717,7 @@ impl<T> InPlaceWrite<T> for UniqueArc<MaybeUninit<T>> {
let slot = self.as_mut_ptr();
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
// slot is valid.
- unsafe { init.__init(slot)? };
+ unsafe { pin_init::raw_try_init(slot, init)? };
// SAFETY: All fields have been initialized.
Ok(unsafe { self.assume_init() })
}
@@ -727,7 +727,7 @@ impl<T> InPlaceWrite<T> for UniqueArc<MaybeUninit<T>> {
let slot = self.as_mut_ptr();
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
// slot is valid and will not be moved, because we pin it later.
- unsafe { init.__pinned_init(slot)? };
+ unsafe { pin_init::raw_try_init(slot, init)? };
// SAFETY: All fields have been initialized.
Ok(unsafe { self.assume_init() }.into())
}
@@ -795,7 +795,7 @@ impl<T> UniqueArc<MaybeUninit<T>> {
#[inline]
pub fn init_with<E>(mut self, init: impl Init<T, E>) -> core::result::Result<UniqueArc<T>, E> {
// SAFETY: The supplied pointer is valid for initialization.
- match unsafe { init.__init(self.as_mut_ptr()) } {
+ match unsafe { pin_init::raw_try_init(self.as_mut_ptr(), init) } {
// SAFETY: Initialization completed successfully.
Ok(()) => Ok(unsafe { self.assume_init() }),
Err(err) => Err(err),
@@ -810,7 +810,7 @@ impl<T> UniqueArc<MaybeUninit<T>> {
) -> core::result::Result<Pin<UniqueArc<T>>, E> {
// SAFETY: The supplied pointer is valid for initialization and we will later pin the value
// to ensure it does not move.
- match unsafe { init.__pinned_init(self.as_mut_ptr()) } {
+ match unsafe { pin_init::raw_try_init(self.as_mut_ptr(), init) } {
// SAFETY: Initialization completed successfully.
Ok(()) => Ok(unsafe { self.assume_init() }.into()),
Err(err) => Err(err),
diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs
index b721b2e00b98..9983ee085248 100644
--- a/rust/kernel/sync/aref.rs
+++ b/rust/kernel/sync/aref.rs
@@ -24,6 +24,11 @@ use core::{
ptr::NonNull, //
};
+use crate::{
+ prelude::*,
+ types::ForeignOwnable, //
+};
+
/// Types that are _always_ reference counted.
///
/// It allows such types to define their own custom ref increment and decrement functions.
@@ -188,6 +193,51 @@ where
}
impl<T: AlwaysRefCounted + Eq> Eq for ARef<T> {}
+// SAFETY: `into_foreign` returns a pointer from `NonNull::as_ptr`, so it's non-null. The
+// `ARef` invariant guarantees that `ptr` points to a valid `T`, so it's aligned to `T`.
+unsafe impl<T: AlwaysRefCounted> ForeignOwnable for ARef<T> {
+ const FOREIGN_ALIGN: usize = core::mem::align_of::<T>();
+
+ type Borrowed<'a>
+ = &'a T
+ where
+ Self: 'a;
+ type BorrowedMut<'a>
+ = &'a T
+ where
+ Self: 'a;
+
+ #[inline]
+ fn into_foreign(self) -> *mut c_void {
+ ARef::into_raw(self).as_ptr().cast()
+ }
+
+ #[inline]
+ unsafe fn from_foreign(ptr: *mut c_void) -> Self {
+ // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
+ // call to `Self::into_foreign`.
+ let ptr = unsafe { NonNull::new_unchecked(ptr.cast()) };
+
+ // SAFETY: `ptr` came from `into_foreign`, which consumed an `ARef` without decrementing
+ // the refcount, so we can transfer the ownership to the new `ARef`.
+ unsafe { ARef::from_raw(ptr) }
+ }
+
+ #[inline]
+ unsafe fn borrow<'a>(ptr: *mut c_void) -> &'a T {
+ // SAFETY: The safety requirements of this method ensure that the object remains alive and
+ // immutable for the duration of 'a.
+ unsafe { &*ptr.cast() }
+ }
+
+ #[inline]
+ unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> &'a T {
+ // SAFETY: The safety requirements for `borrow_mut` are a superset of the safety
+ // requirements for `borrow`.
+ unsafe { <Self as ForeignOwnable>::borrow(ptr) }
+ }
+}
+
impl<T, U> PartialEq<&'_ U> for ARef<T>
where
T: AlwaysRefCounted + PartialEq<U>,
diff --git a/rust/kernel/sync/rcu.rs b/rust/kernel/sync/rcu.rs
index a32bef6e490b..42d1b26a2143 100644
--- a/rust/kernel/sync/rcu.rs
+++ b/rust/kernel/sync/rcu.rs
@@ -50,3 +50,23 @@ impl Drop for Guard {
pub fn read_lock() -> Guard {
Guard::new()
}
+
+/// Wait until all in-flight `call_rcu()` callbacks complete.
+///
+/// Note that this primitive does not necessarily wait for an RCU grace period
+/// to complete. For example, if there are no RCU callbacks queued anywhere
+/// in the system, then [`rcu_barrier()`] is within its rights to return
+/// immediately, without waiting for anything, much less an RCU grace period.
+/// In fact, [`rcu_barrier()`] will normally not result in any RCU grace periods
+/// beyond those that were already destined to be executed.
+///
+/// In kernels built with `CONFIG_RCU_LAZY=y`, this function also hurries all
+/// pending lazy RCU callbacks.
+///
+/// Note that this is one of the RCU primitives which must not be called in
+/// atomic context.
+#[inline]
+pub fn rcu_barrier() {
+ // SAFETY: `rcu_barrier()` is always safe to be called. It just might wait for a grace period.
+ unsafe { bindings::rcu_barrier() };
+}