1*9dc04365SWedson Almeida Filho // SPDX-License-Identifier: GPL-2.0 2*9dc04365SWedson Almeida Filho 3*9dc04365SWedson Almeida Filho //! A reference-counted pointer. 4*9dc04365SWedson Almeida Filho //! 5*9dc04365SWedson Almeida Filho //! This module implements a way for users to create reference-counted objects and pointers to 6*9dc04365SWedson Almeida Filho //! them. Such a pointer automatically increments and decrements the count, and drops the 7*9dc04365SWedson Almeida Filho //! underlying object when it reaches zero. It is also safe to use concurrently from multiple 8*9dc04365SWedson Almeida Filho //! threads. 9*9dc04365SWedson Almeida Filho //! 10*9dc04365SWedson Almeida Filho //! It is different from the standard library's [`Arc`] in a few ways: 11*9dc04365SWedson Almeida Filho //! 1. It is backed by the kernel's `refcount_t` type. 12*9dc04365SWedson Almeida Filho //! 2. It does not support weak references, which allows it to be half the size. 13*9dc04365SWedson Almeida Filho //! 3. It saturates the reference count instead of aborting when it goes over a threshold. 14*9dc04365SWedson Almeida Filho //! 4. It does not provide a `get_mut` method, so the ref counted object is pinned. 15*9dc04365SWedson Almeida Filho //! 16*9dc04365SWedson Almeida Filho //! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html 17*9dc04365SWedson Almeida Filho 18*9dc04365SWedson Almeida Filho use crate::{bindings, error::Result, types::Opaque}; 19*9dc04365SWedson Almeida Filho use alloc::boxed::Box; 20*9dc04365SWedson Almeida Filho use core::{marker::PhantomData, ops::Deref, ptr::NonNull}; 21*9dc04365SWedson Almeida Filho 22*9dc04365SWedson Almeida Filho /// A reference-counted pointer to an instance of `T`. 23*9dc04365SWedson Almeida Filho /// 24*9dc04365SWedson Almeida Filho /// The reference count is incremented when new instances of [`Arc`] are created, and decremented 25*9dc04365SWedson Almeida Filho /// when they are dropped. When the count reaches zero, the underlying `T` is also dropped. 26*9dc04365SWedson Almeida Filho /// 27*9dc04365SWedson Almeida Filho /// # Invariants 28*9dc04365SWedson Almeida Filho /// 29*9dc04365SWedson Almeida Filho /// The reference count on an instance of [`Arc`] is always non-zero. 30*9dc04365SWedson Almeida Filho /// The object pointed to by [`Arc`] is always pinned. 31*9dc04365SWedson Almeida Filho /// 32*9dc04365SWedson Almeida Filho /// # Examples 33*9dc04365SWedson Almeida Filho /// 34*9dc04365SWedson Almeida Filho /// ``` 35*9dc04365SWedson Almeida Filho /// use kernel::sync::Arc; 36*9dc04365SWedson Almeida Filho /// 37*9dc04365SWedson Almeida Filho /// struct Example { 38*9dc04365SWedson Almeida Filho /// a: u32, 39*9dc04365SWedson Almeida Filho /// b: u32, 40*9dc04365SWedson Almeida Filho /// } 41*9dc04365SWedson Almeida Filho /// 42*9dc04365SWedson Almeida Filho /// // Create a ref-counted instance of `Example`. 43*9dc04365SWedson Almeida Filho /// let obj = Arc::try_new(Example { a: 10, b: 20 })?; 44*9dc04365SWedson Almeida Filho /// 45*9dc04365SWedson Almeida Filho /// // Get a new pointer to `obj` and increment the refcount. 46*9dc04365SWedson Almeida Filho /// let cloned = obj.clone(); 47*9dc04365SWedson Almeida Filho /// 48*9dc04365SWedson Almeida Filho /// // Assert that both `obj` and `cloned` point to the same underlying object. 49*9dc04365SWedson Almeida Filho /// assert!(core::ptr::eq(&*obj, &*cloned)); 50*9dc04365SWedson Almeida Filho /// 51*9dc04365SWedson Almeida Filho /// // Destroy `obj` and decrement its refcount. 52*9dc04365SWedson Almeida Filho /// drop(obj); 53*9dc04365SWedson Almeida Filho /// 54*9dc04365SWedson Almeida Filho /// // Check that the values are still accessible through `cloned`. 55*9dc04365SWedson Almeida Filho /// assert_eq!(cloned.a, 10); 56*9dc04365SWedson Almeida Filho /// assert_eq!(cloned.b, 20); 57*9dc04365SWedson Almeida Filho /// 58*9dc04365SWedson Almeida Filho /// // The refcount drops to zero when `cloned` goes out of scope, and the memory is freed. 59*9dc04365SWedson Almeida Filho /// ``` 60*9dc04365SWedson Almeida Filho pub struct Arc<T: ?Sized> { 61*9dc04365SWedson Almeida Filho ptr: NonNull<ArcInner<T>>, 62*9dc04365SWedson Almeida Filho _p: PhantomData<ArcInner<T>>, 63*9dc04365SWedson Almeida Filho } 64*9dc04365SWedson Almeida Filho 65*9dc04365SWedson Almeida Filho #[repr(C)] 66*9dc04365SWedson Almeida Filho struct ArcInner<T: ?Sized> { 67*9dc04365SWedson Almeida Filho refcount: Opaque<bindings::refcount_t>, 68*9dc04365SWedson Almeida Filho data: T, 69*9dc04365SWedson Almeida Filho } 70*9dc04365SWedson Almeida Filho 71*9dc04365SWedson Almeida Filho // SAFETY: It is safe to send `Arc<T>` to another thread when the underlying `T` is `Sync` because 72*9dc04365SWedson Almeida Filho // it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs 73*9dc04365SWedson Almeida Filho // `T` to be `Send` because any thread that has an `Arc<T>` may ultimately access `T` directly, for 74*9dc04365SWedson Almeida Filho // example, when the reference count reaches zero and `T` is dropped. 75*9dc04365SWedson Almeida Filho unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {} 76*9dc04365SWedson Almeida Filho 77*9dc04365SWedson Almeida Filho // SAFETY: It is safe to send `&Arc<T>` to another thread when the underlying `T` is `Sync` for the 78*9dc04365SWedson Almeida Filho // same reason as above. `T` needs to be `Send` as well because a thread can clone an `&Arc<T>` 79*9dc04365SWedson Almeida Filho // into an `Arc<T>`, which may lead to `T` being accessed by the same reasoning as above. 80*9dc04365SWedson Almeida Filho unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {} 81*9dc04365SWedson Almeida Filho 82*9dc04365SWedson Almeida Filho impl<T> Arc<T> { 83*9dc04365SWedson Almeida Filho /// Constructs a new reference counted instance of `T`. 84*9dc04365SWedson Almeida Filho pub fn try_new(contents: T) -> Result<Self> { 85*9dc04365SWedson Almeida Filho // INVARIANT: The refcount is initialised to a non-zero value. 86*9dc04365SWedson Almeida Filho let value = ArcInner { 87*9dc04365SWedson Almeida Filho // SAFETY: There are no safety requirements for this FFI call. 88*9dc04365SWedson Almeida Filho refcount: Opaque::new(unsafe { bindings::REFCOUNT_INIT(1) }), 89*9dc04365SWedson Almeida Filho data: contents, 90*9dc04365SWedson Almeida Filho }; 91*9dc04365SWedson Almeida Filho 92*9dc04365SWedson Almeida Filho let inner = Box::try_new(value)?; 93*9dc04365SWedson Almeida Filho 94*9dc04365SWedson Almeida Filho // SAFETY: We just created `inner` with a reference count of 1, which is owned by the new 95*9dc04365SWedson Almeida Filho // `Arc` object. 96*9dc04365SWedson Almeida Filho Ok(unsafe { Self::from_inner(Box::leak(inner).into()) }) 97*9dc04365SWedson Almeida Filho } 98*9dc04365SWedson Almeida Filho } 99*9dc04365SWedson Almeida Filho 100*9dc04365SWedson Almeida Filho impl<T: ?Sized> Arc<T> { 101*9dc04365SWedson Almeida Filho /// Constructs a new [`Arc`] from an existing [`ArcInner`]. 102*9dc04365SWedson Almeida Filho /// 103*9dc04365SWedson Almeida Filho /// # Safety 104*9dc04365SWedson Almeida Filho /// 105*9dc04365SWedson Almeida Filho /// The caller must ensure that `inner` points to a valid location and has a non-zero reference 106*9dc04365SWedson Almeida Filho /// count, one of which will be owned by the new [`Arc`] instance. 107*9dc04365SWedson Almeida Filho unsafe fn from_inner(inner: NonNull<ArcInner<T>>) -> Self { 108*9dc04365SWedson Almeida Filho // INVARIANT: By the safety requirements, the invariants hold. 109*9dc04365SWedson Almeida Filho Arc { 110*9dc04365SWedson Almeida Filho ptr: inner, 111*9dc04365SWedson Almeida Filho _p: PhantomData, 112*9dc04365SWedson Almeida Filho } 113*9dc04365SWedson Almeida Filho } 114*9dc04365SWedson Almeida Filho } 115*9dc04365SWedson Almeida Filho 116*9dc04365SWedson Almeida Filho impl<T: ?Sized> Deref for Arc<T> { 117*9dc04365SWedson Almeida Filho type Target = T; 118*9dc04365SWedson Almeida Filho 119*9dc04365SWedson Almeida Filho fn deref(&self) -> &Self::Target { 120*9dc04365SWedson Almeida Filho // SAFETY: By the type invariant, there is necessarily a reference to the object, so it is 121*9dc04365SWedson Almeida Filho // safe to dereference it. 122*9dc04365SWedson Almeida Filho unsafe { &self.ptr.as_ref().data } 123*9dc04365SWedson Almeida Filho } 124*9dc04365SWedson Almeida Filho } 125*9dc04365SWedson Almeida Filho 126*9dc04365SWedson Almeida Filho impl<T: ?Sized> Clone for Arc<T> { 127*9dc04365SWedson Almeida Filho fn clone(&self) -> Self { 128*9dc04365SWedson Almeida Filho // INVARIANT: C `refcount_inc` saturates the refcount, so it cannot overflow to zero. 129*9dc04365SWedson Almeida Filho // SAFETY: By the type invariant, there is necessarily a reference to the object, so it is 130*9dc04365SWedson Almeida Filho // safe to increment the refcount. 131*9dc04365SWedson Almeida Filho unsafe { bindings::refcount_inc(self.ptr.as_ref().refcount.get()) }; 132*9dc04365SWedson Almeida Filho 133*9dc04365SWedson Almeida Filho // SAFETY: We just incremented the refcount. This increment is now owned by the new `Arc`. 134*9dc04365SWedson Almeida Filho unsafe { Self::from_inner(self.ptr) } 135*9dc04365SWedson Almeida Filho } 136*9dc04365SWedson Almeida Filho } 137*9dc04365SWedson Almeida Filho 138*9dc04365SWedson Almeida Filho impl<T: ?Sized> Drop for Arc<T> { 139*9dc04365SWedson Almeida Filho fn drop(&mut self) { 140*9dc04365SWedson Almeida Filho // SAFETY: By the type invariant, there is necessarily a reference to the object. We cannot 141*9dc04365SWedson Almeida Filho // touch `refcount` after it's decremented to a non-zero value because another thread/CPU 142*9dc04365SWedson Almeida Filho // may concurrently decrement it to zero and free it. It is ok to have a raw pointer to 143*9dc04365SWedson Almeida Filho // freed/invalid memory as long as it is never dereferenced. 144*9dc04365SWedson Almeida Filho let refcount = unsafe { self.ptr.as_ref() }.refcount.get(); 145*9dc04365SWedson Almeida Filho 146*9dc04365SWedson Almeida Filho // INVARIANT: If the refcount reaches zero, there are no other instances of `Arc`, and 147*9dc04365SWedson Almeida Filho // this instance is being dropped, so the broken invariant is not observable. 148*9dc04365SWedson Almeida Filho // SAFETY: Also by the type invariant, we are allowed to decrement the refcount. 149*9dc04365SWedson Almeida Filho let is_zero = unsafe { bindings::refcount_dec_and_test(refcount) }; 150*9dc04365SWedson Almeida Filho if is_zero { 151*9dc04365SWedson Almeida Filho // The count reached zero, we must free the memory. 152*9dc04365SWedson Almeida Filho // 153*9dc04365SWedson Almeida Filho // SAFETY: The pointer was initialised from the result of `Box::leak`. 154*9dc04365SWedson Almeida Filho unsafe { Box::from_raw(self.ptr.as_ptr()) }; 155*9dc04365SWedson Almeida Filho } 156*9dc04365SWedson Almeida Filho } 157*9dc04365SWedson Almeida Filho } 158