|
16 | 16 | // architecture-defined behavior and not standard defined behavior.
|
17 | 17 | // That should make trying other architectures easier.
|
18 | 18 |
|
19 |
| -// user can define QTHREADS_USE_STANDARD_128_BIT_ATOMICS in their flags to override this detection logic. |
| 19 | +// User can define QTHREADS_USE_STANDARD_128_BIT_ATOMICS in their flags to override this detection logic. |
20 | 20 | #ifndef QTHREADS_USE_STANDARD_128_BIT_ATOMICS
|
| 21 | + |
| 22 | +// Get the version of the gcc supporting libraries being used. |
| 23 | +// Clang currently says it's gcc 4.2 via the __GNUC__ and __GNUC_MINOR__ macros |
| 24 | +// so instead we have to parse the version info from it's selected gcc install at configure time |
| 25 | +// and pipe it through to here via our own preprocessor define. |
| 26 | +// icc exactly mimics gcc in this case, and icx and acfl behave the same as clang but do |
| 27 | +// not require their own detection logic here. |
| 28 | +#if defined(__clang__) |
| 29 | +#define QTHREADS_GCC_LIB_MAJOR_VERSION QTHREADS_CLANG_UNDERLYING_GCC_MAJOR_VERSION |
| 30 | +#define QTHREADS_GCC_LIB_MINOR_VERSION QTHREADS_CLANG_UNDERLYING_GCC_MINOR_VERSION |
| 31 | +#else |
| 32 | +#define QTHREADS_GCC_LIB_MAJOR_VERSION __GNUC__ |
| 33 | +#define QTHREADS_GCC_LIB_MINOR_VERSION __GNUC_MINOR__ |
| 34 | +#endif |
21 | 35 | #ifdef __x86_64__
|
22 | 36 | #ifdef __AVX__
|
23 | 37 | // Intel and AMD both specify that 128 bit loads and stores are atomic (with reasonable alignment constraints)
|
|
35 | 49 | // then fall back to the vendored implementation which just uses the old cmpxchg16b instruction if it would use locks.
|
36 | 50 | // With clang, it'll just inline the appropriate atomic instructions as long as optimizations are on.
|
37 | 51 | // In debug mode it falls back to the not quite equivalent libatomic implementation from gcc though.
|
38 |
| -// In our configure script we set clang up to tell us which gcc version it's using via the __GNUC__ and __GNUC_MINOR__ |
39 |
| -// defines instead of its old weird defaults so we can check for the libatomic version at compile time here. |
40 | 52 | // This all works assuming that qthreads is never compiled with a newer libatomic than is available at runtime.
|
41 |
| -// icc also just passes through the __GNUC__ values from the underlying gcc it's using. |
42 |
| -// icx and acfl just do what clang does. |
43 | 53 | #if defined(__clang__) && defined(__OPTIMIZE__)
|
44 | 54 | #define QTHREADS_USE_STANDARD_128_BIT_ATOMICS
|
45 |
| -#elif __GNUC__ >= 13 || (__GNUC__ == 12 && __GNUC_MINOR__ >= 3) || (__GNUC__ == 11 && __GNUC_MINOR__ >= 4) |
| 55 | +#elif QTHREADS_GCC_LIB_MAJOR_VERSION >= 13 || (QTHREADS_GCC_LIB_MAJOR_VERSION == 12 && QTHREADS_GCC_LIB_MINOR_VERSION >= 3) || (QTHREADS_GCC_LIB_MAJOR_VERSION == 11 && QTHREADS_GCC_LIB_MINOR_VERSION >= 4) |
46 | 56 | #define QTHREADS_USE_STANDARD_128_BIT_ATOMICS
|
47 | 57 | #endif
|
48 | 58 | #endif // #ifdef __AVX__
|
|
54 | 64 | #if defined(__clang) && defined(__OPTIMIZE__)
|
55 | 65 | // clang inlines the 128 bit atomic loads on arm as long as optimizations are on, but falls back to
|
56 | 66 | // the gcc libatomic implementation (which isn't always equivalent) when optimizations aren't on.
|
57 |
| -// At build time we have clang pipe the underlying gcc's version info through __GNUC__ and __GNUC_MINOR__ |
58 |
| -// so that logic works as a fallback when optimizations are off. |
59 | 67 | // Again, this all works assuming that qthreads is never compiled with a newer libatomic than is available at runtime.
|
60 | 68 | #define QTHREADS_USE_STANDARD_128_BIT_ATOMICS
|
61 |
| -#elif __GNUC__ >= 13 |
| 69 | +#elif QTHREADS_GCC_LIB_MAJOR_VERSION >= 13 |
62 | 70 | #if __ARM_ARCH > 8 && __ARM_ARCH != 801 && __ARM_ARCH != 802 && __ARM_ARCH != 803
|
63 | 71 | // gcc only provides lock-free 128 bit atomics in libatomic for armv8.4 and later.
|
64 | 72 | // We want arm 8.4 or later, but there's inconsistency with how to detect arm versions.
|
|
0 commit comments