19dc04365SWedson Almeida Filho // SPDX-License-Identifier: GPL-2.0 29dc04365SWedson Almeida Filho 39dc04365SWedson Almeida Filho //! A reference-counted pointer. 49dc04365SWedson Almeida Filho //! 59dc04365SWedson Almeida Filho //! This module implements a way for users to create reference-counted objects and pointers to 69dc04365SWedson Almeida Filho //! them. Such a pointer automatically increments and decrements the count, and drops the 79dc04365SWedson Almeida Filho //! underlying object when it reaches zero. It is also safe to use concurrently from multiple 89dc04365SWedson Almeida Filho //! threads. 99dc04365SWedson Almeida Filho //! 109dc04365SWedson Almeida Filho //! It is different from the standard library's [`Arc`] in a few ways: 119dc04365SWedson Almeida Filho //! 1. It is backed by the kernel's `refcount_t` type. 129dc04365SWedson Almeida Filho //! 2. It does not support weak references, which allows it to be half the size. 139dc04365SWedson Almeida Filho //! 3. It saturates the reference count instead of aborting when it goes over a threshold. 149dc04365SWedson Almeida Filho //! 4. It does not provide a `get_mut` method, so the ref counted object is pinned. 159dc04365SWedson Almeida Filho //! 169dc04365SWedson Almeida Filho //! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html 179dc04365SWedson Almeida Filho 189dc04365SWedson Almeida Filho use crate::{bindings, error::Result, types::Opaque}; 199dc04365SWedson Almeida Filho use alloc::boxed::Box; 209dc04365SWedson Almeida Filho use core::{marker::PhantomData, ops::Deref, ptr::NonNull}; 219dc04365SWedson Almeida Filho 229dc04365SWedson Almeida Filho /// A reference-counted pointer to an instance of `T`. 239dc04365SWedson Almeida Filho /// 249dc04365SWedson Almeida Filho /// The reference count is incremented when new instances of [`Arc`] are created, and decremented 259dc04365SWedson Almeida Filho /// when they are dropped. When the count reaches zero, the underlying `T` is also dropped. 269dc04365SWedson Almeida Filho /// 279dc04365SWedson Almeida Filho /// # Invariants 289dc04365SWedson Almeida Filho /// 299dc04365SWedson Almeida Filho /// The reference count on an instance of [`Arc`] is always non-zero. 309dc04365SWedson Almeida Filho /// The object pointed to by [`Arc`] is always pinned. 319dc04365SWedson Almeida Filho /// 329dc04365SWedson Almeida Filho /// # Examples 339dc04365SWedson Almeida Filho /// 349dc04365SWedson Almeida Filho /// ``` 359dc04365SWedson Almeida Filho /// use kernel::sync::Arc; 369dc04365SWedson Almeida Filho /// 379dc04365SWedson Almeida Filho /// struct Example { 389dc04365SWedson Almeida Filho /// a: u32, 399dc04365SWedson Almeida Filho /// b: u32, 409dc04365SWedson Almeida Filho /// } 419dc04365SWedson Almeida Filho /// 429dc04365SWedson Almeida Filho /// // Create a ref-counted instance of `Example`. 439dc04365SWedson Almeida Filho /// let obj = Arc::try_new(Example { a: 10, b: 20 })?; 449dc04365SWedson Almeida Filho /// 459dc04365SWedson Almeida Filho /// // Get a new pointer to `obj` and increment the refcount. 469dc04365SWedson Almeida Filho /// let cloned = obj.clone(); 479dc04365SWedson Almeida Filho /// 489dc04365SWedson Almeida Filho /// // Assert that both `obj` and `cloned` point to the same underlying object. 499dc04365SWedson Almeida Filho /// assert!(core::ptr::eq(&*obj, &*cloned)); 509dc04365SWedson Almeida Filho /// 519dc04365SWedson Almeida Filho /// // Destroy `obj` and decrement its refcount. 529dc04365SWedson Almeida Filho /// drop(obj); 539dc04365SWedson Almeida Filho /// 549dc04365SWedson Almeida Filho /// // Check that the values are still accessible through `cloned`. 559dc04365SWedson Almeida Filho /// assert_eq!(cloned.a, 10); 569dc04365SWedson Almeida Filho /// assert_eq!(cloned.b, 20); 579dc04365SWedson Almeida Filho /// 589dc04365SWedson Almeida Filho /// // The refcount drops to zero when `cloned` goes out of scope, and the memory is freed. 599dc04365SWedson Almeida Filho /// ``` 60*53528772SWedson Almeida Filho /// 61*53528772SWedson Almeida Filho /// Using `Arc<T>` as the type of `self`: 62*53528772SWedson Almeida Filho /// 63*53528772SWedson Almeida Filho /// ``` 64*53528772SWedson Almeida Filho /// use kernel::sync::Arc; 65*53528772SWedson Almeida Filho /// 66*53528772SWedson Almeida Filho /// struct Example { 67*53528772SWedson Almeida Filho /// a: u32, 68*53528772SWedson Almeida Filho /// b: u32, 69*53528772SWedson Almeida Filho /// } 70*53528772SWedson Almeida Filho /// 71*53528772SWedson Almeida Filho /// impl Example { 72*53528772SWedson Almeida Filho /// fn take_over(self: Arc<Self>) { 73*53528772SWedson Almeida Filho /// // ... 74*53528772SWedson Almeida Filho /// } 75*53528772SWedson Almeida Filho /// 76*53528772SWedson Almeida Filho /// fn use_reference(self: &Arc<Self>) { 77*53528772SWedson Almeida Filho /// // ... 78*53528772SWedson Almeida Filho /// } 79*53528772SWedson Almeida Filho /// } 80*53528772SWedson Almeida Filho /// 81*53528772SWedson Almeida Filho /// let obj = Arc::try_new(Example { a: 10, b: 20 })?; 82*53528772SWedson Almeida Filho /// obj.use_reference(); 83*53528772SWedson Almeida Filho /// obj.take_over(); 84*53528772SWedson Almeida Filho /// ``` 859dc04365SWedson Almeida Filho pub struct Arc<T: ?Sized> { 869dc04365SWedson Almeida Filho ptr: NonNull<ArcInner<T>>, 879dc04365SWedson Almeida Filho _p: PhantomData<ArcInner<T>>, 889dc04365SWedson Almeida Filho } 899dc04365SWedson Almeida Filho 909dc04365SWedson Almeida Filho #[repr(C)] 919dc04365SWedson Almeida Filho struct ArcInner<T: ?Sized> { 929dc04365SWedson Almeida Filho refcount: Opaque<bindings::refcount_t>, 939dc04365SWedson Almeida Filho data: T, 949dc04365SWedson Almeida Filho } 959dc04365SWedson Almeida Filho 96*53528772SWedson Almeida Filho // This is to allow [`Arc`] (and variants) to be used as the type of `self`. 97*53528772SWedson Almeida Filho impl<T: ?Sized> core::ops::Receiver for Arc<T> {} 98*53528772SWedson Almeida Filho 999dc04365SWedson Almeida Filho // SAFETY: It is safe to send `Arc<T>` to another thread when the underlying `T` is `Sync` because 1009dc04365SWedson Almeida Filho // it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs 1019dc04365SWedson Almeida Filho // `T` to be `Send` because any thread that has an `Arc<T>` may ultimately access `T` directly, for 1029dc04365SWedson Almeida Filho // example, when the reference count reaches zero and `T` is dropped. 1039dc04365SWedson Almeida Filho unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {} 1049dc04365SWedson Almeida Filho 1059dc04365SWedson Almeida Filho // SAFETY: It is safe to send `&Arc<T>` to another thread when the underlying `T` is `Sync` for the 1069dc04365SWedson Almeida Filho // same reason as above. `T` needs to be `Send` as well because a thread can clone an `&Arc<T>` 1079dc04365SWedson Almeida Filho // into an `Arc<T>`, which may lead to `T` being accessed by the same reasoning as above. 1089dc04365SWedson Almeida Filho unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {} 1099dc04365SWedson Almeida Filho 1109dc04365SWedson Almeida Filho impl<T> Arc<T> { 1119dc04365SWedson Almeida Filho /// Constructs a new reference counted instance of `T`. 1129dc04365SWedson Almeida Filho pub fn try_new(contents: T) -> Result<Self> { 1139dc04365SWedson Almeida Filho // INVARIANT: The refcount is initialised to a non-zero value. 1149dc04365SWedson Almeida Filho let value = ArcInner { 1159dc04365SWedson Almeida Filho // SAFETY: There are no safety requirements for this FFI call. 1169dc04365SWedson Almeida Filho refcount: Opaque::new(unsafe { bindings::REFCOUNT_INIT(1) }), 1179dc04365SWedson Almeida Filho data: contents, 1189dc04365SWedson Almeida Filho }; 1199dc04365SWedson Almeida Filho 1209dc04365SWedson Almeida Filho let inner = Box::try_new(value)?; 1219dc04365SWedson Almeida Filho 1229dc04365SWedson Almeida Filho // SAFETY: We just created `inner` with a reference count of 1, which is owned by the new 1239dc04365SWedson Almeida Filho // `Arc` object. 1249dc04365SWedson Almeida Filho Ok(unsafe { Self::from_inner(Box::leak(inner).into()) }) 1259dc04365SWedson Almeida Filho } 1269dc04365SWedson Almeida Filho } 1279dc04365SWedson Almeida Filho 1289dc04365SWedson Almeida Filho impl<T: ?Sized> Arc<T> { 1299dc04365SWedson Almeida Filho /// Constructs a new [`Arc`] from an existing [`ArcInner`]. 1309dc04365SWedson Almeida Filho /// 1319dc04365SWedson Almeida Filho /// # Safety 1329dc04365SWedson Almeida Filho /// 1339dc04365SWedson Almeida Filho /// The caller must ensure that `inner` points to a valid location and has a non-zero reference 1349dc04365SWedson Almeida Filho /// count, one of which will be owned by the new [`Arc`] instance. 1359dc04365SWedson Almeida Filho unsafe fn from_inner(inner: NonNull<ArcInner<T>>) -> Self { 1369dc04365SWedson Almeida Filho // INVARIANT: By the safety requirements, the invariants hold. 1379dc04365SWedson Almeida Filho Arc { 1389dc04365SWedson Almeida Filho ptr: inner, 1399dc04365SWedson Almeida Filho _p: PhantomData, 1409dc04365SWedson Almeida Filho } 1419dc04365SWedson Almeida Filho } 1429dc04365SWedson Almeida Filho } 1439dc04365SWedson Almeida Filho 1449dc04365SWedson Almeida Filho impl<T: ?Sized> Deref for Arc<T> { 1459dc04365SWedson Almeida Filho type Target = T; 1469dc04365SWedson Almeida Filho 1479dc04365SWedson Almeida Filho fn deref(&self) -> &Self::Target { 1489dc04365SWedson Almeida Filho // SAFETY: By the type invariant, there is necessarily a reference to the object, so it is 1499dc04365SWedson Almeida Filho // safe to dereference it. 1509dc04365SWedson Almeida Filho unsafe { &self.ptr.as_ref().data } 1519dc04365SWedson Almeida Filho } 1529dc04365SWedson Almeida Filho } 1539dc04365SWedson Almeida Filho 1549dc04365SWedson Almeida Filho impl<T: ?Sized> Clone for Arc<T> { 1559dc04365SWedson Almeida Filho fn clone(&self) -> Self { 1569dc04365SWedson Almeida Filho // INVARIANT: C `refcount_inc` saturates the refcount, so it cannot overflow to zero. 1579dc04365SWedson Almeida Filho // SAFETY: By the type invariant, there is necessarily a reference to the object, so it is 1589dc04365SWedson Almeida Filho // safe to increment the refcount. 1599dc04365SWedson Almeida Filho unsafe { bindings::refcount_inc(self.ptr.as_ref().refcount.get()) }; 1609dc04365SWedson Almeida Filho 1619dc04365SWedson Almeida Filho // SAFETY: We just incremented the refcount. This increment is now owned by the new `Arc`. 1629dc04365SWedson Almeida Filho unsafe { Self::from_inner(self.ptr) } 1639dc04365SWedson Almeida Filho } 1649dc04365SWedson Almeida Filho } 1659dc04365SWedson Almeida Filho 1669dc04365SWedson Almeida Filho impl<T: ?Sized> Drop for Arc<T> { 1679dc04365SWedson Almeida Filho fn drop(&mut self) { 1689dc04365SWedson Almeida Filho // SAFETY: By the type invariant, there is necessarily a reference to the object. We cannot 1699dc04365SWedson Almeida Filho // touch `refcount` after it's decremented to a non-zero value because another thread/CPU 1709dc04365SWedson Almeida Filho // may concurrently decrement it to zero and free it. It is ok to have a raw pointer to 1719dc04365SWedson Almeida Filho // freed/invalid memory as long as it is never dereferenced. 1729dc04365SWedson Almeida Filho let refcount = unsafe { self.ptr.as_ref() }.refcount.get(); 1739dc04365SWedson Almeida Filho 1749dc04365SWedson Almeida Filho // INVARIANT: If the refcount reaches zero, there are no other instances of `Arc`, and 1759dc04365SWedson Almeida Filho // this instance is being dropped, so the broken invariant is not observable. 1769dc04365SWedson Almeida Filho // SAFETY: Also by the type invariant, we are allowed to decrement the refcount. 1779dc04365SWedson Almeida Filho let is_zero = unsafe { bindings::refcount_dec_and_test(refcount) }; 1789dc04365SWedson Almeida Filho if is_zero { 1799dc04365SWedson Almeida Filho // The count reached zero, we must free the memory. 1809dc04365SWedson Almeida Filho // 1819dc04365SWedson Almeida Filho // SAFETY: The pointer was initialised from the result of `Box::leak`. 1829dc04365SWedson Almeida Filho unsafe { Box::from_raw(self.ptr.as_ptr()) }; 1839dc04365SWedson Almeida Filho } 1849dc04365SWedson Almeida Filho } 1859dc04365SWedson Almeida Filho } 186