1bb38f35bSGary Guo // SPDX-License-Identifier: GPL-2.0 2bb38f35bSGary Guo 3bb38f35bSGary Guo //! Atomic reference counting. 4bb38f35bSGary Guo //! 5bb38f35bSGary Guo //! C header: [`include/linux/refcount.h`](srctree/include/linux/refcount.h) 6bb38f35bSGary Guo 7bb38f35bSGary Guo use crate::build_assert; 8*a307bf1dSGary Guo use crate::sync::atomic::Atomic; 9bb38f35bSGary Guo use crate::types::Opaque; 10bb38f35bSGary Guo 11bb38f35bSGary Guo /// Atomic reference counter. 12bb38f35bSGary Guo /// 13bb38f35bSGary Guo /// This type is conceptually an atomic integer, but provides saturation semantics compared to 14bb38f35bSGary Guo /// normal atomic integers. Values in the negative range when viewed as a signed integer are 15bb38f35bSGary Guo /// saturation (bad) values. For details about the saturation semantics, please refer to top of 16bb38f35bSGary Guo /// [`include/linux/refcount.h`](srctree/include/linux/refcount.h). 17bb38f35bSGary Guo /// 18bb38f35bSGary Guo /// Wraps the kernel's C `refcount_t`. 19bb38f35bSGary Guo #[repr(transparent)] 20bb38f35bSGary Guo pub struct Refcount(Opaque<bindings::refcount_t>); 21bb38f35bSGary Guo 22bb38f35bSGary Guo impl Refcount { 23bb38f35bSGary Guo /// Construct a new [`Refcount`] from an initial value. 24bb38f35bSGary Guo /// 25bb38f35bSGary Guo /// The initial value should be non-saturated. 26bb38f35bSGary Guo #[inline] 27bb38f35bSGary Guo pub fn new(value: i32) -> Self { 28bb38f35bSGary Guo build_assert!(value >= 0, "initial value saturated"); 29bb38f35bSGary Guo // SAFETY: There are no safety requirements for this FFI call. 30bb38f35bSGary Guo Self(Opaque::new(unsafe { bindings::REFCOUNT_INIT(value) })) 31bb38f35bSGary Guo } 32bb38f35bSGary Guo 33bb38f35bSGary Guo #[inline] 34bb38f35bSGary Guo fn as_ptr(&self) -> *mut bindings::refcount_t { 35bb38f35bSGary Guo self.0.get() 36bb38f35bSGary Guo } 37bb38f35bSGary Guo 38*a307bf1dSGary Guo /// Get the underlying atomic counter that backs the refcount. 39*a307bf1dSGary Guo /// 40*a307bf1dSGary Guo /// NOTE: Usage of this function is discouraged as it can circumvent the protections offered by 41*a307bf1dSGary Guo /// `refcount.h`. If there is no way to achieve the result using APIs in `refcount.h`, then 42*a307bf1dSGary Guo /// this function can be used. Otherwise consider adding a binding for the required API. 43*a307bf1dSGary Guo #[inline] 44*a307bf1dSGary Guo pub fn as_atomic(&self) -> &Atomic<i32> { 45*a307bf1dSGary Guo let ptr = self.0.get().cast(); 46*a307bf1dSGary Guo // SAFETY: `refcount_t` is a transparent wrapper of `atomic_t`, which is an atomic 32-bit 47*a307bf1dSGary Guo // integer that is layout-wise compatible with `Atomic<i32>`. All values are valid for 48*a307bf1dSGary Guo // `refcount_t`, despite some of the values being considered saturated and "bad". 49*a307bf1dSGary Guo unsafe { &*ptr } 50*a307bf1dSGary Guo } 51*a307bf1dSGary Guo 52bb38f35bSGary Guo /// Set a refcount's value. 53bb38f35bSGary Guo #[inline] 54bb38f35bSGary Guo pub fn set(&self, value: i32) { 55bb38f35bSGary Guo // SAFETY: `self.as_ptr()` is valid. 56bb38f35bSGary Guo unsafe { bindings::refcount_set(self.as_ptr(), value) } 57bb38f35bSGary Guo } 58bb38f35bSGary Guo 59bb38f35bSGary Guo /// Increment a refcount. 60bb38f35bSGary Guo /// 61bb38f35bSGary Guo /// It will saturate if overflows and `WARN`. It will also `WARN` if the refcount is 0, as this 62bb38f35bSGary Guo /// represents a possible use-after-free condition. 63bb38f35bSGary Guo /// 64bb38f35bSGary Guo /// Provides no memory ordering, it is assumed that caller already has a reference on the 65bb38f35bSGary Guo /// object. 66bb38f35bSGary Guo #[inline] 67bb38f35bSGary Guo pub fn inc(&self) { 68bb38f35bSGary Guo // SAFETY: self is valid. 69bb38f35bSGary Guo unsafe { bindings::refcount_inc(self.as_ptr()) } 70bb38f35bSGary Guo } 71bb38f35bSGary Guo 72bb38f35bSGary Guo /// Decrement a refcount. 73bb38f35bSGary Guo /// 74bb38f35bSGary Guo /// It will `WARN` on underflow and fail to decrement when saturated. 75bb38f35bSGary Guo /// 76bb38f35bSGary Guo /// Provides release memory ordering, such that prior loads and stores are done 77bb38f35bSGary Guo /// before. 78bb38f35bSGary Guo #[inline] 79bb38f35bSGary Guo pub fn dec(&self) { 80bb38f35bSGary Guo // SAFETY: `self.as_ptr()` is valid. 81bb38f35bSGary Guo unsafe { bindings::refcount_dec(self.as_ptr()) } 82bb38f35bSGary Guo } 83bb38f35bSGary Guo 84bb38f35bSGary Guo /// Decrement a refcount and test if it is 0. 85bb38f35bSGary Guo /// 86bb38f35bSGary Guo /// It will `WARN` on underflow and fail to decrement when saturated. 87bb38f35bSGary Guo /// 88bb38f35bSGary Guo /// Provides release memory ordering, such that prior loads and stores are done 89bb38f35bSGary Guo /// before, and provides an acquire ordering on success such that memory deallocation 90bb38f35bSGary Guo /// must come after. 91bb38f35bSGary Guo /// 92bb38f35bSGary Guo /// Returns true if the resulting refcount is 0, false otherwise. 93bb38f35bSGary Guo /// 94bb38f35bSGary Guo /// # Notes 95bb38f35bSGary Guo /// 96bb38f35bSGary Guo /// A common pattern of using `Refcount` is to free memory when the reference count reaches 97bb38f35bSGary Guo /// zero. This means that the reference to `Refcount` could become invalid after calling this 98bb38f35bSGary Guo /// function. This is fine as long as the reference to `Refcount` is no longer used when this 99bb38f35bSGary Guo /// function returns `false`. It is not necessary to use raw pointers in this scenario, see 100bb38f35bSGary Guo /// <https://github.com/rust-lang/rust/issues/55005>. 101bb38f35bSGary Guo #[inline] 102bb38f35bSGary Guo #[must_use = "use `dec` instead if you do not need to test if it is 0"] 103bb38f35bSGary Guo pub fn dec_and_test(&self) -> bool { 104bb38f35bSGary Guo // SAFETY: `self.as_ptr()` is valid. 105bb38f35bSGary Guo unsafe { bindings::refcount_dec_and_test(self.as_ptr()) } 106bb38f35bSGary Guo } 107bb38f35bSGary Guo } 108bb38f35bSGary Guo 109bb38f35bSGary Guo // SAFETY: `refcount_t` is thread-safe. 110bb38f35bSGary Guo unsafe impl Send for Refcount {} 111bb38f35bSGary Guo 112bb38f35bSGary Guo // SAFETY: `refcount_t` is thread-safe. 113bb38f35bSGary Guo unsafe impl Sync for Refcount {} 114