diff options
Diffstat (limited to 'include/linux/percpu-refcount.h')
-rw-r--r-- | include/linux/percpu-refcount.h | 50 |
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 | ||
69 | int __must_check percpu_ref_init(struct percpu_ref *ref, | 70 | int __must_check percpu_ref_init(struct percpu_ref *ref, |
70 | percpu_ref_func_t *release); | 71 | percpu_ref_func_t *release); |
71 | void percpu_ref_cancel_init(struct percpu_ref *ref); | 72 | void percpu_ref_cancel_init(struct percpu_ref *ref); |
72 | void percpu_ref_kill(struct percpu_ref *ref); | 73 | void 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 | */ | ||
86 | static 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 | */ | ||
132 | static 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 | * |