1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _LINUX_REFCOUNT_H 3 #define _LINUX_REFCOUNT_H 4 5 #include <linux/atomic.h> 6 #include <linux/compiler.h> 7 #include <linux/limits.h> 8 #include <linux/spinlock_types.h> 9 10 struct mutex; 11 12 /** 13 * struct refcount_t - variant of atomic_t specialized for reference counts 14 * @refs: atomic_t counter field 15 * 16 * The counter saturates at REFCOUNT_SATURATED and will not move once 17 * there. This avoids wrapping the counter and causing 'spurious' 18 * use-after-free bugs. 19 */ 20 typedef struct refcount_struct { 21 atomic_t refs; 22 } refcount_t; 23 24 #define REFCOUNT_INIT(n) { .refs = ATOMIC_INIT(n), } 25 26 /** 27 * refcount_set - set a refcount's value 28 * @r: the refcount 29 * @n: value to which the refcount will be set 30 */ 31 static inline void refcount_set(refcount_t *r, int n) 32 { 33 atomic_set(&r->refs, n); 34 } 35 36 /** 37 * refcount_read - get a refcount's value 38 * @r: the refcount 39 * 40 * Return: the refcount's value 41 */ 42 static inline unsigned int refcount_read(const refcount_t *r) 43 { 44 return atomic_read(&r->refs); 45 } 46 47 #ifdef CONFIG_REFCOUNT_FULL 48 49 #define REFCOUNT_MAX (UINT_MAX - 1) 50 #define REFCOUNT_SATURATED UINT_MAX 51 52 extern __must_check bool refcount_add_not_zero(int i, refcount_t *r); 53 extern void refcount_add(int i, refcount_t *r); 54 55 extern __must_check bool refcount_inc_not_zero(refcount_t *r); 56 extern void refcount_inc(refcount_t *r); 57 58 extern __must_check bool refcount_sub_and_test(int i, refcount_t *r); 59 60 extern __must_check bool refcount_dec_and_test(refcount_t *r); 61 extern void refcount_dec(refcount_t *r); 62 63 #else 64 65 #define REFCOUNT_MAX INT_MAX 66 #define REFCOUNT_SATURATED (INT_MIN / 2) 67 68 # ifdef CONFIG_ARCH_HAS_REFCOUNT 69 # include <asm/refcount.h> 70 # else 71 static inline __must_check bool refcount_add_not_zero(int i, refcount_t *r) 72 { 73 return atomic_add_unless(&r->refs, i, 0); 74 } 75 76 static inline void refcount_add(int i, refcount_t *r) 77 { 78 atomic_add(i, &r->refs); 79 } 80 81 static inline __must_check bool refcount_inc_not_zero(refcount_t *r) 82 { 83 return atomic_add_unless(&r->refs, 1, 0); 84 } 85 86 static inline void refcount_inc(refcount_t *r) 87 { 88 atomic_inc(&r->refs); 89 } 90 91 static inline __must_check bool refcount_sub_and_test(int i, refcount_t *r) 92 { 93 return atomic_sub_and_test(i, &r->refs); 94 } 95 96 static inline __must_check bool refcount_dec_and_test(refcount_t *r) 97 { 98 return atomic_dec_and_test(&r->refs); 99 } 100 101 static inline void refcount_dec(refcount_t *r) 102 { 103 atomic_dec(&r->refs); 104 } 105 # endif /* !CONFIG_ARCH_HAS_REFCOUNT */ 106 #endif /* CONFIG_REFCOUNT_FULL */ 107 108 extern __must_check bool refcount_dec_if_one(refcount_t *r); 109 extern __must_check bool refcount_dec_not_one(refcount_t *r); 110 extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock); 111 extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock); 112 extern __must_check bool refcount_dec_and_lock_irqsave(refcount_t *r, 113 spinlock_t *lock, 114 unsigned long *flags); 115 #endif /* _LINUX_REFCOUNT_H */ 116