On Mon, Apr 10, 2017 at 12:20:53PM -0400, Alan Stern wrote:
> On Mon, 10 Apr 2017, Paul E. McKenney wrote:
> 
> > > But I would like to get this matter settled first.  Is the explicit 
> > > barrier truly necessary?
> > 
> > If you are using wait_event()/wake_up() or friends, the explicit
> > barrier -is- necessary.  To see this, look at v4.10's wait_event():
> > 
> >     #define wait_event(wq, condition)                               \
> >     do {                                                            \
> >             might_sleep();                                          \
> >             if (condition)                                          \
> >                     break;                                          \
> >             __wait_event(wq, condition);                            \
> >     } while (0)
> > 
> > As you can see, if the condition is set just before the wait_event()
> > macro checks it, there is no ordering whatsoever.
> 
> This is true, but it is not relevant to the question I was asking.

Apologies!  What I get for answering email too early on Monday, I guess...

> >  And if wake_up()
> > finds nothing to wake up, there is no relevant ordering on that side,
> > either.
> > 
> > So you had better supply your own ordering, period, end of story.
> 
> The question is: Exactly what ordering do I need to supply?  The 
> ordering among my own variables is okay; I know how to deal with that.  
> But what about the ordering between my variables and current->state?

The ordering with current->state is sadly not relevant because it is
only touched if wake_up() actually wakes the process up.

> For example, __wait_event() calls prepare_to_wait(), which calls
> set_current_state(), which calls smp_store_mb(), thereby inserting a
> full memory barrier between setting current->state and checking the
> condition.  But I didn't see any comparable barrier inserted by
> wake_up(), between setting the condition and checking task->state.
> 
> However, now that I look more closely, I do see that wakeup_process() 
> calls try_to_wake_up(), which begins with:
> 
>       /*
>        * If we are going to wake up a thread waiting for CONDITION we
>        * need to ensure that CONDITION=1 done by the caller can not be
>        * reordered with p->state check below. This pairs with mb() in
>        * set_current_state() the waiting thread does.
>        */
>       smp_mb__before_spinlock();
>       raw_spin_lock_irqsave(&p->pi_lock, flags);
>       if (!(p->state & state))
> 
> So it does insert a full barrier after all, and there is nothing to 
> worry about.

Nice!

Hmmm...

Another valid (and I believe more common) idiom is this:

        spin_lock(&mylock);
        changes_that_must_be_visible_to_woken_thread();
        WRITE_ONCE(need_wake_up, true);
        spin_unlock(&mylock);

        ---

        wait_event(wq, READ_ONCE(need_wake_up));
        spin_lock(&mylock);
        access_variables_used_by_waking_thread();
        spin_unlock(&mylock);

In this case, the locks do all the required ordering.

> This also means that the analysis provided by Thinh Nguyen in the 
> original patch description is wrong.

And that the bug is elsewhere?

                                                        Thanx, Paul

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to