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