Skip to content

Commit 39da92d

Browse files
wedsonafojeda
authored andcommitted
rust: introduce ARef
This is an owned reference to an object that is always ref-counted. This is meant to be used in wrappers for C types that have their own ref counting functions, for example, tasks, files, inodes, dentries, etc. Reviewed-by: Martin Rodriguez Reboredo <[email protected]> Signed-off-by: Wedson Almeida Filho <[email protected]> Reviewed-by: Gary Guo <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent c1c1904 commit 39da92d

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

rust/kernel/types.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ use crate::init::{self, PinInit};
66
use alloc::boxed::Box;
77
use core::{
88
cell::UnsafeCell,
9+
marker::PhantomData,
910
mem::MaybeUninit,
1011
ops::{Deref, DerefMut},
12+
ptr::NonNull,
1113
};
1214

1315
/// Used to transfer ownership to and from foreign (non-Rust) languages.
@@ -268,6 +270,111 @@ impl<T> Opaque<T> {
268270
}
269271
}
270272

273+
/// Types that are _always_ reference counted.
274+
///
275+
/// It allows such types to define their own custom ref increment and decrement functions.
276+
/// Additionally, it allows users to convert from a shared reference `&T` to an owned reference
277+
/// [`ARef<T>`].
278+
///
279+
/// This is usually implemented by wrappers to existing structures on the C side of the code. For
280+
/// Rust code, the recommendation is to use [`Arc`](crate::sync::Arc) to create reference-counted
281+
/// instances of a type.
282+
///
283+
/// # Safety
284+
///
285+
/// Implementers must ensure that increments to the reference count keep the object alive in memory
286+
/// at least until matching decrements are performed.
287+
///
288+
/// Implementers must also ensure that all instances are reference-counted. (Otherwise they
289+
/// won't be able to honour the requirement that [`AlwaysRefCounted::inc_ref`] keep the object
290+
/// alive.)
291+
pub unsafe trait AlwaysRefCounted {
292+
/// Increments the reference count on the object.
293+
fn inc_ref(&self);
294+
295+
/// Decrements the reference count on the object.
296+
///
297+
/// Frees the object when the count reaches zero.
298+
///
299+
/// # Safety
300+
///
301+
/// Callers must ensure that there was a previous matching increment to the reference count,
302+
/// and that the object is no longer used after its reference count is decremented (as it may
303+
/// result in the object being freed), unless the caller owns another increment on the refcount
304+
/// (e.g., it calls [`AlwaysRefCounted::inc_ref`] twice, then calls
305+
/// [`AlwaysRefCounted::dec_ref`] once).
306+
unsafe fn dec_ref(obj: NonNull<Self>);
307+
}
308+
309+
/// An owned reference to an always-reference-counted object.
310+
///
311+
/// The object's reference count is automatically decremented when an instance of [`ARef`] is
312+
/// dropped. It is also automatically incremented when a new instance is created via
313+
/// [`ARef::clone`].
314+
///
315+
/// # Invariants
316+
///
317+
/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`ARef`] instance. In
318+
/// particular, the [`ARef`] instance owns an increment on the underlying object's reference count.
319+
pub struct ARef<T: AlwaysRefCounted> {
320+
ptr: NonNull<T>,
321+
_p: PhantomData<T>,
322+
}
323+
324+
impl<T: AlwaysRefCounted> ARef<T> {
325+
/// Creates a new instance of [`ARef`].
326+
///
327+
/// It takes over an increment of the reference count on the underlying object.
328+
///
329+
/// # Safety
330+
///
331+
/// Callers must ensure that the reference count was incremented at least once, and that they
332+
/// are properly relinquishing one increment. That is, if there is only one increment, callers
333+
/// must not use the underlying object anymore -- it is only safe to do so via the newly
334+
/// created [`ARef`].
335+
pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
336+
// INVARIANT: The safety requirements guarantee that the new instance now owns the
337+
// increment on the refcount.
338+
Self {
339+
ptr,
340+
_p: PhantomData,
341+
}
342+
}
343+
}
344+
345+
impl<T: AlwaysRefCounted> Clone for ARef<T> {
346+
fn clone(&self) -> Self {
347+
self.inc_ref();
348+
// SAFETY: We just incremented the refcount above.
349+
unsafe { Self::from_raw(self.ptr) }
350+
}
351+
}
352+
353+
impl<T: AlwaysRefCounted> Deref for ARef<T> {
354+
type Target = T;
355+
356+
fn deref(&self) -> &Self::Target {
357+
// SAFETY: The type invariants guarantee that the object is valid.
358+
unsafe { self.ptr.as_ref() }
359+
}
360+
}
361+
362+
impl<T: AlwaysRefCounted> From<&T> for ARef<T> {
363+
fn from(b: &T) -> Self {
364+
b.inc_ref();
365+
// SAFETY: We just incremented the refcount above.
366+
unsafe { Self::from_raw(NonNull::from(b)) }
367+
}
368+
}
369+
370+
impl<T: AlwaysRefCounted> Drop for ARef<T> {
371+
fn drop(&mut self) {
372+
// SAFETY: The type invariants guarantee that the `ARef` owns the reference we're about to
373+
// decrement.
374+
unsafe { T::dec_ref(self.ptr) };
375+
}
376+
}
377+
271378
/// A sum type that always holds either a value of type `L` or `R`.
272379
pub enum Either<L, R> {
273380
/// Constructs an instance of [`Either`] containing a value of type `L`.

0 commit comments

Comments
 (0)