The pseudocode isn't UB because of the locks, but my argument is that it shouldn't be UB
even if the locks were gone. In that case, there is a simultaneous read/increment, but it's still obviously linearizable exactly the same way as with locks, so it still shouldn't be UB. (Or, if the memory fence caused by
atomic increment instruction makes it non-UB, then just imagine overwriting a flag without any fences instead.) In Rust it's not even possible to write such code.
Another example is Figure 5 in this paper [1] (referenced from Bohem's paper above):
x = y = 0
// thread 1: // thread 2:
a = x; c = y;
b = x; x = c;
if (a == b)
y = 1;
My point is that the assumption that
a == b is invalid if
x is a global variable. That's not a valid assumption for the compiler to make,
ever, unless it can prove that
x isn't accessed from different threads (as a human would have to, to manually perform the optimisation).
I haven't been tracking OCaml's progress too closely (multicore is just taking too long), but hopefully it's going in this direction... if you've any relevant references / descriptions of their memory model, let me know!
https://www.ccs.neu.edu/home/wahl/Teaching/Software-Model-Ch...