From: Peter Zijlstra <peterz@infradead.org>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>,
Ingo Molnar <mingo@redhat.com>,
Felipe Balbi <felipe.balbi@linux.intel.com>,
USB list <linux-usb@vger.kernel.org>,
Kernel development list <linux-kernel@vger.kernel.org>
Subject: Re: Memory barrier needed with wake_up_process()?
Date: Fri, 2 Sep 2016 21:18:57 +0200 [thread overview]
Message-ID: <20160902191857.GL10153@twins.programming.kicks-ass.net> (raw)
In-Reply-To: <Pine.LNX.4.44L0.1609021341220.2027-100000@iolanthe.rowland.org>
On Fri, Sep 02, 2016 at 02:10:13PM -0400, Alan Stern wrote:
> Paul, Peter, and Ingo:
>
> This must have come up before, but I don't know what was decided.
>
> Isn't it often true that a memory barrier is needed before a call to
> wake_up_process()? A typical scenario might look like this:
>
> CPU 0
> -----
> for (;;) {
> set_current_state(TASK_INTERRUPTIBLE);
> if (signal_pending(current))
> break;
> if (wakeup_flag)
> break;
> schedule();
> }
> __set_current_state(TASK_RUNNING);
> wakeup_flag = 0;
>
>
> CPU 1
> -----
> wakeup_flag = 1;
> wake_up_process(my_task);
>
> The underlying pattern is:
>
> CPU 0 CPU 1
> ----- -----
> write current->state write wakeup_flag
> smp_mb();
> read wakeup_flag read my_task->state
>
> where set_current_state() does the write to current->state and
> automatically adds the smp_mb(), and wake_up_process() reads
> my_task->state to see whether the task needs to be woken up.
>
> The kerneldoc for wake_up_process() says that it has no implied memory
> barrier if it doesn't actually wake anything up. And even when it
> does, the implied barrier is only smp_wmb, not smp_mb.
>
> This is the so-called SB (Store Buffer) pattern, which is well known to
> require a full smp_mb on both sides. Since wake_up_process() doesn't
> include smp_mb(), isn't it correct that the caller must add it
> explicitly?
>
> In other words, shouldn't the code for CPU 1 really be:
>
> wakeup_flag = 1;
> smp_mb();
> wake_up_process(task);
>
No, it doesn't need to do that. try_to_wake_up() does the right thing.
It does:
smp_mb__before_spinlock();
raw_spin_lock_irqsave(&p->pi_lock);
Now, smp_mb__before_spinlock() is a bit of an odd duck, if you look at
its comment it says:
/*
* Despite its name it doesn't necessarily has to be a full barrier.
* It should only guarantee that a STORE before the critical section
* can not be reordered with LOADs and STOREs inside this section.
* spin_lock() is the one-way barrier, this LOAD can not escape out
* of the region. So the default implementation simply ensures that
* a STORE can not move into the critical section, smp_wmb() should
* serialize it with another STORE done by spin_lock().
*/
#ifndef smp_mb__before_spinlock
#define smp_mb__before_spinlock() smp_wmb()
#endif
So per default it ends up being:
WMB
LOCK
Which is sufficient to order the prior store vs the later load as is
required. Note that a spinlock acquire _must_ imply a store (we need to
mark the lock as taken), therefore the prior store is ordered against
the lock store per the wmb, and since the lock must imply an ACQUIRE
that limits the load.
Now, PowerPC defines smp_mb__before_spinlock as smp_mb(), and this is
because PowerPC ACQUIRE is a bit of an exception, if you want more
details I'm sure I or Paul can dredge them up :-)
next prev parent reply other threads:[~2016-09-02 19:20 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-02 18:10 Memory barrier needed with wake_up_process()? Alan Stern
2016-09-02 18:47 ` Paul E. McKenney
2016-09-02 20:29 ` Alan Stern
2016-09-03 9:07 ` Paul E. McKenney
2016-09-03 12:31 ` Peter Zijlstra
2016-09-03 14:26 ` Alan Stern
2016-09-03 14:49 ` Alan Stern
2016-09-05 8:33 ` Peter Zijlstra
2016-09-05 15:29 ` Alan Stern
2016-09-06 11:36 ` Peter Zijlstra
2016-09-06 11:43 ` Felipe Balbi
2016-09-06 11:49 ` Peter Zijlstra
2016-09-06 12:20 ` Peter Zijlstra
2016-09-06 14:46 ` Alan Stern
2016-09-06 15:05 ` Peter Zijlstra
2016-09-07 10:12 ` Felipe Balbi
2016-09-09 10:36 ` Felipe Balbi
2016-09-09 16:12 ` Alan Stern
2016-09-19 11:11 ` Felipe Balbi
2016-09-19 17:35 ` Alan Stern
2016-09-20 10:12 ` Felipe Balbi
2016-09-20 12:53 ` Felipe Balbi
2016-09-20 14:40 ` Alan Stern
2017-01-16 11:12 ` Felipe Balbi
2017-01-16 17:09 ` Alan Stern
2017-01-16 19:04 ` Felipe Balbi
2017-01-16 19:19 ` Felipe Balbi
2016-09-02 19:18 ` Peter Zijlstra [this message]
2016-09-02 20:16 ` Alan Stern
2016-09-02 22:14 ` Peter Zijlstra
2016-09-02 22:16 ` Peter Zijlstra
2016-09-05 9:43 ` Will Deacon
2016-09-06 11:10 ` Peter Zijlstra
2016-09-02 22:16 ` Peter Zijlstra
2016-09-03 6:58 ` Felipe Balbi
2016-09-03 12:19 ` Peter Zijlstra
2016-09-03 13:51 ` Felipe Balbi
2016-09-05 8:09 ` Peter Zijlstra
2016-09-03 14:16 ` Alan Stern
2016-09-05 8:08 ` Peter Zijlstra
2016-09-05 14:33 ` Alan Stern
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=20160902191857.GL10153@twins.programming.kicks-ass.net \
--to=peterz@infradead.org \
--cc=felipe.balbi@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=paulmck@linux.vnet.ibm.com \
--cc=stern@rowland.harvard.edu \
/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.