Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undefined reference linker error when using 16-byte CAS with GCC

Tags:

c++

c++11

atomic

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?

like image 1000
Siler Avatar asked Nov 01 '14 12:11

Siler


Video Answer


1 Answers

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!)

like image 99
Mats Petersson Avatar answered Oct 03 '22 11:10

Mats Petersson