|
| 1 | +# some platforms do not offer support for atomic primitive for all integer |
| 2 | +# types, in that case we need to link against libatomic |
| 3 | + |
| 4 | +include(CheckCXXSourceCompiles) |
| 5 | +include(CMakePushCheckState) |
| 6 | + |
| 7 | + |
| 8 | +function(check_cxx_atomics var) |
| 9 | + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11") |
| 10 | + check_cxx_source_compiles(" |
| 11 | +#include <atomic> |
| 12 | +#include <cstdint> |
| 13 | +#include <cstddef> |
| 14 | +#if defined(__SIZEOF_INT128__) |
| 15 | +// Boost needs 16-byte atomics for tagged pointers. |
| 16 | +// These are implemented via inline instructions on the platform |
| 17 | +// if 16-byte alignment can be proven, and are delegated to libatomic |
| 18 | +// library routines otherwise. Whether or not alignment is provably |
| 19 | +// OK for a std::atomic unfortunately depends on compiler version and |
| 20 | +// optimization levels, and also on the details of the expression. |
| 21 | +// We specifically test access via an otherwise unknown pointer here |
| 22 | +// to ensure we get the most complex case. If this access can be |
| 23 | +// done without libatomic, then all accesses can be done. |
| 24 | +struct tagged_ptr { |
| 25 | + int* ptr; |
| 26 | + std::size_t tag; |
| 27 | +}; |
| 28 | +void atomic16(std::atomic<tagged_ptr> *ptr) |
| 29 | +{ |
| 30 | + tagged_ptr p{nullptr, 1}; |
| 31 | + ptr->store(p); |
| 32 | + tagged_ptr f = ptr->load(); |
| 33 | + tagged_ptr new_tag{nullptr, 0}; |
| 34 | + ptr->compare_exchange_strong(f, new_tag); |
| 35 | +} |
| 36 | +#endif |
| 37 | +int main() { |
| 38 | +#if defined(__SIZEOF_INT128__) |
| 39 | + std::atomic<tagged_ptr> ptr; |
| 40 | + atomic16(&ptr); |
| 41 | +#endif |
| 42 | + std::atomic<uint8_t> w1; |
| 43 | + std::atomic<uint16_t> w2; |
| 44 | + std::atomic<uint32_t> w4; |
| 45 | + std::atomic<uint64_t> w8; |
| 46 | + return w1 + w2 + w4 + w8; |
| 47 | +} |
| 48 | +" ${var}) |
| 49 | +endfunction(check_cxx_atomics) |
| 50 | + |
| 51 | +cmake_push_check_state() |
| 52 | +check_cxx_atomics(HAVE_CXX11_ATOMIC) |
| 53 | +cmake_pop_check_state() |
| 54 | + |
| 55 | +if(NOT HAVE_CXX11_ATOMIC) |
| 56 | + cmake_push_check_state() |
| 57 | + set(CMAKE_REQUIRED_LIBRARIES "atomic") |
| 58 | + check_cxx_atomics(HAVE_LIBATOMIC) |
| 59 | + cmake_pop_check_state() |
| 60 | + if(HAVE_LIBATOMIC) |
| 61 | + set(LIBATOMIC_LINK_FLAGS "-latomic") |
| 62 | + else() |
| 63 | + message(FATAL_ERROR |
| 64 | + "Host compiler ${CMAKE_CXX_COMPILER} requires libatomic, but it is not found") |
| 65 | + endif() |
| 66 | +endif() |
0 commit comments