7
votes

I think C++ does not cover any sort of transaction memory yet, but still TSX can somehow fit using "as if rule" into something that is governed by C++ memory model.

So, what happens on successful HLE operation, or successful RTM transaction?

Saying "there is data race, but it is ok" is not much helpful, as it does not clarify what "ok" means.

With HLE probably it can be seen as "previous operation happens before subsequent operation. As if the section was still guarded by the lock that was elided".

What is with RTM? As there's no even an elided lock, only (potentially non-atomic) memory operations, which could be loads, stores, both, or no-op. What is synchronized with what? What happens before what?

1
The transactional memory TS has been shelved for now, as it's still "too niche". As far as Standard C++ is concerned, Intel TSX is just Undefined Behavior. Specific implementations may have implementation-specified behavior; I'd check icc first.MSalters
As compilers provide intrinsics for TSX (both HLE and RTM), I expect something sane for them. So I think this "sane thing" can be mapped into memory model.Alex Guteniev
I also think that there are useful cases for transaction memory as optional implementation detail even before it is official standard feature. See, for example, the implementation of std::call_once, that is called from a single thread most of the time, so is likely to benefit from lock elided by HLE (sure, transition between states is under potentially elided lock, not user callback). Or maybe even shared_ptr copy counters, that mostly copied in a single thread.Alex Guteniev

1 Answers

4
votes

Apparently before going into specs or asking SO I should have read thoroughly "overview" pages:

Hardware Lock Elision Overview

The hardware ensures program order of operations on the lock, even though the eliding processor did not perform external write operations to the lock. If the eliding processor itself reads the value of the lock in the critical section, it will appear as if the processor had acquired the lock (the read will return the non-elided value). This behavior makes an HLE execution functionally equivalent to an execution without the HLE prefixes.

Restricted Transactional Memory Overview

RTM Memory Ordering

A successful RTM commit causes all memory operations in the RTM region to appear to execute atomically. A successfully committed RTM region consisting of an XBEGIN followed by an XEND, even with no memory operations in the RTM region, has the same ordering semantics as a LOCK prefixed instruction. The XBEGIN instruction does not have fencing semantics. However, if an RTM execution aborts, all memory updates from within the RTM region are discarded and never made visible to any other logical processor.

To complete the answer:

LOCK prefixed instructions map to C++ std::memory_order::seq_cst. This covers all successful RTM transactions (which are as if single LOCK-prefixed instruction). It also covers most of HLE cases. Specifically:

  • LOCK prefixed instructions are executed as if they are executed, this implies seq_cst too
  • The same for XACQUIRE XCHG / XRELEASE XCHG, as if it is executed, this implies seq_cst too
  • Finally, XRELEASE MOV [mem], op is as if MOV [mem], op, so it is just release (under usual implementation of C++ memory model where sequentially consistent store has memory fence, not load)

(The documentation links are for Intel compiler. However they document hardware behavior, so the information should be applicable to other compilers. The only variable that compiler might introduce is compile time reordering. I expect however that if compiler implements intrinsic, it also implements proper reordering prohibition, if still unsure, place compiler barriers. And with direct assembly should just mark assembly code accordingly)