From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
To: Steven Rostedt <rostedt@goodmis.org>
Cc: linux-kernel@vger.kernel.org, mingo@elte.hu,
akpm@linux-foundation.org, oleg@tv-sign.ru,
manfred@colorfullife.com, dipankar@in.ibm.com, dvhltc@us.ibm.com,
niv@us.ibm.com
Subject: Re: [PATCH tip/core/rcu] classic RCU locking and memory-barrier cleanups
Date: Tue, 5 Aug 2008 10:40:58 -0700 [thread overview]
Message-ID: <20080805174058.GE6737@linux.vnet.ibm.com> (raw)
In-Reply-To: <alpine.DEB.1.10.0808051244550.27713@gandalf.stny.rr.com>
On Tue, Aug 05, 2008 at 12:48:41PM -0400, Steven Rostedt wrote:
Thank you for looking this over, Steve!
> On Tue, 5 Aug 2008, Paul E. McKenney wrote:
> > ---
> >
> > rcuclassic.c | 51 +++++++++++++++++++++++++++++++++++++++++----------
> > 1 file changed, 41 insertions(+), 10 deletions(-)
> >
> > diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c
> > index d3553ee..e6f42ef 100644
> > --- a/kernel/rcuclassic.c
> > +++ b/kernel/rcuclassic.c
> > @@ -86,6 +86,7 @@ static void force_quiescent_state(struct rcu_data *rdp,
> > int cpu;
> > cpumask_t cpumask;
> > set_need_resched();
> > + spin_lock(&rcp->lock);
> > if (unlikely(!rcp->signaled)) {
> > rcp->signaled = 1;
> > /*
> > @@ -111,6 +112,7 @@ static void force_quiescent_state(struct rcu_data *rdp,
> > for_each_cpu_mask(cpu, cpumask)
> > smp_send_reschedule(cpu);
> > }
> > + spin_unlock(&rcp->lock);
> > }
> > #else
> > static inline void force_quiescent_state(struct rcu_data *rdp,
> > @@ -124,7 +126,9 @@ static void __call_rcu(struct rcu_head *head, struct rcu_ctrlblk *rcp,
> > struct rcu_data *rdp)
> > {
> > long batch;
> > - smp_mb(); /* reads the most recently updated value of rcu->cur. */
> > +
> > + head->next = NULL;
> > + smp_mb(); /* Read of rcu->cur must happen after any change by caller. */
> >
> > /*
> > * Determine the batch number of this callback.
> > @@ -174,7 +178,6 @@ void call_rcu(struct rcu_head *head,
> > unsigned long flags;
> >
> > head->func = func;
> > - head->next = NULL;
> > local_irq_save(flags);
> > __call_rcu(head, &rcu_ctrlblk, &__get_cpu_var(rcu_data));
> > local_irq_restore(flags);
> > @@ -203,7 +206,6 @@ void call_rcu_bh(struct rcu_head *head,
> > unsigned long flags;
> >
> > head->func = func;
> > - head->next = NULL;
> > local_irq_save(flags);
> > __call_rcu(head, &rcu_bh_ctrlblk, &__get_cpu_var(rcu_bh_data));
> > local_irq_restore(flags);
> > @@ -389,17 +391,17 @@ static void rcu_move_batch(struct rcu_data *this_rdp, struct rcu_head *list,
> > static void __rcu_offline_cpu(struct rcu_data *this_rdp,
> > struct rcu_ctrlblk *rcp, struct rcu_data *rdp)
> > {
> > - /* if the cpu going offline owns the grace period
> > + /*
> > + * if the cpu going offline owns the grace period
> > * we can block indefinitely waiting for it, so flush
> > * it here
> > */
> > spin_lock_bh(&rcp->lock);
> > if (rcp->cur != rcp->completed)
> > cpu_quiet(rdp->cpu, rcp);
> > - spin_unlock_bh(&rcp->lock);
> > - /* spin_lock implies smp_mb() */
>
> The spin_unlock is being removed here. Was that the smp_mb that was
> implied or is it the above spin_lock_bh?
Moving the spinlock down below, combined with adding spinlocks elsewhere,
eliminates the need for the memory barrier -- the locking primitives
provide full ordering and atomicity as well. This does likely reduce
scalability somewhat, which I will address with a hierarchical approach
in a later patch.
Thanx, Paul
> > rcu_move_batch(this_rdp, rdp->donelist, rdp->donetail, rcp->cur + 1);
> > rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail[2], rcp->cur + 1);
> > + spin_unlock_bh(&rcp->lock);
> >
> > local_irq_disable();
> > this_rdp->qlen += rdp->qlen;
> > @@ -433,16 +435,19 @@ static void rcu_offline_cpu(int cpu)
> > static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp,
> > struct rcu_data *rdp)
> > {
> > + long completed_snap;
> > +
> > if (rdp->nxtlist) {
> > local_irq_disable();
> > + completed_snap = ACCESS_ONCE(rcp->completed);
> >
> > /*
> > * move the other grace-period-completed entries to
> > * [rdp->nxtlist, *rdp->nxttail[0]) temporarily
> > */
> > - if (!rcu_batch_before(rcp->completed, rdp->batch))
> > + if (!rcu_batch_before(completed_snap, rdp->batch))
> > rdp->nxttail[0] = rdp->nxttail[1] = rdp->nxttail[2];
> > - else if (!rcu_batch_before(rcp->completed, rdp->batch - 1))
> > + else if (!rcu_batch_before(completed_snap, rdp->batch - 1))
> > rdp->nxttail[0] = rdp->nxttail[1];
> >
> > /*
> > @@ -483,20 +488,38 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp,
> >
> > static void rcu_process_callbacks(struct softirq_action *unused)
> > {
> > + /*
> > + * Memory references from any prior RCU read-side critical sections
> > + * executed by the interrupted code must be see before any RCU
> > + * grace-period manupulations below.
> > + */
> > +
> > + smp_mb(); /* See above block comment. */
> > +
> > __rcu_process_callbacks(&rcu_ctrlblk, &__get_cpu_var(rcu_data));
> > __rcu_process_callbacks(&rcu_bh_ctrlblk, &__get_cpu_var(rcu_bh_data));
> > +
> > + /*
> > + * Memory references from any later RCU read-side critical sections
> > + * executed by the interrupted code must be see after any RCU
> > + * grace-period manupulations above.
> > + */
> > +
> > + smp_mb(); /* See above block comment. */
> > }
> >
> > static int __rcu_pending(struct rcu_ctrlblk *rcp, struct rcu_data *rdp)
> > {
> > if (rdp->nxtlist) {
> > + long completed_snap = ACCESS_ONCE(rcp->completed);
> > +
> > /*
> > * This cpu has pending rcu entries and the grace period
> > * for them has completed.
> > */
> > - if (!rcu_batch_before(rcp->completed, rdp->batch))
> > + if (!rcu_batch_before(completed_snap, rdp->batch))
> > return 1;
> > - if (!rcu_batch_before(rcp->completed, rdp->batch - 1) &&
> > + if (!rcu_batch_before(completed_snap, rdp->batch - 1) &&
> > rdp->nxttail[0] != rdp->nxttail[1])
> > return 1;
> > if (rdp->nxttail[0] != &rdp->nxtlist)
> > @@ -547,6 +570,12 @@ int rcu_needs_cpu(int cpu)
> > return !!rdp->nxtlist || !!rdp_bh->nxtlist || rcu_pending(cpu);
> > }
> >
> > +/*
> > + * Top-level function driving RCU grace-period detection, normally
> > + * invoked from the scheduler-clock interrupt. This function simply
> > + * increments counters that are read only from softirq by this same
> > + * CPU, so there are no memory barriers required.
> > + */
> > void rcu_check_callbacks(int cpu, int user)
> > {
> > if (user ||
> > @@ -590,6 +619,7 @@ void rcu_check_callbacks(int cpu, int user)
> > static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp,
> > struct rcu_data *rdp)
> > {
> > + spin_lock(&rcp->lock);
> > memset(rdp, 0, sizeof(*rdp));
> > rdp->nxttail[0] = rdp->nxttail[1] = rdp->nxttail[2] = &rdp->nxtlist;
> > rdp->donetail = &rdp->donelist;
> > @@ -597,6 +627,7 @@ static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp,
> > rdp->qs_pending = 0;
> > rdp->cpu = cpu;
> > rdp->blimit = blimit;
> > + spin_unlock(&rcp->lock);
> > }
> >
> > static void __cpuinit rcu_online_cpu(int cpu)
> >
next prev parent reply other threads:[~2008-08-05 17:41 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-05 16:21 [PATCH tip/core/rcu] classic RCU locking and memory-barrier cleanups Paul E. McKenney
2008-08-05 16:48 ` Steven Rostedt
2008-08-05 17:40 ` Paul E. McKenney [this message]
2008-08-06 5:30 ` Manfred Spraul
2008-08-07 3:18 ` Paul E. McKenney
2008-08-18 9:13 ` Manfred Spraul
2008-08-18 14:04 ` Paul E. McKenney
2008-08-19 10:48 ` Manfred Spraul
2008-08-19 14:03 ` Paul E. McKenney
2008-08-19 17:16 ` nohz_cpu_mask question (was: Re: [PATCH tip/core/rcu] classic RCU locking and memory-barrier cleanups) Manfred Spraul
2008-08-19 17:41 ` Paul E. McKenney
2008-08-15 14:09 ` [PATCH tip/core/rcu] classic RCU locking and memory-barrier cleanups Ingo Molnar
2008-08-15 14:24 ` Ingo Molnar
2008-08-15 14:56 ` Ingo Molnar
2008-08-15 14:58 ` Paul E. McKenney
2008-08-17 14:37 ` [PATCH tip/core/rcu] classic RCU locking cleanup fix lockdep problem Paul E. McKenney
2008-08-17 15:38 ` Ingo Molnar
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=20080805174058.GE6737@linux.vnet.ibm.com \
--to=paulmck@linux.vnet.ibm.com \
--cc=akpm@linux-foundation.org \
--cc=dipankar@in.ibm.com \
--cc=dvhltc@us.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=manfred@colorfullife.com \
--cc=mingo@elte.hu \
--cc=niv@us.ibm.com \
--cc=oleg@tv-sign.ru \
--cc=rostedt@goodmis.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.