Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the C++11 memory model prevent memory tearing and conflicts?

Reading a draft of C++11 I was interested by clause 1.7.3:

A memory location is either an object of scalar type or a maximal sequence of adjacent bit-fields all having non-zero width. ... Two threads of execution (1.10) can update and access separate memory locations without interfering with each other.

Does this clause protect from hardware related race conditions such as:

  • unaligned data access where memory is updated in two bus transactions (memory tearing)?
  • where you have distinct objects within a system memory unit, e.g. two 16-bit signed integers in a 32-bit word, and each independent update of the separate objects requires the entire memory unit to be written (memory conflict)?
like image 584
TheJuice Avatar asked Jun 05 '12 12:06

TheJuice


2 Answers

Regarding the second point, the standard guarantees that there will be no race there. That being said, I have been told that this guarantee is not implemented in current compilers, and it might even be impossible to implement in some architectures.

Regarding the first point, if the second point is guaranteed, and if your program does not contain any race condition, then the natural outcome is that this will not be a race condition either. That is, given the premise that the standard guarantees that writes to different sub word locations are safe, then the only case where you can have a race condition is if multiple threads access the same variable (that is split across words, or more probably for this to be problematic, across cache lines).

Again this might be hard or even impossible to implement. If your unaligned datum goes across a cache line, then it would be almost impossible to guarantee the correctness of the code without imposing a huge cost to performance. You should try to avoid unaligned variables as much as possible for this and other reasons (including raw performance, a write to an object that touches two cache lines involves writing as many as 32 bytes to memory, and if any other thread is touching any of the cache lines, it also involves the cost of synchronization of the caches...

like image 169
David Rodríguez - dribeas Avatar answered Nov 12 '22 21:11

David Rodríguez - dribeas


It does not protect against memory tearing, which is only visible when two threads access the same memory location (but the clause only applies to separate memory locations).

It appears to protect against memory conflict, according to your example. The most likely way to achieve this is that a system which can't write less than 32 bits at once would have 32-bit char, and then two separate objects could never share a "system memory unit". (The only way two 16-bit integers can be adjacent on a system with 32-bit char is as bitfields.)

like image 34
Ben Voigt Avatar answered Nov 12 '22 23:11

Ben Voigt