The C++11 Memory Model and GCC
This page contains links to the various pages which describe the new C++11 memory model and how it affects GCC.
Understanding the Memory Model
Summary and Compiler Options - A quick overall view.
DataRaces - Impacts on existing code optimization.
Atomic Types - The new atomic types.
Atomic Synchronization Modes - That pesky memory model parameter.
Implementation Summary - What needs to be done to GCC.
Testing - How to test and prevent regressions.
Practical Usage - The Dead-Simple version of what to do with all this.
GCC implementation details
Code generation for the C++ memory model - Changes needed to allow ports to utilize their hardware efficient synchronizations.
Optimization Aspects of C++ Atomics [ In Progress ] - Rationale for how the different atomic memory models may impact optimizers.
Optimization list. [ In Progress ] - List of various GCC optimizations and what can be done when encountering a synchronization builtin. Based on the previous rationale. This is for current discussion and future implementation. Currently everything is a full barrier.
GCC Alignment Policy - Addresses what the compiler and ports ought to do regarding atomic operations and alignment.
GCC 4.7 status
C++ memory model work is ongoing and scheduled for completion in the next GCC release. GCC 4.7 has now been released, so this is what you can expect from it.
Full atomic implementation for supported lock free instructions. All the atomic operations have been implemented with the new __atomic builtins, and most targets reflect the memory model parameter in the code which is generated. Optimizations will not move shared memory operations past atomic operations, so the various happens relationships are honoured.
When lock free instructions are not available (either through hardware or OS support) atomic operations are left as function calls to be resolved by a library. Due to time constraints and an API which is not finalized, there is no libatomic supplied with GCC 4.7. This is easily determined by encountering unsatisfied external symbols beginning with __atomic_*.
Should a program require library assistance, a single C file sample implementation is available to be compiled and linked in with the client program to resolve these external function calls using a locked implementation. Download sample libatomic
- C++ templates fully support arbitrary sized objects, althought the previously mentioned libatomic.c file may be required to satisfy some user defined classes. If a class maps to the same size as a supported lock-free integral type, then lock-free routines will be used as well.
- Bitfields are not compliant with the memory model. That is to say that they may introduce load or store data races due to whole word accesses when reading or writing.
- Optimizations have not been fully audited for compliance, although some work has been done. Some optimizations may introduce new data races which were not present before. The number of known cases are small, and testing for compliance is not trivial. If anyone encounters a case where an optimization introduces a new data race, please open a bugzilla case for it so it can be addressed.
From __sync to __atomic
Generally speaking, the original __sync built-in functions map to the equivalent __atomic built-in functions using the __ATOMIC_SEQ_CST memory model. The other memory model's allow architectures with a more relaxed approach to ordering loads and stores a bit more freedom and speed if the programmer understands the issues of synchronization and barriers. It is always safe to replace a __sync call with an __atomic call using the __ATOMIC_SEQ_CST memory model. This is in fact what happens internally right now. (__sync calls are processed by the new __atomic routines)
GCC 4.8 will transition all tool chain references to __sync with calls to __atomic with the __ATOMIC_SEQ_CST memory model. Each occurrence will be examined to see if a more relaxed memory model is more appropriate.
It is recommended that all new code use the __atomic functions and existing code be transitioned when possible in anticipation of the __sync routines eventually being deprecated.
The memory model parameter on __atomic functions is a signed integer. The lower 8 bits are reserved for the memory model, while the rest of the value is reserved for future use and should be 0. Using the provided __ATOMIC_* predefined values will ensure proper usage.
External Atomics Library
Gcc's current library plans - When an atomic call cannot be turned into lock-free instructions, GCC will make calls into this library. The goal is to get this standardized between all the compilers implementing atomics so the can interact seemlessly, so comments are welcome.
GCC 4.7 does not include a library implementation as the API has not been firmly established. GCC 4.8 will include a libatomic implementation with the toolchain. For users of GCC 4.7 who wish to build a library for their own use, a sample library is available here which can be compiled with gcc 4.7 as a single object file and linked with client code to provide the appropriate entry points and routines.
Personnel
Andrew MacLeod
- Aldy Hernandez
Status
The implementation was done on the cxx-mem-model branch in the GCC SVN repository and merged to the main trunk in November 2011.
The branch is maintained by Aldy Hernandez < aldyh@redhat.com >. The usual rules for contributing to branches apply to this branch:
Messages and patches to the lists should have their subject prefixed with [cxx-mem-model].
ChangeLog entries should be written to ChangeLog.mm.
TODO
- Create the testing framework which conclusively determines if a test passes or fails in a multithreaded environment.
- Create testcases to find places where the compiler introduces new data races, or tests atomic instructions.
- Modify the optimizations to honor the flags and pass the above testcases.