diff options
Diffstat (limited to 'lib/percpu-refcount.c')
-rw-r--r-- | lib/percpu-refcount.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/lib/percpu-refcount.c b/lib/percpu-refcount.c index ebeaac274cb9..8bf9e719cca0 100644 --- a/lib/percpu-refcount.c +++ b/lib/percpu-refcount.c | |||
@@ -118,6 +118,10 @@ static void percpu_ref_kill_rcu(struct rcu_head *rcu) | |||
118 | 118 | ||
119 | atomic_add((int) count - PCPU_COUNT_BIAS, &ref->count); | 119 | atomic_add((int) count - PCPU_COUNT_BIAS, &ref->count); |
120 | 120 | ||
121 | /* @ref is viewed as dead on all CPUs, send out kill confirmation */ | ||
122 | if (ref->confirm_kill) | ||
123 | ref->confirm_kill(ref); | ||
124 | |||
121 | /* | 125 | /* |
122 | * Now we're in single atomic_t mode with a consistent refcount, so it's | 126 | * Now we're in single atomic_t mode with a consistent refcount, so it's |
123 | * safe to drop our initial ref: | 127 | * safe to drop our initial ref: |
@@ -126,22 +130,29 @@ static void percpu_ref_kill_rcu(struct rcu_head *rcu) | |||
126 | } | 130 | } |
127 | 131 | ||
128 | /** | 132 | /** |
129 | * percpu_ref_kill - safely drop initial ref | 133 | * percpu_ref_kill_and_confirm - drop the initial ref and schedule confirmation |
130 | * @ref: percpu_ref to kill | 134 | * @ref: percpu_ref to kill |
135 | * @confirm_kill: optional confirmation callback | ||
131 | * | 136 | * |
132 | * Must be used to drop the initial ref on a percpu refcount; must be called | 137 | * Equivalent to percpu_ref_kill() but also schedules kill confirmation if |
133 | * precisely once before shutdown. | 138 | * @confirm_kill is not NULL. @confirm_kill, which may not block, will be |
139 | * called after @ref is seen as dead from all CPUs - all further | ||
140 | * invocations of percpu_ref_tryget() will fail. See percpu_ref_tryget() | ||
141 | * for more details. | ||
134 | * | 142 | * |
135 | * Puts @ref in non percpu mode, then does a call_rcu() before gathering up the | 143 | * Due to the way percpu_ref is implemented, @confirm_kill will be called |
136 | * percpu counters and dropping the initial ref. | 144 | * after at least one full RCU grace period has passed but this is an |
145 | * implementation detail and callers must not depend on it. | ||
137 | */ | 146 | */ |
138 | void percpu_ref_kill(struct percpu_ref *ref) | 147 | void percpu_ref_kill_and_confirm(struct percpu_ref *ref, |
148 | percpu_ref_func_t *confirm_kill) | ||
139 | { | 149 | { |
140 | WARN_ONCE(REF_STATUS(ref->pcpu_count) == PCPU_REF_DEAD, | 150 | WARN_ONCE(REF_STATUS(ref->pcpu_count) == PCPU_REF_DEAD, |
141 | "percpu_ref_kill() called more than once!\n"); | 151 | "percpu_ref_kill() called more than once!\n"); |
142 | 152 | ||
143 | ref->pcpu_count = (unsigned __percpu *) | 153 | ref->pcpu_count = (unsigned __percpu *) |
144 | (((unsigned long) ref->pcpu_count)|PCPU_REF_DEAD); | 154 | (((unsigned long) ref->pcpu_count)|PCPU_REF_DEAD); |
155 | ref->confirm_kill = confirm_kill; | ||
145 | 156 | ||
146 | call_rcu(&ref->rcu, percpu_ref_kill_rcu); | 157 | call_rcu(&ref->rcu, percpu_ref_kill_rcu); |
147 | } | 158 | } |