forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 431
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rust: kernel: move
ARef<T>
and AlwaysRefCounted
to new `sync::are…
…f` module Refactor the `ARef` type and `AlwaysRefCounted` trait from `types.rs` into a new `sync/aref.rs` module: - Add `rust/kernel/sync/aref.rs` with the definitions of `ARef` and `AlwaysRefCounted`. - Remove the same type and trait definitions from `rust/kernel/types.rs`. - Update relevant files to import `ARef` and `AlwaysRefCounted` from `sync/aref.rs`. The type and trait definitions remain unchanged. Suggested-by: Benno Lossin <benno.lossin@proton.me> Link: #1117 Signed-off-by: Aliet Exposito Garcia <aliet.exposito@gmail.com> Reviewed-by: Fiona Behrens <me@kloenk.dev> Reviewed-by: Benno Lossin <benno.lossin@proton.me> Link: https://lore.kernel.org/r/20240918225115.2309224-3-aliet.exposito@gmail.com [ Rebased on top of the lints series, slightly reworded and removed unneeded `use AlwaysRefCounted` in example. - Miguel ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
- Loading branch information
Showing
9 changed files
with
169 additions
and
166 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
use crate::types::Opaque; | ||
|
||
mod arc; | ||
pub mod aref; | ||
mod condvar; | ||
pub mod lock; | ||
mod locked_by; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
//! Types and utilities for managing always-reference-counted objects. | ||
|
||
use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull}; | ||
|
||
/// Types that are _always_ reference counted. | ||
/// | ||
/// It allows such types to define their own custom ref increment and decrement functions. | ||
/// Additionally, it allows users to convert from a shared reference `&T` to an owned reference | ||
/// [`ARef<T>`]. | ||
/// | ||
/// This is usually implemented by wrappers to existing structures on the C side of the code. For | ||
/// Rust code, the recommendation is to use [`Arc`](crate::sync::Arc) to create reference-counted | ||
/// instances of a type. | ||
/// | ||
/// # Safety | ||
/// | ||
/// Implementers must ensure that increments to the reference count keep the object alive in memory | ||
/// at least until matching decrements are performed. | ||
/// | ||
/// Implementers must also ensure that all instances are reference-counted. (Otherwise they | ||
/// won't be able to honour the requirement that [`AlwaysRefCounted::inc_ref`] keep the object | ||
/// alive.) | ||
pub unsafe trait AlwaysRefCounted { | ||
/// Increments the reference count on the object. | ||
fn inc_ref(&self); | ||
|
||
/// Decrements the reference count on the object. | ||
/// | ||
/// Frees the object when the count reaches zero. | ||
/// | ||
/// # Safety | ||
/// | ||
/// Callers must ensure that there was a previous matching increment to the reference count, | ||
/// and that the object is no longer used after its reference count is decremented (as it may | ||
/// result in the object being freed), unless the caller owns another increment on the refcount | ||
/// (e.g., it calls [`AlwaysRefCounted::inc_ref`] twice, then calls | ||
/// [`AlwaysRefCounted::dec_ref`] once). | ||
unsafe fn dec_ref(obj: NonNull<Self>); | ||
} | ||
|
||
/// An owned reference to an always-reference-counted object. | ||
/// | ||
/// The object's reference count is automatically decremented when an instance of [`ARef`] is | ||
/// dropped. It is also automatically incremented when a new instance is created via | ||
/// [`ARef::clone`]. | ||
/// | ||
/// # Invariants | ||
/// | ||
/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`ARef`] instance. In | ||
/// particular, the [`ARef`] instance owns an increment on the underlying object's reference count. | ||
pub struct ARef<T: AlwaysRefCounted> { | ||
ptr: NonNull<T>, | ||
_p: PhantomData<T>, | ||
} | ||
|
||
// SAFETY: It is safe to send `ARef<T>` to another thread when the underlying `T` is `Sync` because | ||
// it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs | ||
// `T` to be `Send` because any thread that has an `ARef<T>` may ultimately access `T` using a | ||
// mutable reference, for example, when the reference count reaches zero and `T` is dropped. | ||
unsafe impl<T: AlwaysRefCounted + Sync + Send> Send for ARef<T> {} | ||
|
||
// SAFETY: It is safe to send `&ARef<T>` to another thread when the underlying `T` is `Sync` | ||
// because it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, | ||
// it needs `T` to be `Send` because any thread that has a `&ARef<T>` may clone it and get an | ||
// `ARef<T>` on that thread, so the thread may ultimately access `T` using a mutable reference, for | ||
// example, when the reference count reaches zero and `T` is dropped. | ||
unsafe impl<T: AlwaysRefCounted + Sync + Send> Sync for ARef<T> {} | ||
|
||
impl<T: AlwaysRefCounted> ARef<T> { | ||
/// Creates a new instance of [`ARef`]. | ||
/// | ||
/// It takes over an increment of the reference count on the underlying object. | ||
/// | ||
/// # Safety | ||
/// | ||
/// Callers must ensure that the reference count was incremented at least once, and that they | ||
/// are properly relinquishing one increment. That is, if there is only one increment, callers | ||
/// must not use the underlying object anymore -- it is only safe to do so via the newly | ||
/// created [`ARef`]. | ||
pub unsafe fn from_raw(ptr: NonNull<T>) -> Self { | ||
// INVARIANT: The safety requirements guarantee that the new instance now owns the | ||
// increment on the refcount. | ||
Self { | ||
ptr, | ||
_p: PhantomData, | ||
} | ||
} | ||
|
||
/// Consumes the `ARef`, returning a raw pointer. | ||
/// | ||
/// This function does not change the refcount. After calling this function, the caller is | ||
/// responsible for the refcount previously managed by the `ARef`. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ``` | ||
/// use core::ptr::NonNull; | ||
/// use kernel::sync::aref::{ARef, AlwaysRefCounted}; | ||
/// | ||
/// struct Empty {} | ||
/// | ||
/// # // SAFETY: TODO. | ||
/// unsafe impl AlwaysRefCounted for Empty { | ||
/// fn inc_ref(&self) {} | ||
/// unsafe fn dec_ref(_obj: NonNull<Self>) {} | ||
/// } | ||
/// | ||
/// let mut data = Empty {}; | ||
/// let ptr = NonNull::<Empty>::new(&mut data as *mut _).unwrap(); | ||
/// # // SAFETY: TODO. | ||
/// let data_ref: ARef<Empty> = unsafe { ARef::from_raw(ptr) }; | ||
/// let raw_ptr: NonNull<Empty> = ARef::into_raw(data_ref); | ||
/// | ||
/// assert_eq!(ptr, raw_ptr); | ||
/// ``` | ||
pub fn into_raw(me: Self) -> NonNull<T> { | ||
ManuallyDrop::new(me).ptr | ||
} | ||
} | ||
|
||
impl<T: AlwaysRefCounted> Clone for ARef<T> { | ||
fn clone(&self) -> Self { | ||
self.inc_ref(); | ||
// SAFETY: We just incremented the refcount above. | ||
unsafe { Self::from_raw(self.ptr) } | ||
} | ||
} | ||
|
||
impl<T: AlwaysRefCounted> Deref for ARef<T> { | ||
type Target = T; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
// SAFETY: The type invariants guarantee that the object is valid. | ||
unsafe { self.ptr.as_ref() } | ||
} | ||
} | ||
|
||
impl<T: AlwaysRefCounted> From<&T> for ARef<T> { | ||
fn from(b: &T) -> Self { | ||
b.inc_ref(); | ||
// SAFETY: We just incremented the refcount above. | ||
unsafe { Self::from_raw(NonNull::from(b)) } | ||
} | ||
} | ||
|
||
impl<T: AlwaysRefCounted> Drop for ARef<T> { | ||
fn drop(&mut self) { | ||
// SAFETY: The type invariants guarantee that the `ARef` owns the reference we're about to | ||
// decrement. | ||
unsafe { T::dec_ref(self.ptr) }; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.