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, unsigned 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 extern __must_check bool refcount_add_not_zero_checked(unsigned int i, refcount_t *r); 48 extern void refcount_add_checked(unsigned int i, refcount_t *r); 49 50 extern __must_check bool refcount_inc_not_zero_checked(refcount_t *r); 51 extern void refcount_inc_checked(refcount_t *r); 52 53 extern __must_check bool refcount_sub_and_test_checked(unsigned int i, refcount_t *r); 54 55 extern __must_check bool refcount_dec_and_test_checked(refcount_t *r); 56 extern void refcount_dec_checked(refcount_t *r); 57 58 #ifdef CONFIG_REFCOUNT_FULL 59 60 #define REFCOUNT_MAX (UINT_MAX - 1) 61 #define REFCOUNT_SATURATED UINT_MAX 62 63 #define refcount_add_not_zero refcount_add_not_zero_checked 64 #define refcount_add refcount_add_checked 65 66 #define refcount_inc_not_zero refcount_inc_not_zero_checked 67 #define refcount_inc refcount_inc_checked 68 69 #define refcount_sub_and_test refcount_sub_and_test_checked 70 71 #define refcount_dec_and_test refcount_dec_and_test_checked 72 #define refcount_dec refcount_dec_checked 73 74 #else 75 76 #define REFCOUNT_MAX INT_MAX 77 #define REFCOUNT_SATURATED (INT_MIN / 2) 78 79 # ifdef CONFIG_ARCH_HAS_REFCOUNT 80 # include <asm/refcount.h> 81 # else 82 static inline __must_check bool refcount_add_not_zero(unsigned int i, refcount_t *r) 83 { 84 return atomic_add_unless(&r->refs, i, 0); 85 } 86 87 static inline void refcount_add(unsigned int i, refcount_t *r) 88 { 89 atomic_add(i, &r->refs); 90 } 91 92 static inline __must_check bool refcount_inc_not_zero(refcount_t *r) 93 { 94 return atomic_add_unless(&r->refs, 1, 0); 95 } 96 97 static inline void refcount_inc(refcount_t *r) 98 { 99 atomic_inc(&r->refs); 100 } 101 102 static inline __must_check bool refcount_sub_and_test(unsigned int i, refcount_t *r) 103 { 104 return atomic_sub_and_test(i, &r->refs); 105 } 106 107 static inline __must_check bool refcount_dec_and_test(refcount_t *r) 108 { 109 return atomic_dec_and_test(&r->refs); 110 } 111 112 static inline void refcount_dec(refcount_t *r) 113 { 114 atomic_dec(&r->refs); 115 } 116 # endif /* !CONFIG_ARCH_HAS_REFCOUNT */ 117 #endif /* CONFIG_REFCOUNT_FULL */ 118 119 extern __must_check bool refcount_dec_if_one(refcount_t *r); 120 extern __must_check bool refcount_dec_not_one(refcount_t *r); 121 extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock); 122 extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock); 123 extern __must_check bool refcount_dec_and_lock_irqsave(refcount_t *r, 124 spinlock_t *lock, 125 unsigned long *flags); 126 #endif /* _LINUX_REFCOUNT_H */ 127