I'm using GCC 4.7.2 on Debian, and getting linker errors whenever I try to use the <atomic>
facilities with 16-byte values. I'm running an x86_64 VM which can support the CMPXCHG16B
instruction - but even if I didn't have the necessary hardware, I don't see why a linker error should be produced here. As far as I know, the <atomic>
library is supposed to fall back on using regular locks if the hardware doesn't support the necessary CAS operation.
Anyway, here's a very simple test case to reproduce this problem:
#include <atomic>
#include <cstdint>
struct foo
{
std::uint64_t x;
std::uint64_t y;
};
int main()
{
std::atomic<foo> f1({0,0});
foo f2 = {0,0};
foo f3 = {1,1};
f1.compare_exchange_strong(f2, f3);
}
When I compile this, I get:
# g++ test.cpp -o test -std=c++11 -g3
/tmp/ccziKZis.o: In function `std::atomic<foo>::compare_exchange_strong(foo&, foo, std::memory_order, std::memory_order)':
/usr/include/c++/4.7/atomic:259: undefined reference to `__atomic_compare_exchange_16'
collect2: error: ld returned 1 exit status
Note that if I change the program so that foo
is only 8 bytes, I don't get the linker error. What's going on here?
Simple answer, once you know it:
Invoke g++
with -mcx16
.
The g++ docs say:
This option will enable GCC to use CMPXCHG16B instruction in generated code. CMPXCHG16B allows for atomic operations on 128-bit double quadword (or oword) data types. This is useful for high resolution counters that could be updated by multiple processors (or cores). This instruction is generated as part of atomic built-in functions: see *note Atomic Builtins:: for details.
(Note that this doesn't work for clang
- I think that is a bug!)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With