Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How come std::atomic<double> isn't implemented when compiling with clang?

Consider the following piece of code:

#include <atomic>

int main(void) {
  std::atomic<double> aDouble;
  aDouble = 6.0;
}

G++ compiles it just fine while clang++ produces the following:

clang++ -std=c++11 Main.cpp 
/tmp/Main-d4f0fc.o: In function `std::atomic<double>::store(double, std::memory_order)':
Main.cpp:(.text._ZNSt6atomicIdE5storeEdSt12memory_order[_ZNSt6atomicIdE5storeEdSt12memory_order]+0x31): undefined reference to `__atomic_store_8'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Do they not link against the same standard library?

like image 801
Rovanion Avatar asked Mar 07 '15 21:03

Rovanion


1 Answers

If clang++ -stdlib=libstdc++ doesn't solve your problem, link with -latomic for the implementation of these functions.

Try to get your compiler to inline 8-byte and narrower atomics, though, because the library functions have potentially large downsides.

Beware that the library functions don't support a memory ordering weaker than memory_order_seq_cst, so they always use mfence on x86, even if the source used relaxed.


The 32-bit x86 version of __atomic_store_8 is even worse: it uses lock cmpxchg8b instead of an SSE or x87 8-byte store. This makes it work even if it's misaligned, but at a massive performance penalty. It also has two redundant lock or [esp], 0 instructions as extra barriers around loading its arguments from the stack. (I'm looking at /usr/lib32/libatomic.so.1.2.0 from gcc7.1.1 on Arch Linux.)

Ironically, current gcc -m32 (in C11 mode, not C++11) under-aligns atomic_llong inside a struct, but inlines movq xmm loads/stores, so it's not actually atomic. (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65146#c4)

Current clang -m32 aligns atomic_llong to 8 bytes even inside structs (unlike regular long long, which the i386 System V ABI only aligns to 4B). The irony is that clang generates calls to the library functions, which uses a lock cmpxchg8b (https://bugs.llvm.org/show_bug.cgi?id=33109) so it actually is atomic even with cache-line splits. (Why is integer assignment on a naturally aligned variable atomic on x86?).

So clang is safe even if some gcc-compiled code passes it a pointer to a misaligned _Atomic long long. But it disagrees with gcc about struct layout, so this can only help if it gets a pointer to the atomic variable directly, rather than the containing struct.


Related: Atomic double floating point or SSE/AVX vector load/store on x86_64

like image 92
Peter Cordes Avatar answered Nov 10 '22 11:11

Peter Cordes