Blame view
include/linux/percpu-refcount.h
10.8 KB
b24413180 License cleanup: ... |
1 |
/* SPDX-License-Identifier: GPL-2.0 */ |
215e262f2 percpu: implement... |
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/* * Percpu refcounts: * (C) 2012 Google, Inc. * Author: Kent Overstreet <koverstreet@google.com> * * This implements a refcount with similar semantics to atomic_t - atomic_inc(), * atomic_dec_and_test() - but percpu. * * There's one important difference between percpu refs and normal atomic_t * refcounts; you have to keep track of your initial refcount, and then when you * start shutting down you call percpu_ref_kill() _before_ dropping the initial * refcount. * * The refcount will have a range of 0 to ((1U << 31) - 1), i.e. one bit less * than an atomic_t - this is because of the way shutdown works, see |
eecc16ba9 percpu_ref: repla... |
17 |
* percpu_ref_kill()/PERCPU_COUNT_BIAS. |
215e262f2 percpu: implement... |
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
* * Before you call percpu_ref_kill(), percpu_ref_put() does not check for the * refcount hitting 0 - it can't, if it was in percpu mode. percpu_ref_kill() * puts the ref back in single atomic_t mode, collecting the per cpu refs and * issuing the appropriate barriers, and then marks the ref as shutting down so * that percpu_ref_put() will check for the ref hitting 0. After it returns, * it's safe to drop the initial ref. * * USAGE: * * See fs/aio.c for some example usage; it's used there for struct kioctx, which * is created when userspaces calls io_setup(), and destroyed when userspace * calls io_destroy() or the process exits. * * In the aio code, kill_ioctx() is called when we wish to destroy a kioctx; it |
b3a5d1119 percpu_ref: Updat... |
33 34 35 36 37 38 39 40 |
* removes the kioctx from the proccess's table of kioctxs and kills percpu_ref. * After that, there can't be any new users of the kioctx (from lookup_ioctx()) * and it's then safe to drop the initial ref with percpu_ref_put(). * * Note that the free path, free_ioctx(), needs to go through explicit call_rcu() * to synchronize with RCU protected lookup_ioctx(). percpu_ref operations don't * imply RCU grace periods of any kind and if a user wants to combine percpu_ref * with RCU protection, it must be done explicitly. |
215e262f2 percpu: implement... |
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
* * Code that does a two stage shutdown like this often needs some kind of * explicit synchronization to ensure the initial refcount can only be dropped * once - percpu_ref_kill() does this for you, it returns true once and false if * someone else already called it. The aio code uses it this way, but it's not * necessary if the code has some other mechanism to synchronize teardown. * around. */ #ifndef _LINUX_PERCPU_REFCOUNT_H #define _LINUX_PERCPU_REFCOUNT_H #include <linux/atomic.h> #include <linux/kernel.h> #include <linux/percpu.h> #include <linux/rcupdate.h> |
a34375ef9 percpu-refcount: ... |
57 |
#include <linux/gfp.h> |
215e262f2 percpu: implement... |
58 59 |
struct percpu_ref; |
ac899061a percpu-refcount: ... |
60 |
typedef void (percpu_ref_func_t)(struct percpu_ref *); |
215e262f2 percpu: implement... |
61 |
|
9e804d1f5 percpu_ref: renam... |
62 63 64 |
/* flags set in the lower bits of percpu_ref->percpu_count_ptr */ enum { __PERCPU_REF_ATOMIC = 1LU << 0, /* operating in atomic mode */ |
27344a901 percpu_ref: add P... |
65 66 67 68 |
__PERCPU_REF_DEAD = 1LU << 1, /* (being) killed */ __PERCPU_REF_ATOMIC_DEAD = __PERCPU_REF_ATOMIC | __PERCPU_REF_DEAD, __PERCPU_REF_FLAG_BITS = 2, |
9e804d1f5 percpu_ref: renam... |
69 |
}; |
2aad2a86f percpu_ref: add P... |
70 71 72 73 |
/* @flags for percpu_ref_init() */ enum { /* * Start w/ ref == 1 in atomic mode. Can be switched to percpu |
1cae13e75 percpu_ref: make ... |
74 75 76 |
* operation using percpu_ref_switch_to_percpu(). If initialized * with this flag, the ref will stay in atomic mode until * percpu_ref_switch_to_percpu() is invoked on it. |
09ed79d6d percpu_ref: intro... |
77 |
* Implies ALLOW_REINIT. |
2aad2a86f percpu_ref: add P... |
78 79 80 81 82 |
*/ PERCPU_REF_INIT_ATOMIC = 1 << 0, /* * Start dead w/ ref == 0 in atomic mode. Must be revived with |
09ed79d6d percpu_ref: intro... |
83 84 |
* percpu_ref_reinit() before used. Implies INIT_ATOMIC and * ALLOW_REINIT. |
2aad2a86f percpu_ref: add P... |
85 86 |
*/ PERCPU_REF_INIT_DEAD = 1 << 1, |
09ed79d6d percpu_ref: intro... |
87 88 89 90 91 |
/* * Allow switching from atomic mode to percpu mode. */ PERCPU_REF_ALLOW_REINIT = 1 << 2, |
2aad2a86f percpu_ref: add P... |
92 |
}; |
2b0d3d3e4 percpu_ref: reduc... |
93 |
struct percpu_ref_data { |
e625305b3 percpu-refcount: ... |
94 |
atomic_long_t count; |
ac899061a percpu-refcount: ... |
95 |
percpu_ref_func_t *release; |
9e804d1f5 percpu_ref: renam... |
96 |
percpu_ref_func_t *confirm_switch; |
1cae13e75 percpu_ref: make ... |
97 |
bool force_atomic:1; |
7d9ab9b6a percpu_ref: relea... |
98 |
bool allow_reinit:1; |
215e262f2 percpu: implement... |
99 |
struct rcu_head rcu; |
2b0d3d3e4 percpu_ref: reduc... |
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
struct percpu_ref *ref; }; struct percpu_ref { /* * The low bit of the pointer indicates whether the ref is in percpu * mode; if set, then get/put will manipulate the atomic_t. */ unsigned long percpu_count_ptr; /* * 'percpu_ref' is often embedded into user structure, and only * 'percpu_count_ptr' is required in fast path, move other fields * into 'percpu_ref_data', so we can reduce memory footprint in * fast path. */ struct percpu_ref_data *data; |
215e262f2 percpu: implement... |
117 |
}; |
acac7883e percpu-refcount: ... |
118 |
int __must_check percpu_ref_init(struct percpu_ref *ref, |
2aad2a86f percpu_ref: add P... |
119 120 |
percpu_ref_func_t *release, unsigned int flags, gfp_t gfp); |
9a1049da9 percpu-refcount: ... |
121 |
void percpu_ref_exit(struct percpu_ref *ref); |
490c79a65 percpu_ref: decou... |
122 123 |
void percpu_ref_switch_to_atomic(struct percpu_ref *ref, percpu_ref_func_t *confirm_switch); |
210f7cdcf percpu-refcount: ... |
124 |
void percpu_ref_switch_to_atomic_sync(struct percpu_ref *ref); |
f47ad4578 percpu_ref: decou... |
125 |
void percpu_ref_switch_to_percpu(struct percpu_ref *ref); |
dbece3a0f percpu-refcount: ... |
126 127 |
void percpu_ref_kill_and_confirm(struct percpu_ref *ref, percpu_ref_func_t *confirm_kill); |
18c9a6bbe percpu-refcount: ... |
128 |
void percpu_ref_resurrect(struct percpu_ref *ref); |
f47ad4578 percpu_ref: decou... |
129 |
void percpu_ref_reinit(struct percpu_ref *ref); |
2b0d3d3e4 percpu_ref: reduc... |
130 |
bool percpu_ref_is_zero(struct percpu_ref *ref); |
dbece3a0f percpu-refcount: ... |
131 132 133 134 135 136 137 138 |
/** * percpu_ref_kill - drop the initial ref * @ref: percpu_ref to kill * * Must be used to drop the initial ref on a percpu refcount; must be called * precisely once before shutdown. * |
b3a5d1119 percpu_ref: Updat... |
139 140 141 142 |
* Switches @ref into atomic mode before gathering up the percpu counters * and dropping the initial ref. * * There are no implied RCU grace periods between kill and release. |
dbece3a0f percpu-refcount: ... |
143 144 145 |
*/ static inline void percpu_ref_kill(struct percpu_ref *ref) { |
4d4142696 percpu: Remove un... |
146 |
percpu_ref_kill_and_confirm(ref, NULL); |
dbece3a0f percpu-refcount: ... |
147 |
} |
215e262f2 percpu: implement... |
148 |
|
eae7975dd percpu-refcount: ... |
149 150 151 152 |
/* * Internal helper. Don't use outside percpu-refcount proper. The * function doesn't return the pointer and let the caller test it for NULL * because doing so forces the compiler to generate two conditional |
eecc16ba9 percpu_ref: repla... |
153 |
* branches as it can't assume that @ref->percpu_count is not NULL. |
eae7975dd percpu-refcount: ... |
154 |
*/ |
9e804d1f5 percpu_ref: renam... |
155 156 |
static inline bool __ref_is_percpu(struct percpu_ref *ref, unsigned long __percpu **percpu_countp) |
eae7975dd percpu-refcount: ... |
157 |
{ |
6810e4a39 percpu_ref: remov... |
158 159 160 161 162 163 164 165 |
unsigned long percpu_ptr; /* * The value of @ref->percpu_count_ptr is tested for * !__PERCPU_REF_ATOMIC, which may be set asynchronously, and then * used as a pointer. If the compiler generates a separate fetch * when using it as a pointer, __PERCPU_REF_ATOMIC may be set in * between contaminating the pointer value, meaning that |
ed8ebd1d5 percpu, locking: ... |
166 |
* READ_ONCE() is required when fetching it. |
b393e8b33 percpu: READ_ONCE... |
167 |
* |
c6cd2e011 include/linux: Re... |
168 |
* The dependency ordering from the READ_ONCE() pairs |
b393e8b33 percpu: READ_ONCE... |
169 |
* with smp_store_release() in __percpu_ref_switch_to_percpu(). |
6810e4a39 percpu_ref: remov... |
170 |
*/ |
ed8ebd1d5 percpu, locking: ... |
171 |
percpu_ptr = READ_ONCE(ref->percpu_count_ptr); |
4aab3b5b3 percpu-ref: fix D... |
172 173 174 175 176 177 178 |
/* * Theoretically, the following could test just ATOMIC; however, * then we'd have to mask off DEAD separately as DEAD may be * visible without ATOMIC if we race with percpu_ref_kill(). DEAD * implies ATOMIC anyway. Test them together. */ if (unlikely(percpu_ptr & __PERCPU_REF_ATOMIC_DEAD)) |
eae7975dd percpu-refcount: ... |
179 |
return false; |
eecc16ba9 percpu_ref: repla... |
180 |
*percpu_countp = (unsigned long __percpu *)percpu_ptr; |
eae7975dd percpu-refcount: ... |
181 182 |
return true; } |
215e262f2 percpu: implement... |
183 184 |
/** |
e8ea14cc6 mm: memcontrol: t... |
185 |
* percpu_ref_get_many - increment a percpu refcount |
ac899061a percpu-refcount: ... |
186 |
* @ref: percpu_ref to get |
e8ea14cc6 mm: memcontrol: t... |
187 |
* @nr: number of references to get |
215e262f2 percpu: implement... |
188 |
* |
e8ea14cc6 mm: memcontrol: t... |
189 |
* Analogous to atomic_long_add(). |
6251f9976 percpu_ref: minor... |
190 191 192 |
* * This function is safe to call as long as @ref is between init and exit. */ |
e8ea14cc6 mm: memcontrol: t... |
193 |
static inline void percpu_ref_get_many(struct percpu_ref *ref, unsigned long nr) |
215e262f2 percpu: implement... |
194 |
{ |
eecc16ba9 percpu_ref: repla... |
195 |
unsigned long __percpu *percpu_count; |
215e262f2 percpu: implement... |
196 |
|
9e8d42a0f percpu-refcount: ... |
197 |
rcu_read_lock(); |
215e262f2 percpu: implement... |
198 |
|
9e804d1f5 percpu_ref: renam... |
199 |
if (__ref_is_percpu(ref, &percpu_count)) |
e8ea14cc6 mm: memcontrol: t... |
200 |
this_cpu_add(*percpu_count, nr); |
215e262f2 percpu: implement... |
201 |
else |
2b0d3d3e4 percpu_ref: reduc... |
202 |
atomic_long_add(nr, &ref->data->count); |
215e262f2 percpu: implement... |
203 |
|
9e8d42a0f percpu-refcount: ... |
204 |
rcu_read_unlock(); |
215e262f2 percpu: implement... |
205 206 207 |
} /** |
e8ea14cc6 mm: memcontrol: t... |
208 209 210 211 212 213 214 215 216 217 218 219 220 |
* percpu_ref_get - increment a percpu refcount * @ref: percpu_ref to get * * Analagous to atomic_long_inc(). * * This function is safe to call as long as @ref is between init and exit. */ static inline void percpu_ref_get(struct percpu_ref *ref) { percpu_ref_get_many(ref, 1); } /** |
4e5ef0231 pcpu_ref: add per... |
221 |
* percpu_ref_tryget_many - try to increment a percpu refcount |
4fb6e2504 percpu-refcount: ... |
222 |
* @ref: percpu_ref to try-get |
4e5ef0231 pcpu_ref: add per... |
223 |
* @nr: number of references to get |
4fb6e2504 percpu-refcount: ... |
224 |
* |
4e5ef0231 pcpu_ref: add per... |
225 |
* Increment a percpu refcount by @nr unless its count already reached zero. |
4fb6e2504 percpu-refcount: ... |
226 227 |
* Returns %true on success; %false on failure. * |
6251f9976 percpu_ref: minor... |
228 |
* This function is safe to call as long as @ref is between init and exit. |
4fb6e2504 percpu-refcount: ... |
229 |
*/ |
4e5ef0231 pcpu_ref: add per... |
230 231 |
static inline bool percpu_ref_tryget_many(struct percpu_ref *ref, unsigned long nr) |
4fb6e2504 percpu-refcount: ... |
232 |
{ |
eecc16ba9 percpu_ref: repla... |
233 |
unsigned long __percpu *percpu_count; |
966d2b04e percpu-refcount: ... |
234 |
bool ret; |
4fb6e2504 percpu-refcount: ... |
235 |
|
9e8d42a0f percpu-refcount: ... |
236 |
rcu_read_lock(); |
4fb6e2504 percpu-refcount: ... |
237 |
|
9e804d1f5 percpu_ref: renam... |
238 |
if (__ref_is_percpu(ref, &percpu_count)) { |
4e5ef0231 pcpu_ref: add per... |
239 |
this_cpu_add(*percpu_count, nr); |
4fb6e2504 percpu-refcount: ... |
240 241 |
ret = true; } else { |
2b0d3d3e4 percpu_ref: reduc... |
242 |
ret = atomic_long_add_unless(&ref->data->count, nr, 0); |
4fb6e2504 percpu-refcount: ... |
243 |
} |
9e8d42a0f percpu-refcount: ... |
244 |
rcu_read_unlock(); |
4fb6e2504 percpu-refcount: ... |
245 246 247 248 249 |
return ret; } /** |
4e5ef0231 pcpu_ref: add per... |
250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
* percpu_ref_tryget - try to increment a percpu refcount * @ref: percpu_ref to try-get * * Increment a percpu refcount unless its count already reached zero. * Returns %true on success; %false on failure. * * This function is safe to call as long as @ref is between init and exit. */ static inline bool percpu_ref_tryget(struct percpu_ref *ref) { return percpu_ref_tryget_many(ref, 1); } /** |
2070d50e1 percpu-refcount: ... |
264 |
* percpu_ref_tryget_live - try to increment a live percpu refcount |
dbece3a0f percpu-refcount: ... |
265 266 267 268 269 |
* @ref: percpu_ref to try-get * * Increment a percpu refcount unless it has already been killed. Returns * %true on success; %false on failure. * |
6251f9976 percpu_ref: minor... |
270 271 272 273 274 |
* Completion of percpu_ref_kill() in itself doesn't guarantee that this * function will fail. For such guarantee, percpu_ref_kill_and_confirm() * should be used. After the confirm_kill callback is invoked, it's * guaranteed that no new reference will be given out by * percpu_ref_tryget_live(). |
4fb6e2504 percpu-refcount: ... |
275 |
* |
6251f9976 percpu_ref: minor... |
276 |
* This function is safe to call as long as @ref is between init and exit. |
dbece3a0f percpu-refcount: ... |
277 |
*/ |
2070d50e1 percpu-refcount: ... |
278 |
static inline bool percpu_ref_tryget_live(struct percpu_ref *ref) |
dbece3a0f percpu-refcount: ... |
279 |
{ |
eecc16ba9 percpu_ref: repla... |
280 |
unsigned long __percpu *percpu_count; |
966d2b04e percpu-refcount: ... |
281 |
bool ret = false; |
dbece3a0f percpu-refcount: ... |
282 |
|
9e8d42a0f percpu-refcount: ... |
283 |
rcu_read_lock(); |
dbece3a0f percpu-refcount: ... |
284 |
|
9e804d1f5 percpu_ref: renam... |
285 |
if (__ref_is_percpu(ref, &percpu_count)) { |
eecc16ba9 percpu_ref: repla... |
286 |
this_cpu_inc(*percpu_count); |
dbece3a0f percpu-refcount: ... |
287 |
ret = true; |
6810e4a39 percpu_ref: remov... |
288 |
} else if (!(ref->percpu_count_ptr & __PERCPU_REF_DEAD)) { |
2b0d3d3e4 percpu_ref: reduc... |
289 |
ret = atomic_long_inc_not_zero(&ref->data->count); |
dbece3a0f percpu-refcount: ... |
290 |
} |
9e8d42a0f percpu-refcount: ... |
291 |
rcu_read_unlock(); |
dbece3a0f percpu-refcount: ... |
292 293 294 295 296 |
return ret; } /** |
e8ea14cc6 mm: memcontrol: t... |
297 |
* percpu_ref_put_many - decrement a percpu refcount |
ac899061a percpu-refcount: ... |
298 |
* @ref: percpu_ref to put |
e8ea14cc6 mm: memcontrol: t... |
299 |
* @nr: number of references to put |
215e262f2 percpu: implement... |
300 301 302 |
* * Decrement the refcount, and if 0, call the release function (which was passed * to percpu_ref_init()) |
6251f9976 percpu_ref: minor... |
303 304 |
* * This function is safe to call as long as @ref is between init and exit. |
215e262f2 percpu: implement... |
305 |
*/ |
e8ea14cc6 mm: memcontrol: t... |
306 |
static inline void percpu_ref_put_many(struct percpu_ref *ref, unsigned long nr) |
215e262f2 percpu: implement... |
307 |
{ |
eecc16ba9 percpu_ref: repla... |
308 |
unsigned long __percpu *percpu_count; |
215e262f2 percpu: implement... |
309 |
|
9e8d42a0f percpu-refcount: ... |
310 |
rcu_read_lock(); |
215e262f2 percpu: implement... |
311 |
|
9e804d1f5 percpu_ref: renam... |
312 |
if (__ref_is_percpu(ref, &percpu_count)) |
e8ea14cc6 mm: memcontrol: t... |
313 |
this_cpu_sub(*percpu_count, nr); |
2b0d3d3e4 percpu_ref: reduc... |
314 315 |
else if (unlikely(atomic_long_sub_and_test(nr, &ref->data->count))) ref->data->release(ref); |
215e262f2 percpu: implement... |
316 |
|
9e8d42a0f percpu-refcount: ... |
317 |
rcu_read_unlock(); |
215e262f2 percpu: implement... |
318 |
} |
2d7227828 percpu-refcount: ... |
319 |
/** |
e8ea14cc6 mm: memcontrol: t... |
320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
* percpu_ref_put - decrement a percpu refcount * @ref: percpu_ref to put * * Decrement the refcount, and if 0, call the release function (which was passed * to percpu_ref_init()) * * This function is safe to call as long as @ref is between init and exit. */ static inline void percpu_ref_put(struct percpu_ref *ref) { percpu_ref_put_many(ref, 1); } /** |
4c907baf3 percpu_ref: imple... |
334 335 336 337 338 339 340 341 342 343 344 345 |
* percpu_ref_is_dying - test whether a percpu refcount is dying or dead * @ref: percpu_ref to test * * Returns %true if @ref is dying or dead. * * This function is safe to call as long as @ref is between init and exit * and the caller is responsible for synchronizing against state changes. */ static inline bool percpu_ref_is_dying(struct percpu_ref *ref) { return ref->percpu_count_ptr & __PERCPU_REF_DEAD; } |
215e262f2 percpu: implement... |
346 |
#endif |