// SPDX-License-Identifier: GPL-2.0 //! Internal reference counting support. 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`]. /// /// 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); } /// 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 { ptr: NonNull, _p: PhantomData, } // SAFETY: It is safe to send `ARef` 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` may ultimately access `T` using a // mutable reference, for example, when the reference count reaches zero and `T` is dropped. unsafe impl Send for ARef {} // SAFETY: It is safe to send `&ARef` 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` may clone it and get an // `ARef` 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 Sync for ARef {} impl ARef { /// 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) -> 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::types::{ARef, AlwaysRefCounted}; /// /// struct Empty {} /// /// # // SAFETY: TODO. /// unsafe impl AlwaysRefCounted for Empty { /// fn inc_ref(&self) {} /// unsafe fn dec_ref(_obj: NonNull) {} /// } /// /// let mut data = Empty {}; /// let ptr = NonNull::::new(&mut data).unwrap(); /// # // SAFETY: TODO. /// let data_ref: ARef = unsafe { ARef::from_raw(ptr) }; /// let raw_ptr: NonNull = ARef::into_raw(data_ref); /// /// assert_eq!(ptr, raw_ptr); /// ``` pub fn into_raw(me: Self) -> NonNull { ManuallyDrop::new(me).ptr } } impl Clone for ARef { fn clone(&self) -> Self { self.inc_ref(); // SAFETY: We just incremented the refcount above. unsafe { Self::from_raw(self.ptr) } } } impl Deref for ARef { type Target = T; fn deref(&self) -> &Self::Target { // SAFETY: The type invariants guarantee that the object is valid. unsafe { self.ptr.as_ref() } } } impl From<&T> for ARef { fn from(b: &T) -> Self { b.inc_ref(); // SAFETY: We just incremented the refcount above. unsafe { Self::from_raw(NonNull::from(b)) } } } impl Drop for ARef { 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) }; } }