This source file includes following definitions.
- refcount_set
- refcount_read
- refcount_inc_not_zero
- refcount_inc
- refcount_sub_and_test
- refcount_dec_and_test
1
2 #ifndef _TOOLS_LINUX_REFCOUNT_H
3 #define _TOOLS_LINUX_REFCOUNT_H
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 #include <linux/atomic.h>
42 #include <linux/kernel.h>
43
44 #ifdef NDEBUG
45 #define REFCOUNT_WARN(cond, str) (void)(cond)
46 #define __refcount_check
47 #else
48 #define REFCOUNT_WARN(cond, str) BUG_ON(cond)
49 #define __refcount_check __must_check
50 #endif
51
52 typedef struct refcount_struct {
53 atomic_t refs;
54 } refcount_t;
55
56 #define REFCOUNT_INIT(n) { .refs = ATOMIC_INIT(n), }
57
58 static inline void refcount_set(refcount_t *r, unsigned int n)
59 {
60 atomic_set(&r->refs, n);
61 }
62
63 static inline unsigned int refcount_read(const refcount_t *r)
64 {
65 return atomic_read(&r->refs);
66 }
67
68
69
70
71
72
73
74
75 static inline __refcount_check
76 bool refcount_inc_not_zero(refcount_t *r)
77 {
78 unsigned int old, new, val = atomic_read(&r->refs);
79
80 for (;;) {
81 new = val + 1;
82
83 if (!val)
84 return false;
85
86 if (unlikely(!new))
87 return true;
88
89 old = atomic_cmpxchg_relaxed(&r->refs, val, new);
90 if (old == val)
91 break;
92
93 val = old;
94 }
95
96 REFCOUNT_WARN(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n");
97
98 return true;
99 }
100
101
102
103
104
105
106
107 static inline void refcount_inc(refcount_t *r)
108 {
109 REFCOUNT_WARN(!refcount_inc_not_zero(r), "refcount_t: increment on 0; use-after-free.\n");
110 }
111
112
113
114
115
116
117
118
119
120 static inline __refcount_check
121 bool refcount_sub_and_test(unsigned int i, refcount_t *r)
122 {
123 unsigned int old, new, val = atomic_read(&r->refs);
124
125 for (;;) {
126 if (unlikely(val == UINT_MAX))
127 return false;
128
129 new = val - i;
130 if (new > val) {
131 REFCOUNT_WARN(new > val, "refcount_t: underflow; use-after-free.\n");
132 return false;
133 }
134
135 old = atomic_cmpxchg_release(&r->refs, val, new);
136 if (old == val)
137 break;
138
139 val = old;
140 }
141
142 return !new;
143 }
144
145 static inline __refcount_check
146 bool refcount_dec_and_test(refcount_t *r)
147 {
148 return refcount_sub_and_test(1, r);
149 }
150
151
152 #endif