Thread (152 messages) 152 messages, 13 authors, 2016-04-14

Re: [v3,11/41] mips: reuse asm-generic/barrier.h

From: Paul E. McKenney <hidden>
Date: 2016-01-15 19:29:07
Also in: linux-arch, linux-arm-kernel, linux-s390, linux-sh, linux-um, linuxppc-dev, lkml, sparclinux, virtualization

On Fri, Jan 15, 2016 at 09:54:01AM -0800, Paul E. McKenney wrote:
On Fri, Jan 15, 2016 at 10:24:32AM +0000, Will Deacon wrote:
quoted
On Thu, Jan 14, 2016 at 02:55:10PM -0800, Paul E. McKenney wrote:
quoted
On Thu, Jan 14, 2016 at 01:36:50PM -0800, Leonid Yegoshin wrote:
quoted
On 01/14/2016 01:29 PM, Paul E. McKenney wrote:
quoted
quoted
On 01/14/2016 12:34 PM, Paul E. McKenney wrote:
quoted
The WRC+addr+addr is OK because data dependencies are not required to be
transitive, in other words, they are not required to flow from one CPU to
another without the help of an explicit memory barrier.
I don't see any reliable way to fit WRC+addr+addr into "DATA
DEPENDENCY BARRIERS" section recommendation to have data dependency
barrier between read of a shared pointer/index and read the shared
data based on that pointer. If you have this two reads, it doesn't
matter the rest of scenario, you should put the dependency barrier
in code anyway. If you don't do it in WRC+addr+addr scenario then
after years it can be easily changed to different scenario which
fits some of scenario in "DATA DEPENDENCY BARRIERS" section and
fails.
The trick is that lockless_dereference() contains an
smp_read_barrier_depends():

#define lockless_dereference(p) \
({ \
typeof(p) _________p1 = READ_ONCE(p); \
smp_read_barrier_depends(); /* Dependency order vs. p above. */ \
(_________p1); \
})

Or am I missing your point?
WRC+addr+addr has no any barrier. lockless_dereference() has a
barrier. I don't see a common points between this and that in your
answer, sorry.
Me, I am wondering what WRC+addr+addr has to do with anything at all.
See my earlier reply [1] (but also, your WRC Linux example looks more
like a variant on WWC and I couldn't really follow it).
I will revisit my WRC Linux example.  And yes, creating litmus tests
that use non-fake dependencies is still a bit of an undertaking.  :-/
I am sure that it will seem more natural with time and experience...
Hmmm...  You are quite right, I did do WWC.  I need to change cpu2()'s
last access from a store to a load to get WRC.  Plus the levels of
indirection definitely didn't match up, did they?

	struct foo {
		struct foo *next;
	};
	struct foo a;
	struct foo b;
	struct foo c = { &a };
	struct foo d = { &b };
	struct foo x = { &c };
	struct foo y = { &d };
	struct foo *r1, *r2, *r3;

	void cpu0(void)
	{
		WRITE_ONCE(x.next, &y);
	}

	void cpu1(void)
	{
		r1 = lockless_dereference(x.next);
		WRITE_ONCE(r1->next, &x);
	}

	void cpu2(void)
	{
		r2 = lockless_dereference(y.next);
		r3 = READ_ONCE(r2->next);
	}

In this case, it is legal to end the run with:

	r1 == &y && r2 == &x && r3 == &c

Please see below for a ppcmem litmus test.

So, did I get it right this time?  ;-)

							Thanx, Paul

PS.  And yes, working through this does help me understand the
     benefits of fake dependencies.  Why do you ask?  ;-)

------------------------------------------------------------------------

PPC WRCnf+addrs
""
{
0:r2=x; 0:r3=y;
1:r2=x; 1:r3=y;
2:r2=x; 2:r3=y;
c=a; d=b; x=c; y=d;
}
 P0           | P1            | P2            ;
 stw r3,0(r2) | lwz r8,0(r2)  | lwz r8,0(r3)  ;
              | stw r2,0(r3)  | lwz r9,0(r8)  ;
exists
(1:r8=y /\ 2:r8=x /\ 2:r9=c)
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help