From: Frederic Weisbecker <fweisbec@gmail.com>
To: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Cc: linux-kernel@vger.kernel.org, mingo@elte.hu,
laijs@cn.fujitsu.com, dipankar@in.ibm.com,
akpm@linux-foundation.org, mathieu.desnoyers@polymtl.ca,
josh@joshtriplett.org, niv@us.ibm.com, tglx@linutronix.de,
peterz@infradead.org, rostedt@goodmis.org, dhowells@redhat.com,
edumazet@google.com, darren@dvhart.com, sbw@mit.edu
Subject: Re: [PATCH RFC nohz_full 6/7] nohz_full: Add full-system-idle state machine
Date: Fri, 19 Jul 2013 04:12:08 +0200 [thread overview]
Message-ID: <20130719021207.GA19491@somewhere> (raw)
In-Reply-To: <20130719002408.GB21367@linux.vnet.ibm.com>
On Thu, Jul 18, 2013 at 05:24:08PM -0700, Paul E. McKenney wrote:
> On Fri, Jul 19, 2013 at 12:46:21AM +0200, Frederic Weisbecker wrote:
> > On Thu, Jul 18, 2013 at 09:47:49AM -0700, Paul E. McKenney wrote:
> > > 1. Some CPU coming out of idle:
> > >
> > > o rcu_sysidle_exit():
> > >
> > > smp_mb__before_atomic_inc();
> > > atomic_inc(&rdtp->dynticks_idle);
> > > smp_mb__after_atomic_inc(); /* A */
> > >
> > > o rcu_sysidle_force_exit():
> > >
> > > oldstate = ACCESS_ONCE(full_sysidle_state);
> > >
> > > 2. RCU GP kthread:
> > >
> > > o rcu_sysidle():
> > >
> > > cmpxchg(&full_sysidle_state, RCU_SYSIDLE_SHORT, RCU_SYSIDLE_LONG);
> > > /* B */
> > >
> > > o rcu_sysidle_check_cpu():
> > >
> > > cur = atomic_read(&rdtp->dynticks_idle);
> > >
> > > Memory barrier A pairs with memory barrier B, so that if #1's load
> > > from full_sysidle_state sees RCU_SYSIDLE_SHORT, we know that #1's
> > > atomic_inc() must be visible to #2's atomic_read(). This will cause #2
> > > to recognize that the CPU came out of idle, which will in turn cause it
> > > to invoke rcu_sysidle_cancel() instead of rcu_sysidle(), resulting in
> > > full_sysidle_state being set to RCU_SYSIDLE_NOT.
> >
> > Ok I get it for that direction.
> > Now imagine CPU 0 is the RCU GP kthread (#2) and CPU 1 is idle and stays
> > so.
> >
> > CPU 0 then rounds and see that all CPUs are idle, until it finally sets
> > up RCU_SYSIDLE_SHORT_FULL and finally goes to sleep.
> >
> > Then CPU 1 wakes up. It really has to see a value above RCU_SYSIDLE_SHORT
> > otherwise it won't do the cmpxchg and see the FULL_NOTED that makes it send
> > the IPI.
> >
> > What provides the guarantee that CPU 1 sees a value above RCU_SYSIDLE_SHORT?
> > Not on the cmpxchg but when it first dereference with ACCESS_ONCE.
>
> The trick is that CPU 0 will have scanned, moved to RCU_SYSIDLE_SHORT,
> scanned, moved to RCU_SYSIDLE_LONG, then scanned again before moving
> to RCU_SYSIDLE_FULL. Given CPU 1 has been idle all this time, CPU 0
> will have read its ->dynticks_idle counter on each scan and seen it
> having an even value. When CPU 1 comes out of idle, it will atomically
> increment its ->dyntick_idle(), which will happen after CPU 0's read of
> ->dyntick_idle() during its last scan.
>
> Because of the memory-barrier pairing above, this means that CPU
> 1's read from full_sysidle_state must follow the cmpxchg() that
> set full_sysidle_state to RCU_SYSIDLE_LONG (though not necessarily
> the two later cmpxchg()s that set it to RCU_SYSIDLE_FULL and
> RCU_SYSIDLE_FULL_NOTED). But because RCU_SYSIDLE_LONG is greater than
> RCU_SYSIDLE_SHORT, CPU 1 will take action to end the idle period.
Lets summarize the last sequence, the following happens ordered by time:
CPU 0 CPU 1
cmpxchg(&full_sysidle_state,
RCU_SYSIDLE_SHORT,
RCU_SYSIDLE_LONG);
smp_mb() //cmpxchg
atomic_read(rdtp(1)->dynticks_idle)
//CPU 0 goes to sleep
//CPU 1 wakes up
atomic_inc(rdtp(1)->dynticks_idle)
smp_mb()
ACCESS_ONCE(full_sysidle_state)
Are you suggesting that because the CPU 1 executes its atomic_inc() _after_ (in terms
of absolute time) the atomic_read of CPU 0, the ordering settled in both sides guarantees
that the value read from CPU 1 is the one from the cmpxchg that precedes the atomic_read,
or FULL or FULL_NOTED that happen later.
If so that's a big lesson for me.
next prev parent reply other threads:[~2013-07-19 2:12 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-09 1:29 [PATCH RFC nohz_full 0/7] v3 Provide infrastructure for full-system idle Paul E. McKenney
2013-07-09 1:30 ` [PATCH RFC nohz_full 1/7] nohz_full: Add Kconfig parameter for scalable detection of all-idle state Paul E. McKenney
2013-07-09 1:30 ` [PATCH RFC nohz_full 2/7] nohz_full: Add rcu_dyntick data " Paul E. McKenney
2013-07-09 9:37 ` Peter Zijlstra
2013-07-09 13:23 ` Paul E. McKenney
2013-07-09 1:30 ` [PATCH RFC nohz_full 3/7] nohz_full: Add per-CPU idle-state tracking Paul E. McKenney
2013-07-09 1:30 ` [PATCH RFC nohz_full 4/7] nohz_full: Add full-system idle states and variables Paul E. McKenney
2013-07-09 1:30 ` [PATCH RFC nohz_full 5/7] nohz_full: Add full-system-idle arguments to API Paul E. McKenney
2013-07-09 1:30 ` [PATCH RFC nohz_full 6/7] nohz_full: Add full-system-idle state machine Paul E. McKenney
2013-07-17 23:31 ` Frederic Weisbecker
2013-07-18 0:41 ` Paul E. McKenney
2013-07-18 1:33 ` Frederic Weisbecker
2013-07-18 3:39 ` Paul E. McKenney
2013-07-18 14:24 ` Frederic Weisbecker
2013-07-18 16:47 ` Paul E. McKenney
2013-07-18 22:46 ` Frederic Weisbecker
2013-07-19 0:24 ` Paul E. McKenney
2013-07-19 2:12 ` Frederic Weisbecker [this message]
2013-07-19 5:06 ` Paul E. McKenney
2013-07-24 18:09 ` Frederic Weisbecker
2013-07-24 22:09 ` Paul E. McKenney
2013-07-24 23:26 ` Frederic Weisbecker
2013-07-26 22:52 ` Paul E. McKenney
2013-07-27 18:13 ` Frederic Weisbecker
2013-07-09 1:30 ` [PATCH RFC nohz_full 7/7] nohz_full: Force RCU's grace-period kthreads onto timekeeping CPU Paul E. McKenney
-- strict thread matches above, loose matches on Subject: below --
2013-07-26 23:18 [PATCH RFC nohz_full 0/7] v4 Provide infrastructure for full-system idle Paul E. McKenney
2013-07-26 23:19 ` [PATCH RFC nohz_full 1/7] nohz_full: Add Kconfig parameter for scalable detection of all-idle state Paul E. McKenney
2013-07-26 23:19 ` [PATCH RFC nohz_full 6/7] nohz_full: Add full-system-idle state machine Paul E. McKenney
2013-07-29 8:19 ` Lai Jiangshan
2013-07-29 17:43 ` Paul E. McKenney
2013-08-09 16:20 ` Frederic Weisbecker
2013-08-14 3:07 ` Paul E. McKenney
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=20130719021207.GA19491@somewhere \
--to=fweisbec@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=darren@dvhart.com \
--cc=dhowells@redhat.com \
--cc=dipankar@in.ibm.com \
--cc=edumazet@google.com \
--cc=josh@joshtriplett.org \
--cc=laijs@cn.fujitsu.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@polymtl.ca \
--cc=mingo@elte.hu \
--cc=niv@us.ibm.com \
--cc=paulmck@linux.vnet.ibm.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=sbw@mit.edu \
--cc=tglx@linutronix.de \
/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.