aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/percpu-refcount.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/percpu-refcount.h')
-rw-r--r--include/linux/percpu-refcount.h50
1 files changed, 49 insertions, 1 deletions
diff --git a/include/linux/percpu-refcount.h b/include/linux/percpu-refcount.h
index 6d843d60690d..dd2a08600453 100644
--- a/include/linux/percpu-refcount.h
+++ b/include/linux/percpu-refcount.h
@@ -63,13 +63,30 @@ struct percpu_ref {
63 */ 63 */
64 unsigned __percpu *pcpu_count; 64 unsigned __percpu *pcpu_count;
65 percpu_ref_func_t *release; 65 percpu_ref_func_t *release;
66 percpu_ref_func_t *confirm_kill;
66 struct rcu_head rcu; 67 struct rcu_head rcu;
67}; 68};
68 69
69int __must_check percpu_ref_init(struct percpu_ref *ref, 70int __must_check percpu_ref_init(struct percpu_ref *ref,
70 percpu_ref_func_t *release); 71 percpu_ref_func_t *release);
71void percpu_ref_cancel_init(struct percpu_ref *ref); 72void percpu_ref_cancel_init(struct percpu_ref *ref);
72void percpu_ref_kill(struct percpu_ref *ref); 73void percpu_ref_kill_and_confirm(struct percpu_ref *ref,
74 percpu_ref_func_t *confirm_kill);
75
76/**
77 * percpu_ref_kill - drop the initial ref
78 * @ref: percpu_ref to kill
79 *
80 * Must be used to drop the initial ref on a percpu refcount; must be called
81 * precisely once before shutdown.
82 *
83 * Puts @ref in non percpu mode, then does a call_rcu() before gathering up the
84 * percpu counters and dropping the initial ref.
85 */
86static inline void percpu_ref_kill(struct percpu_ref *ref)
87{
88 return percpu_ref_kill_and_confirm(ref, NULL);
89}
73 90
74#define PCPU_STATUS_BITS 2 91#define PCPU_STATUS_BITS 2
75#define PCPU_STATUS_MASK ((1 << PCPU_STATUS_BITS) - 1) 92#define PCPU_STATUS_MASK ((1 << PCPU_STATUS_BITS) - 1)
@@ -101,6 +118,37 @@ static inline void percpu_ref_get(struct percpu_ref *ref)
101} 118}
102 119
103/** 120/**
121 * percpu_ref_tryget - try to increment a percpu refcount
122 * @ref: percpu_ref to try-get
123 *
124 * Increment a percpu refcount unless it has already been killed. Returns
125 * %true on success; %false on failure.
126 *
127 * Completion of percpu_ref_kill() in itself doesn't guarantee that tryget
128 * will fail. For such guarantee, percpu_ref_kill_and_confirm() should be
129 * used. After the confirm_kill callback is invoked, it's guaranteed that
130 * no new reference will be given out by percpu_ref_tryget().
131 */
132static inline bool percpu_ref_tryget(struct percpu_ref *ref)
133{
134 unsigned __percpu *pcpu_count;
135 int ret = false;
136
137 rcu_read_lock();
138
139 pcpu_count = ACCESS_ONCE(ref->pcpu_count);
140
141 if (likely(REF_STATUS(pcpu_count) == PCPU_REF_PTR)) {
142 __this_cpu_inc(*pcpu_count);
143 ret = true;
144 }
145
146 rcu_read_unlock();
147
148 return ret;
149}
150
151/**
104 * percpu_ref_put - decrement a percpu refcount 152 * percpu_ref_put - decrement a percpu refcount
105 * @ref: percpu_ref to put 153 * @ref: percpu_ref to put
106 * 154 *