On Fri, 5 May 2023 at 21:19, Richard Henderson <[email protected]> wrote: > > On 5/4/23 18:17, Peter Maydell wrote: > >> + case MO_ATOM_WITHIN16: > >> + tmp = p & 15; > >> + if (tmp + (1 << size) <= 16) { > >> + atmax = size; > > > > OK, so this is "whole operation is within 16 bytes, > > whole operation must be atomic"... > > > >> + } else if (atmax == size) { > >> + return MO_8; > > > > ...but I don't understand the interaction of WITHIN16 > > and also specifying an ATMAX value that's not ATMAX_SIZE. > > I'm trying to describe e.g. LDP, which if not within16 has two 8-byte > elements, one or > both of which must be atomic. We will have set MO_ATOM_WITHIN16 | MO_ATMAX_8. > > If atmax == size, there is only one element, and since it is not within16, > there is no > atomicity. > > >> + } else if (tmp + (1 << atmax) != 16) { > > > > Why is this doing an exact inequality check? > > What if you're asking for a load of 8 bytes at > > MO_ATMAX_2 from a pointer that's at an offset of > > 10 bytes from a 16-byte boundary? Then tmp is 10, > > tmp + (1 << atmax) is 12, but we could still do the > > loads at atomicity 2. This doesn't seem to me to be > > any different from the case it does catch where > > the first ATMAX_2-sized unit happens to be the only > > thing in this 16-byte block. > > If the LDP is aligned mod 8, but not aligned mod 16, then both 8-byte > operations must be > (separately) atomic, and we return MO_64.
So there's an implicit "at most 2 atomic sub-operations inside a WITHIN16 load" restriction? i.e. you can't use WITHIN16 to say "do this 8 byte load atomically but if it's not in a 16-byte region do it with 4 2-byte loads", even though in theory MO_ATOM_WITHIN16 | MO_ATMAX_2 | MO_8 would describe that ? thanks -- PMM
