]> git.sesse.net Git - bcachefs-tools-debian/blob - include/linux/percpu-refcount.h
cmd_migrate
[bcachefs-tools-debian] / include / linux / percpu-refcount.h
1 #ifndef __TOOLS_LINUX_PERCPU_REFCOUNT_H
2 #define __TOOLS_LINUX_PERCPU_REFCOUNT_H
3
4 #include <linux/atomic.h>
5 #include <linux/kernel.h>
6 #include <linux/percpu.h>
7
8 struct percpu_ref;
9 typedef void (percpu_ref_func_t)(struct percpu_ref *);
10
11 /* flags set in the lower bits of percpu_ref->percpu_count_ptr */
12 enum {
13         __PERCPU_REF_ATOMIC     = 1LU << 0,     /* operating in atomic mode */
14         __PERCPU_REF_DEAD       = 1LU << 1,     /* (being) killed */
15         __PERCPU_REF_ATOMIC_DEAD = __PERCPU_REF_ATOMIC | __PERCPU_REF_DEAD,
16
17         __PERCPU_REF_FLAG_BITS  = 2,
18 };
19
20 /* @flags for percpu_ref_init() */
21 enum {
22         /*
23          * Start w/ ref == 1 in atomic mode.  Can be switched to percpu
24          * operation using percpu_ref_switch_to_percpu().  If initialized
25          * with this flag, the ref will stay in atomic mode until
26          * percpu_ref_switch_to_percpu() is invoked on it.
27          */
28         PERCPU_REF_INIT_ATOMIC  = 1 << 0,
29
30         /*
31          * Start dead w/ ref == 0 in atomic mode.  Must be revived with
32          * percpu_ref_reinit() before used.  Implies INIT_ATOMIC.
33          */
34         PERCPU_REF_INIT_DEAD    = 1 << 1,
35 };
36
37 struct percpu_ref {
38         atomic_long_t           count;
39         percpu_ref_func_t       *release;
40         percpu_ref_func_t       *confirm_switch;
41 };
42
43 static inline void percpu_ref_exit(struct percpu_ref *ref) {}
44
45 static inline int __must_check percpu_ref_init(struct percpu_ref *ref,
46                                  percpu_ref_func_t *release, unsigned int flags,
47                                  gfp_t gfp)
48 {
49         unsigned long start_count = 0;
50
51         if (!(flags & PERCPU_REF_INIT_DEAD))
52                 start_count++;
53
54         atomic_long_set(&ref->count, start_count);
55
56         ref->release = release;
57         return 0;
58 }
59
60 static inline void percpu_ref_switch_to_atomic(struct percpu_ref *ref,
61                                  percpu_ref_func_t *confirm_switch) {}
62
63 static inline void percpu_ref_switch_to_percpu(struct percpu_ref *ref) {}
64
65 static inline void percpu_ref_reinit(struct percpu_ref *ref) {}
66
67 /**
68  * percpu_ref_get_many - increment a percpu refcount
69  * @ref: percpu_ref to get
70  * @nr: number of references to get
71  *
72  * Analogous to atomic_long_add().
73  *
74  * This function is safe to call as long as @ref is between init and exit.
75  */
76 static inline void percpu_ref_get_many(struct percpu_ref *ref, unsigned long nr)
77 {
78         atomic_long_add(nr, &ref->count);
79 }
80
81 /**
82  * percpu_ref_get - increment a percpu refcount
83  * @ref: percpu_ref to get
84  *
85  * Analagous to atomic_long_inc().
86  *
87  * This function is safe to call as long as @ref is between init and exit.
88  */
89 static inline void percpu_ref_get(struct percpu_ref *ref)
90 {
91         percpu_ref_get_many(ref, 1);
92 }
93
94 /**
95  * percpu_ref_tryget - try to increment a percpu refcount
96  * @ref: percpu_ref to try-get
97  *
98  * Increment a percpu refcount unless its count already reached zero.
99  * Returns %true on success; %false on failure.
100  *
101  * This function is safe to call as long as @ref is between init and exit.
102  */
103 static inline bool percpu_ref_tryget(struct percpu_ref *ref)
104 {
105         return atomic_long_inc_not_zero(&ref->count);
106 }
107
108 /**
109  * percpu_ref_tryget_live - try to increment a live percpu refcount
110  * @ref: percpu_ref to try-get
111  *
112  * Increment a percpu refcount unless it has already been killed.  Returns
113  * %true on success; %false on failure.
114  *
115  * Completion of percpu_ref_kill() in itself doesn't guarantee that this
116  * function will fail.  For such guarantee, percpu_ref_kill_and_confirm()
117  * should be used.  After the confirm_kill callback is invoked, it's
118  * guaranteed that no new reference will be given out by
119  * percpu_ref_tryget_live().
120  *
121  * This function is safe to call as long as @ref is between init and exit.
122  */
123 static inline bool percpu_ref_tryget_live(struct percpu_ref *ref)
124 {
125         return atomic_long_inc_not_zero(&ref->count);
126 }
127
128 /**
129  * percpu_ref_put_many - decrement a percpu refcount
130  * @ref: percpu_ref to put
131  * @nr: number of references to put
132  *
133  * Decrement the refcount, and if 0, call the release function (which was passed
134  * to percpu_ref_init())
135  *
136  * This function is safe to call as long as @ref is between init and exit.
137  */
138 static inline void percpu_ref_put_many(struct percpu_ref *ref, unsigned long nr)
139 {
140         if (unlikely(atomic_long_sub_and_test(nr, &ref->count)))
141                 ref->release(ref);
142 }
143
144 /**
145  * percpu_ref_put - decrement a percpu refcount
146  * @ref: percpu_ref to put
147  *
148  * Decrement the refcount, and if 0, call the release function (which was passed
149  * to percpu_ref_init())
150  *
151  * This function is safe to call as long as @ref is between init and exit.
152  */
153 static inline void percpu_ref_put(struct percpu_ref *ref)
154 {
155         percpu_ref_put_many(ref, 1);
156 }
157
158 /**
159  * percpu_ref_kill - drop the initial ref
160  * @ref: percpu_ref to kill
161  *
162  * Must be used to drop the initial ref on a percpu refcount; must be called
163  * precisely once before shutdown.
164  */
165 static inline void percpu_ref_kill(struct percpu_ref *ref)
166 {
167         percpu_ref_put(ref);
168 }
169
170 /**
171  * percpu_ref_is_zero - test whether a percpu refcount reached zero
172  * @ref: percpu_ref to test
173  *
174  * Returns %true if @ref reached zero.
175  *
176  * This function is safe to call as long as @ref is between init and exit.
177  */
178 static inline bool percpu_ref_is_zero(struct percpu_ref *ref)
179 {
180         return !atomic_long_read(&ref->count);
181 }
182
183 static inline bool percpu_ref_is_dying(struct percpu_ref *ref)
184 {
185         return percpu_ref_is_zero(ref);
186 }
187
188 #endif /* __TOOLS_LINUX_PERCPU_REFCOUNT_H */