On Fri, May 20, 2016 at 05:48:39PM -0700, Davidlohr Bueso wrote:Then !spin_is_locked() and spin_unlock_wait() would be different with regards to memory barriers.
As opposed to spin_is_locked(), spin_unlock_wait() is perhaps more temptingI'm tempted to put that trailing smp_rmb() in spin_unlock_wait() too;
to use for locking correctness. For example, taking a look at nf_conntrack_all_lock(),
it too likes to get smart with spin_unlock_wait() -- also for finer graining purposes.
While not identical to sems, it goes like:
nf_conntrack_all_lock(): nf_conntrack_lock():
spin_lock(B); spin_lock(A);
if (bar) { // false
bar = 1; ...
}
[loop ctrl-barrier]
spin_unlock_wait(A);
foo(); foo();
If the spin_unlock_wait() doesn't yet see the store that makes A visibly locked,
we could end up with both threads in foo(), no?. (Although I'm unsure about that
ctrl barrier and archs could fall into it. The point was to see in-tree examples
of creative thinking with locking).
because I suspect the netfilter code is broken without it.
And it seems intuitive to assume that if we return from unlock_wait() we
can indeed observe the critical section we waited on.