| // SPDX-License-Identifier: GPL-2.0 | |
| //! Internal reference counting support. | |
| //! | |
| //! Many C types already have their own reference counting mechanism (e.g. by storing a | |
| //! `refcount_t`). This module provides support for directly using their internal reference count | |
| //! from Rust; instead of making users have to use an additional Rust-reference count in the form of | |
| //! [`Arc`]. | |
| //! | |
| //! The smart pointer [`ARef<T>`] acts similarly to [`Arc<T>`] in that it holds a refcount on the | |
| //! underlying object, but this refcount is internal to the object. It essentially is a Rust | |
| //! implementation of the `get_` and `put_` pattern used in C for reference counting. | |
| //! | |
| //! To make use of [`ARef<MyType>`], `MyType` needs to implement [`AlwaysRefCounted`]. It is a trait | |
| //! for accessing the internal reference count of an object of the `MyType` type. | |
| //! | |
| //! [`Arc`]: crate::sync::Arc | |
| //! [`Arc<T>`]: crate::sync::Arc | |
| use core::{ | |
| marker::PhantomData, | |
| mem::ManuallyDrop, | |
| ops::Deref, | |
| 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. | |
| /// 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> {} | |
| // Even if `T` is pinned, pointers to `T` can still move. | |
| impl<T: AlwaysRefCounted> Unpin 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).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) }; | |
| } | |
| } | |
| impl<T, U> PartialEq<ARef<U>> for ARef<T> | |
| where | |
| T: AlwaysRefCounted + PartialEq<U>, | |
| U: AlwaysRefCounted, | |
| { | |
| #[inline] | |
| fn eq(&self, other: &ARef<U>) -> bool { | |
| T::eq(&**self, &**other) | |
| } | |
| } | |
| 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>, | |
| { | |
| #[inline] | |
| fn eq(&self, other: &&U) -> bool { | |
| T::eq(&**self, other) | |
| } | |
| } |