On Wed, 13 Aug 2025 12:29:28 GMT, Emanuel Peter <epe...@openjdk.org> wrote:

>> Per Minborg has updated the pull request with a new target base due to a 
>> merge or a rebase. The incremental webrev excludes the unrelated changes 
>> brought in by the merge/rebase. The pull request contains 12 additional 
>> commits since the last revision:
>> 
>>  - Revert comment
>>  - Revert change in AMSI
>>  - Back paddle on the branchless overlap method
>>  - Merge branch 'master' into copy-overlap
>>  - Fix comment
>>  - Simplify
>>  - Update copyright year
>>  - Add a branchless overlaps method
>>  - Optimize copy for certain lengths
>>  - Add methods to ScopedMemoryAccess
>>  - ... and 2 more: https://git.openjdk.org/jdk/compare/6f6585fd...1a1606e2
>
> If I see this right, it could be that we duplicate the copy on a byte. If we 
> only copy 2 bytes, then the copy on the second byte is repeated:
> 
> src[0] -> dst[0]
> src[1] -> dst[1]
> src[1] -> dst[1]
> 
> But is that ok?
> 
> Assume we have threads 1 and 2, both access memory locations A and B:
> 
> // Initial state
> A = x;
> B = y;
> 
> // Concurrently:
> 1: B = A;
> 2: A = B + 1;
> 
> What states could be observed at the end? We could look at all permutations 
> of the 4 operations from threads 1 and 2. Let's call the operations 1.1 (1 
> loads A), 1.2 (1 stores B), 2.1 (2 loads B), 2.2 (2 stores A).
> These are the 4! / 4 = 6 possible permutations, together with the results for 
> A and B:
> 
> 1.1 1.2 2.1 2.2 -> A = x+1; B = x
> 1.1 2.1 1.2 2.2 -> A = y+1; B = x
> 1.1 2.1 2.2 1.2 -> A = y+1; B = x
> 2.1 1.1 1.2 2.2 -> A = y+1; B = x
> 2.1 1.1 2.2 1.2 -> A = y+1; B = x
> 2.1 2.2 1.1 1.2 -> A = y+1; B = y+1
> 
> Now assume we repeat the copy for thread 1. Thus, this could happen:
> 
> 1: B = A;
> 2: A = B + 1;
> 1: B = A; // repeated copy
> 
> And if it happens in this sequence, we get result:
> `A = x+1; B = x+1`
> But this result was not observable before.
> 
> That makes me wonder if repeating the copy is really allowed in the Java 
> memory model?

> We have discussed the possibility of threads seeing different values, like in 
> the above example by @eme64. We think this is ok because there are no 
> guarantees of inter-thread visibility for memory segments. This has to be 
> provided externally (e.g., using volatile/CAS operations). There are other 
> cases where we are susceptible to similar problems (e.g, when doing unaligned 
> long access). In short, segments do not fulfill all the aspects of the normal 
> Java memory model (like for arrays).

Hmm, I see. Is this documented in the `MemorySegment` API? What are all the bad 
things that can happen?
- Tearing of unaligned access - can it also tear if the user has ensured 
alignment?
- Repeated instructions (like the repeated copy I pointed out above).

It is of course a little surprising that you lose the Java memory model 
guarantees of instruction ordering if you wrap an array in a `MemorySegment`.

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

PR Comment: https://git.openjdk.org/jdk/pull/26672#issuecomment-3184127780

Reply via email to