|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [DOC v1] Xen transport for 9pfs
On Fri, 2 Dec 2016, David Vrabel wrote:
> On 02/12/16 00:29, Stefano Stabellini wrote:
> > On Wed, 30 Nov 2016, David Vrabel wrote:
> >> On 29/11/16 23:34, Stefano Stabellini wrote:
> >>>
> >>> The producer (the backend for **in**, the frontend for **out**) writes to
> >>> the
> >>> array in the following way:
> >>>
> >> - read memory barrier
> >>> - read *cons*, *prod* from shared memory
> >>> - write to array at position *prod* up to *cons*, wrapping around the
> >>> circular
> >>> buffer when necessary
> >> - write memory barrier
> >>> - increase *prod*
> >>> - notify the other end via evtchn
> >>>
> >>> The consumer (the backend for **out**, the frontend for **in**) reads
> >>> from the
> >>> array in the following way:
> >>
> >> - read memory barrier
> >>> - read *prod*, *cons* from shared memory
> >>> - read from array at position *cons* up to *prod*, wrapping around the
> >>> circular
> >>> buffer when necessary
> >>> - memory barrier
> >>> - increase *cons*
> >>> - notify the other end via evtchn
> >>
> >> Your barriers are wrong (see corrections above).
> >
> > Thanks for the review. Sorry for not specifying the type of memory
> > barriers. I agree with some of your suggestions, but I don't understand
> > why you moved the read memory barrier before reading prod and cons.
> >
> > Shouldn't it be for a producer:
> > - read *cons*, *prod* from shared memory
> > - read memory barrier
>
> Barriers must be paired to enforce the required ordering. So where you
> have a barrier before writing cons, you need another barrier before
> reading cons on the other side.
>
> This barrier here does nothing because the following access is a write
> and there's a data dependency here anyway.
You are right that this should be a general memory barrier as the
following is a write. You are also right that it looks superfluous
because there is a data dependency, but it is necessary to match the
barrier on the consumer side, see below.
> Without a barrier P before reading cons it can see the value after C as
> written cons but before C has actually read the requests.
>
> The Linux barrier documentation explains this better than I can.
This is an example from Documentation/memory-barriers.txt:
CPU 1 CPU 2
=================== ===================
WRITE_ONCE(a, 1); }---- --->{ v = READ_ONCE(c);
WRITE_ONCE(b, 2); } \ / { w = READ_ONCE(d);
<write barrier> \ <read barrier>
WRITE_ONCE(c, 3); } / \ { x = READ_ONCE(a);
WRITE_ONCE(d, 4); }---- --->{ y = READ_ONCE(b);
I'll adapt this example to our case:
CPU1 == Producer CPU2 == Consumer
=================== ===================
WRITE DATA TO RING READ PROD
<write barrier> <read barrier>
WRITE PROD READ DATA FROM RING
It is exactly the same. If you agree that this is correct so far, I'll
add the other half of it:
CPU1 == Producer CPU2 == Consumer
=================== ===================
READ CONS READ DATA FROM RING
<general barrier> <general barrier>
WRITE DATA TO RING WRITE CONS
There isn't exactly a matching example in
Documentation/memory-barriers.txt, but I think is correct.
All together:
CPU1 == Producer CPU2 == Consumer
=================== ===================
READ CONS READ PROD
<general barrier 1> <read barrier 3>
WRITE DATA TO RING READ DATA FROM RING
<write barrier 2> <general barrier 4>
WRITE PROD WRITE CONS
1 is pared with 4
2 is pared with 3
If there is a problem with this, I don't see it, please explain.
> >> I think you should use a private copy of cons/prod in the
> >> consumer/producer and use this to validate that the shared prod/cons is
> >> within a sensible range.
> >
> > With the masking macro provided (MASK_XEN_9PFS_IDX), indices cannot go
> > out of range:
> >
> > #define MASK_XEN_9PFS_IDX(idx) ((idx) & (XEN_9PFS_RING_SIZE - 1))
>
> For example, the producer writes cons = 0 and prod = 100000000 so
> although you will not index off the array, the consumer will end up
> processing 1000s of bogus entries.
I see, I'll write something about it.
> There have been XSAs where backends did not validate prod in this way.
Really? I thought that the XSAs were about reading the same field twice.
So for example:
cons = ring->cons;
prod = ring->prod;
<some barrier>
do_stuff1();
do_stuff2(ring->prod);
Maybe I am thinking of a different XSA?
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |