All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
To: Steven Rostedt <rostedt@goodmis.org>
Cc: Peter Zijlstra <peterz@infradead.org>,
	linux-kernel@vger.kernel.org,
	"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>,
	Oleg Nesterov <oleg@redhat.com>, Ingo Molnar <mingo@elte.hu>,
	akpm@linux-foundation.org, josh@joshtriplett.org,
	tglx@linutronix.de, Valdis.Kletnieks@vt.edu, dhowells@redhat.com,
	laijs@cn.fujitsu.com, dipankar@in.ibm.com
Subject: Re: [RFC PATCH] introduce sys_membarrier(): process-wide memory barrier (v5)
Date: Thu, 14 Jan 2010 14:33:55 -0500	[thread overview]
Message-ID: <20100114193355.GA23436@Krystal> (raw)
In-Reply-To: <1263495132.28171.3861.camel@gandalf.stny.rr.com>

* Steven Rostedt (rostedt@goodmis.org) wrote:
> On Thu, 2010-01-14 at 13:37 -0500, Mathieu Desnoyers wrote:
> 
> > To make this painfully clear, I'll reorder the accesses to match that of
> > the CPU to memory:
> > 
> >        CPU 0 (membarrier)                  CPU 1 (another mm -our mm)
> >        <user-space>
> >                                            <kernel-space>
> >                                            switch_mm()
> >                                              smp_mb()
> >                                              clear_mm_cpumask()
> >                                              set_mm_cpumask()
> >                                              smp_mb() (by load_cr3() on x86)
> >                                            switch_to()
> >                                              <buffered current = next>
> >                                            <switch back to user-space>
> >                                            urcu read lock()
> >                                              access critical section data (3)
> >        memory access before membarrier
> >        <call sys_membarrier()>
> >        smp_mb()
> >        mm_cpumask includes CPU 1
> >        rcu_read_lock()
> >        if (CPU 1 mm != our mm)
> >          skip CPU 1.
> 
> I still don't see how the above conditional fails?

First, I just want to fix one detail I had wrong. It does not change the
end result, but it changes the order of the scenario:

  A cpu "current" task struct is not the same thing as that same CPU
rq->curr. So we are talking about the rq->curr update here, not the cpu
"current" task (as I mistakenly assumed previously).

   if (CPU 1 mm != our mm) translates into:

   if (cpu_curr(1)->mm != current->mm)

where cpu_curr(cpu) is:

#define cpu_rq(cpu)             (&per_cpu(runqueues, (cpu)))
#define cpu_curr(cpu)           (cpu_rq(cpu)->curr)

struct rq "curr" field is a struct task_struct *, updated by
schedule() before calling context_switch().

So the requirement is that we need a smp_mb() before and after rq->curr
update in schedule(). The smp_mb() after the update is ensured by
context_switch() -> switch_mm() -> load_cr3(). However, updating my
scenario to match the fact that we are really talking about rq->curr
update here (which happens _before_ switch_mm() and not after), we can
see that the problematic case happens if there is no smp_mb() before
rq->curr update:

It's a case where CPU 1 switches from our mm to another mm:

       CPU 0 (membarrier)                  CPU 1 (another mm -our mm)
       <user-space>                        <user-space>
                                           <buffered access C.S. data>
                                           urcu read unlock()
                                             barrier()
                                             store local gp
                                           <kernel-space>
                                           rq->curr = next (1)
       memory access before membarrier
       <call sys_membarrier()>
       smp_mb()
       mm_cpumask includes CPU 1
       rcu_read_lock()
       if (cpu_curr(1)->mm != our mm)
         skip CPU 1     -> here, rq->curr new version is already visible
       rcu_read_unlock()
       smp_mb()
       <return to user-space>
       memory access after membarrier
       -> this is where we allow freeing
          the old structure although the
          buffered access C.S. data is
          still in flight.
                                           User-space access C.S. data (2)
                                             (buffer flush)
                                           switch_mm()
                                             smp_mb()
                                             clear_mm_cpumask()
                                             set_mm_cpumask()
                                             smp_mb() (by load_cr3() on x86)
                                           switch_to()
                                             <buffered current = next>
                                           <switch back to user-space>
                                             current = next (1) (buffer flush)
                                           access critical section data (3)

As we can see, the reordering of (1) and (2) is problematic, as it lets
the check skip over a CPU that have global side-effects not committed to
memory yet.

Hopefully this explanation helps ?

Thanks,

Mathieu

> 
> -- Steve
> 
> >        rcu_read_unlock()
> >        smp_mb()
> >        <return to user-space>
> >        memory access after membarrier
> >                                              current = next (1) (buffer flush)
> >                                              read gp
> >                                              store local gp (2)
> > 
> > This should make the problem a bit more evident. Access (3) is done
> > outside of the read-side C.S. as far as the userspace synchronize_rcu()
> > is concerned.
> > 
> > Thanks,
> > 
> > Mathieu
> > 
> > 
> 
> 

-- 
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

  reply	other threads:[~2010-01-14 19:34 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-01-13  1:37 [RFC PATCH] introduce sys_membarrier(): process-wide memory barrier (v5) Mathieu Desnoyers
2010-01-13  3:23 ` KOSAKI Motohiro
2010-01-13  3:58   ` Mathieu Desnoyers
2010-01-13  4:47     ` KOSAKI Motohiro
2010-01-13  5:33       ` Paul E. McKenney
2010-01-13 15:03       ` Mathieu Desnoyers
2010-01-14  0:15         ` KOSAKI Motohiro
2010-01-14  2:16           ` Mathieu Desnoyers
2010-01-14  2:25             ` KOSAKI Motohiro
2010-01-13  5:00 ` Nicholas Miell
2010-01-13  5:31   ` Paul E. McKenney
2010-01-13  5:39     ` Nicholas Miell
2010-01-13 14:38       ` Mathieu Desnoyers
2010-01-13 18:07         ` Nicholas Miell
2010-01-13 18:24           ` Mathieu Desnoyers
2010-01-13 18:41             ` Nicholas Miell
2010-01-13 19:17               ` Mathieu Desnoyers
2010-01-13 19:42                 ` David Daney
2010-01-13 19:53                   ` Nicholas Miell
2010-01-13 23:42                     ` Mathieu Desnoyers
2010-01-13 15:58       ` Paul E. McKenney
2010-01-13 11:07 ` Heiko Carstens
2010-01-13 14:46   ` Mathieu Desnoyers
2010-01-13 16:38 ` Peter Zijlstra
2010-01-13 19:36   ` Mathieu Desnoyers
2010-01-14  9:08     ` Peter Zijlstra
2010-01-14 16:26       ` Mathieu Desnoyers
2010-01-14 17:03         ` Peter Zijlstra
2010-01-14 17:54           ` Mathieu Desnoyers
2010-01-14 18:37             ` Mathieu Desnoyers
2010-01-14 18:52               ` Steven Rostedt
2010-01-14 19:33                 ` Mathieu Desnoyers [this message]
2010-01-14 21:26                   ` Steven Rostedt
2010-01-19 18:37                   ` Peter Zijlstra
2010-01-19 19:06                     ` Peter Zijlstra
2010-01-20  3:13                       ` Mathieu Desnoyers
2010-01-20  8:45                         ` Peter Zijlstra
2010-01-21 11:26                       ` Peter Zijlstra
2010-01-21 16:07                         ` Mathieu Desnoyers
2010-01-21 16:12                           ` Steven Rostedt
2010-01-21 16:22                             ` Mathieu Desnoyers
2010-01-21 16:32                               ` Steven Rostedt
2010-01-21 17:02                                 ` Mathieu Desnoyers
2010-01-21 16:17                           ` Peter Zijlstra
2010-01-21 17:01                             ` Mathieu Desnoyers
2010-01-19 19:43                     ` Steven Rostedt
2010-01-14 18:50             ` Steven Rostedt
2010-01-19 16:47         ` Peter Zijlstra
2010-01-19 17:11           ` Mathieu Desnoyers
2010-01-19 17:30           ` Steven Rostedt

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=20100114193355.GA23436@Krystal \
    --to=mathieu.desnoyers@polymtl.ca \
    --cc=Valdis.Kletnieks@vt.edu \
    --cc=akpm@linux-foundation.org \
    --cc=dhowells@redhat.com \
    --cc=dipankar@in.ibm.com \
    --cc=josh@joshtriplett.org \
    --cc=laijs@cn.fujitsu.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=oleg@redhat.com \
    --cc=paulmck@linux.vnet.ibm.com \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --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.