-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
.NET .volatile writes don't prevent any writes from floating above them - that's the semantics of store-release. So in the following scenario..
Voltile.Write(ref locationA, 1);
locationB = 2; // normal writethose 2 writes can be reordered.
@JPWatson suggested putting a dummy volatile read from the just written location to form a single barrier that doesn't pass reads/writes below itself nor allows writes to float above it.
Voltile.Write(ref locationA, 1);
_dummy = Voltile.Read(ref locationA);
locationB = 2; // normal writeThe reasoning is this:
- volatile reads can't be reordered with the writes to the same memory location
- volatile operations can't be eliminated
- no memory operations can be reordered with a previous volatile read
- no memory operations can be reordered with a following volatile write
It looks legitimate according to ECMA CLI
A volatile read has “acquire semantics” meaning that the read is guaranteed to occur prior to any
references to memory that occur after the read instruction in the CIL instruction sequence. A
volatile write has “release semantics” meaning that the write is guaranteed to happen after any
memory references prior to the write instruction in the CIL instruction sequence.
...
An optimizing compiler that converts CIL to native code shall not remove any volatile operation,
nor shall it coalesce multiple volatile operations into a single operation.
For reads this trick won't work because in such scenario, thanks to store buffer forwarding, reads can be reordered with the dummy read. @joeduffy explained it here and here.
Is it a legitimate way to create a barrier for following writes or we have to use full memory barrier?