kernel/sync/aref.rs
1// SPDX-License-Identifier: GPL-2.0
2
3//! Internal reference counting support.
4//!
5//! Many C types already have their own reference counting mechanism (e.g. by storing a
6//! `refcount_t`). This module provides support for directly using their internal reference count
7//! from Rust; instead of making users have to use an additional Rust-reference count in the form of
8//! [`Arc`].
9//!
10//! The smart pointer [`ARef<T>`] acts similarly to [`Arc<T>`] in that it holds a refcount on the
11//! underlying object, but this refcount is internal to the object. It essentially is a Rust
12//! implementation of the `get_` and `put_` pattern used in C for reference counting.
13//!
14//! To make use of [`ARef<MyType>`], `MyType` needs to implement [`AlwaysRefCounted`]. It is a trait
15//! for accessing the internal reference count of an object of the `MyType` type.
16//!
17//! [`Arc`]: crate::sync::Arc
18//! [`Arc<T>`]: crate::sync::Arc
19
20use core::{
21 marker::PhantomData,
22 mem::ManuallyDrop,
23 ops::Deref,
24 ptr::NonNull, //
25};
26
27use crate::{
28 prelude::*,
29 types::ForeignOwnable, //
30};
31
32/// Types that are _always_ reference counted.
33///
34/// It allows such types to define their own custom ref increment and decrement functions.
35/// Additionally, it allows users to convert from a shared reference `&T` to an owned reference
36/// [`ARef<T>`].
37///
38/// This is usually implemented by wrappers to existing structures on the C side of the code. For
39/// Rust code, the recommendation is to use [`Arc`](crate::sync::Arc) to create reference-counted
40/// instances of a type.
41///
42/// # Safety
43///
44/// Implementers must ensure that increments to the reference count keep the object alive in memory
45/// at least until matching decrements are performed.
46///
47/// Implementers must also ensure that all instances are reference-counted. (Otherwise they
48/// won't be able to honour the requirement that [`AlwaysRefCounted::inc_ref`] keep the object
49/// alive.)
50pub unsafe trait AlwaysRefCounted {
51 /// Increments the reference count on the object.
52 fn inc_ref(&self);
53
54 /// Decrements the reference count on the object.
55 ///
56 /// Frees the object when the count reaches zero.
57 ///
58 /// # Safety
59 ///
60 /// Callers must ensure that there was a previous matching increment to the reference count,
61 /// and that the object is no longer used after its reference count is decremented (as it may
62 /// result in the object being freed), unless the caller owns another increment on the refcount
63 /// (e.g., it calls [`AlwaysRefCounted::inc_ref`] twice, then calls
64 /// [`AlwaysRefCounted::dec_ref`] once).
65 unsafe fn dec_ref(obj: NonNull<Self>);
66}
67
68/// An owned reference to an always-reference-counted object.
69///
70/// The object's reference count is automatically decremented when an instance of [`ARef`] is
71/// dropped. It is also automatically incremented when a new instance is created via
72/// [`ARef::clone`].
73///
74/// # Invariants
75///
76/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`ARef`] instance. In
77/// particular, the [`ARef`] instance owns an increment on the underlying object's reference count.
78pub struct ARef<T: AlwaysRefCounted> {
79 ptr: NonNull<T>,
80 _p: PhantomData<T>,
81}
82
83// SAFETY: It is safe to send `ARef<T>` to another thread when the underlying `T` is `Sync` because
84// it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs
85// `T` to be `Send` because any thread that has an `ARef<T>` may ultimately access `T` using a
86// mutable reference, for example, when the reference count reaches zero and `T` is dropped.
87unsafe impl<T: AlwaysRefCounted + Sync + Send> Send for ARef<T> {}
88
89// SAFETY: It is safe to send `&ARef<T>` to another thread when the underlying `T` is `Sync`
90// because it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally,
91// it needs `T` to be `Send` because any thread that has a `&ARef<T>` may clone it and get an
92// `ARef<T>` on that thread, so the thread may ultimately access `T` using a mutable reference, for
93// example, when the reference count reaches zero and `T` is dropped.
94unsafe impl<T: AlwaysRefCounted + Sync + Send> Sync for ARef<T> {}
95
96// Even if `T` is pinned, pointers to `T` can still move.
97impl<T: AlwaysRefCounted> Unpin for ARef<T> {}
98
99impl<T: AlwaysRefCounted> ARef<T> {
100 /// Creates a new instance of [`ARef`].
101 ///
102 /// It takes over an increment of the reference count on the underlying object.
103 ///
104 /// # Safety
105 ///
106 /// Callers must ensure that the reference count was incremented at least once, and that they
107 /// are properly relinquishing one increment. That is, if there is only one increment, callers
108 /// must not use the underlying object anymore -- it is only safe to do so via the newly
109 /// created [`ARef`].
110 pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
111 // INVARIANT: The safety requirements guarantee that the new instance now owns the
112 // increment on the refcount.
113 Self {
114 ptr,
115 _p: PhantomData,
116 }
117 }
118
119 /// Consumes the `ARef`, returning a raw pointer.
120 ///
121 /// This function does not change the refcount. After calling this function, the caller is
122 /// responsible for the refcount previously managed by the `ARef`.
123 ///
124 /// # Examples
125 ///
126 /// ```
127 /// use core::ptr::NonNull;
128 /// use kernel::sync::aref::{ARef, AlwaysRefCounted};
129 ///
130 /// struct Empty {}
131 ///
132 /// # // SAFETY: TODO.
133 /// unsafe impl AlwaysRefCounted for Empty {
134 /// fn inc_ref(&self) {}
135 /// unsafe fn dec_ref(_obj: NonNull<Self>) {}
136 /// }
137 ///
138 /// let mut data = Empty {};
139 /// let ptr = NonNull::<Empty>::new(&mut data).unwrap();
140 /// # // SAFETY: TODO.
141 /// let data_ref: ARef<Empty> = unsafe { ARef::from_raw(ptr) };
142 /// let raw_ptr: NonNull<Empty> = ARef::into_raw(data_ref);
143 ///
144 /// assert_eq!(ptr, raw_ptr);
145 /// ```
146 pub fn into_raw(me: Self) -> NonNull<T> {
147 ManuallyDrop::new(me).ptr
148 }
149}
150
151impl<T: AlwaysRefCounted> Clone for ARef<T> {
152 fn clone(&self) -> Self {
153 self.inc_ref();
154 // SAFETY: We just incremented the refcount above.
155 unsafe { Self::from_raw(self.ptr) }
156 }
157}
158
159impl<T: AlwaysRefCounted> Deref for ARef<T> {
160 type Target = T;
161
162 fn deref(&self) -> &Self::Target {
163 // SAFETY: The type invariants guarantee that the object is valid.
164 unsafe { self.ptr.as_ref() }
165 }
166}
167
168impl<T: AlwaysRefCounted> From<&T> for ARef<T> {
169 fn from(b: &T) -> Self {
170 b.inc_ref();
171 // SAFETY: We just incremented the refcount above.
172 unsafe { Self::from_raw(NonNull::from(b)) }
173 }
174}
175
176impl<T: AlwaysRefCounted> Drop for ARef<T> {
177 fn drop(&mut self) {
178 // SAFETY: The type invariants guarantee that the `ARef` owns the reference we're about to
179 // decrement.
180 unsafe { T::dec_ref(self.ptr) };
181 }
182}
183
184impl<T, U> PartialEq<ARef<U>> for ARef<T>
185where
186 T: AlwaysRefCounted + PartialEq<U>,
187 U: AlwaysRefCounted,
188{
189 #[inline]
190 fn eq(&self, other: &ARef<U>) -> bool {
191 T::eq(&**self, &**other)
192 }
193}
194impl<T: AlwaysRefCounted + Eq> Eq for ARef<T> {}
195
196// SAFETY: `into_foreign` returns a pointer from `NonNull::as_ptr`, so it's non-null. The
197// `ARef` invariant guarantees that `ptr` points to a valid `T`, so it's aligned to `T`.
198unsafe impl<T: AlwaysRefCounted> ForeignOwnable for ARef<T> {
199 const FOREIGN_ALIGN: usize = core::mem::align_of::<T>();
200
201 type Borrowed<'a>
202 = &'a T
203 where
204 Self: 'a;
205 type BorrowedMut<'a>
206 = &'a T
207 where
208 Self: 'a;
209
210 #[inline]
211 fn into_foreign(self) -> *mut c_void {
212 ARef::into_raw(self).as_ptr().cast()
213 }
214
215 #[inline]
216 unsafe fn from_foreign(ptr: *mut c_void) -> Self {
217 // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
218 // call to `Self::into_foreign`.
219 let ptr = unsafe { NonNull::new_unchecked(ptr.cast()) };
220
221 // SAFETY: `ptr` came from `into_foreign`, which consumed an `ARef` without decrementing
222 // the refcount, so we can transfer the ownership to the new `ARef`.
223 unsafe { ARef::from_raw(ptr) }
224 }
225
226 #[inline]
227 unsafe fn borrow<'a>(ptr: *mut c_void) -> &'a T {
228 // SAFETY: The safety requirements of this method ensure that the object remains alive and
229 // immutable for the duration of 'a.
230 unsafe { &*ptr.cast() }
231 }
232
233 #[inline]
234 unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> &'a T {
235 // SAFETY: The safety requirements for `borrow_mut` are a superset of the safety
236 // requirements for `borrow`.
237 unsafe { <Self as ForeignOwnable>::borrow(ptr) }
238 }
239}
240
241impl<T, U> PartialEq<&'_ U> for ARef<T>
242where
243 T: AlwaysRefCounted + PartialEq<U>,
244{
245 #[inline]
246 fn eq(&self, other: &&U) -> bool {
247 T::eq(&**self, other)
248 }
249}