From: Lai Jiangshan <laijs@cn.fujitsu.com>
To: Tejun Heo <tj@kernel.org>
Cc: <cl@linux-foundation.org>, <kmo@daterainc.com>,
<linux-kernel@vger.kernel.org>,
"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Subject: Re: [PATCH v2 6/6] percpu-refcount: implement percpu_ref_reinit() and percpu_ref_is_zero()
Date: Thu, 19 Jun 2014 11:01:26 +0800 [thread overview]
Message-ID: <53A25286.1030003@cn.fujitsu.com> (raw)
In-Reply-To: <20140619022055.GD20100@mtj.dyndns.org>
On 06/19/2014 10:20 AM, Tejun Heo wrote:
> Now that explicit invocation of percpu_ref_exit() is necessary to free
> the percpu counter, we can implement percpu_ref_reinit() which
> reinitializes a released percpu_ref. This can be used implement
> scalable gating switch which can be drained and then re-opened without
> worrying about memory allocation failures.
>
> percpu_ref_is_zero() is added to be used in a sanity check in
> percpu_ref_exit(). As this function will be useful for other purposes
> too, make it a public interface.
>
> v2: Use smp_read_barrier_depends() instead of smp_load_acquire(). We
> only need data dep barrier and smp_load_acquire() is stronger and
> heavier on some archs. Spotted by Lai Jiangshan.
>
> Signed-off-by: Tejun Heo <tj@kernel.org>
> Cc: Kent Overstreet <kmo@daterainc.com>
> Cc: Christoph Lameter <cl@linux-foundation.org>
> Cc: Lai Jiangshan <laijs@cn.fujitsu.com>
> ---
> include/linux/percpu-refcount.h | 19 +++++++++++++++++++
> lib/percpu-refcount.c | 35 +++++++++++++++++++++++++++++++++++
> 2 files changed, 54 insertions(+)
>
> --- a/include/linux/percpu-refcount.h
> +++ b/include/linux/percpu-refcount.h
> @@ -67,6 +67,7 @@ struct percpu_ref {
>
> int __must_check percpu_ref_init(struct percpu_ref *ref,
> percpu_ref_func_t *release);
> +void percpu_ref_reinit(struct percpu_ref *ref);
> void percpu_ref_exit(struct percpu_ref *ref);
> void percpu_ref_kill_and_confirm(struct percpu_ref *ref,
> percpu_ref_func_t *confirm_kill);
> @@ -99,6 +100,9 @@ static inline bool __pcpu_ref_alive(stru
> {
> unsigned long pcpu_ptr = ACCESS_ONCE(ref->pcpu_count_ptr);
>
> + /* paired with smp_store_release() in percpu_ref_reinit() */
> + smp_read_barrier_depends();
> +
> if (unlikely(pcpu_ptr & PCPU_REF_DEAD))
> return false;
>
> @@ -206,4 +210,19 @@ static inline void percpu_ref_put(struct
> rcu_read_unlock_sched();
> }
>
> +/**
> + * percpu_ref_is_zero - test whether a percpu refcount reached zero
> + * @ref: percpu_ref to test
> + *
> + * Returns %true if @ref reached zero.
> + */
> +static inline bool percpu_ref_is_zero(struct percpu_ref *ref)
> +{
> + unsigned __percpu *pcpu_count;
> +
> + if (__pcpu_ref_alive(ref, &pcpu_count))
> + return false;
> + return !atomic_read(&ref->count);
> +}
> +
> #endif
> --- a/lib/percpu-refcount.c
> +++ b/lib/percpu-refcount.c
> @@ -61,6 +61,41 @@ int percpu_ref_init(struct percpu_ref *r
> EXPORT_SYMBOL_GPL(percpu_ref_init);
>
> /**
> + * percpu_ref_reinit - re-initialize a percpu refcount
> + * @ref: perpcu_ref to re-initialize
> + *
> + * Re-initialize @ref so that it's in the same state as when it finished
> + * percpu_ref_init(). @ref must have been initialized successfully, killed
> + * and reached 0 but not exited.
> + *
> + * Note that percpu_ref_tryget[_live]() are safe to perform on @ref while
> + * this function is in progress.
> + */
> +void percpu_ref_reinit(struct percpu_ref *ref)
> +{
> + unsigned __percpu *pcpu_count = pcpu_count_ptr(ref);
> + int cpu;
> +
> + BUG_ON(!pcpu_count);
> + WARN_ON(!percpu_ref_is_zero(ref));
> +
> + atomic_set(&ref->count, 1 + PCPU_COUNT_BIAS);
> +
> + /*
> + * Restore per-cpu operation. smp_store_release() is paired with
> + * smp_load_acquire() in __pcpu_ref_alive() and guarantees that the
s/smp_load_acquire()/smp_read_barrier_depends()/
s/smp_store_release()/smp_mb()/ if you accept my next comment.
> + * zeroing is visible to all percpu accesses which can see the
> + * following PCPU_REF_DEAD clearing.
> + */
> + for_each_possible_cpu(cpu)
> + *per_cpu_ptr(pcpu_count, cpu) = 0;
> +
> + smp_store_release(&ref->pcpu_count_ptr,
> + ref->pcpu_count_ptr & ~PCPU_REF_DEAD);
I think it would be better if smp_mb() is used.
it is documented that smp_read_barrier_depends() and smp_mb() are paired.
Not smp_read_barrier_depends() and smp_store_release().
> +}
> +EXPORT_SYMBOL_GPL(percpu_ref_reinit);
> +
> +/**
> * percpu_ref_exit - undo percpu_ref_init()
> * @ref: percpu_ref to exit
> *
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
> .
>
next prev parent reply other threads:[~2014-06-19 3:00 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-18 1:07 [PATCHSET percpu/for-3.17] percpu: implement percpu_ref_reinit() Tejun Heo
2014-06-18 1:08 ` [PATCH 1/6] percpu-refcount, aio: use percpu_ref_cancel_init() in ioctx_alloc() Tejun Heo
2014-06-25 14:31 ` Benjamin LaHaise
2014-06-25 14:56 ` Tejun Heo
2014-06-25 15:35 ` Benjamin LaHaise
2014-06-25 15:37 ` Tejun Heo
2014-06-18 1:08 ` [PATCH 2/6] percpu-refcount: one bit is enough for REF_STATUS Tejun Heo
2014-06-18 2:37 ` Lai Jiangshan
2014-06-18 1:08 ` [PATCH 3/6] percpu-refcount: add helpers for ->percpu_count accesses Tejun Heo
2014-06-18 1:08 ` [PATCH 4/6] percpu-refcount: use unsigned long for pcpu_count pointer Tejun Heo
2014-06-18 1:08 ` [PATCH 5/6] percpu-refcount: require percpu_ref to be exited explicitly Tejun Heo
2014-06-18 1:08 ` [PATCH 6/6] percpu-refcount: implement percpu_ref_reinit() and percpu_ref_is_zero() Tejun Heo
2014-06-18 3:37 ` Lai Jiangshan
2014-06-18 15:32 ` Tejun Heo
2014-06-19 1:58 ` Lai Jiangshan
2014-06-19 2:07 ` Tejun Heo
2014-06-19 2:27 ` Paul E. McKenney
2014-06-19 13:36 ` Tejun Heo
2014-06-19 17:05 ` Paul E. McKenney
2014-06-19 19:06 ` Tejun Heo
2014-06-19 21:07 ` Paul E. McKenney
2014-06-19 2:20 ` [PATCH v2 " Tejun Heo
2014-06-19 3:01 ` Lai Jiangshan [this message]
2014-06-19 13:31 ` Tejun Heo
2014-06-19 16:55 ` Paul E. McKenney
2014-06-19 17:03 ` Paul E. McKenney
2014-06-19 19:06 ` Tejun Heo
2014-06-28 12:10 ` [PATCHSET percpu/for-3.17] percpu: implement percpu_ref_reinit() Tejun Heo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=53A25286.1030003@cn.fujitsu.com \
--to=laijs@cn.fujitsu.com \
--cc=cl@linux-foundation.org \
--cc=kmo@daterainc.com \
--cc=linux-kernel@vger.kernel.org \
--cc=paulmck@linux.vnet.ibm.com \
--cc=tj@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.