Remove support for stdatomic.h.

This header doesn't build on g++ v6 as it's a C and not C++ header
(_Atomic is not a keyword in C++11). Since the C and C++ invocations
cannot be guaranteed to point to the same underlying atomic_int
implementation, remove support for them and use compiler intrinsics
instead.

BUG=webm:1461

Change-Id: Ie1cd6759c258042efc87f51f036b9aa53e4ea9d5
This commit is contained in:
Peter Boström 2017-09-06 11:48:42 -04:00
parent d49a1a5329
commit 6822fb2f09

View File

@ -19,13 +19,13 @@ extern "C" {
#if CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD #if CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \ // Look for built-in atomic support. We cannot use <stdatomic.h> or <atomic>
(defined(__cplusplus) && __cplusplus >= 201112L) // since neither is guaranteed to exist on both C and C++ platforms, and we need
// Where available, use <stdatomic.h> // to back the atomic type with the same type (g++ needs to be able to use
#include <stdatomic.h> // gcc-built code). g++ 6 doesn't support _Atomic as a keyword and can't use the
#define VPX_USE_STD_ATOMIC // stdatomic.h header. Even if both <stdatomic.h> and <atomic> existed it's not
#else // guaranteed that atomic_int is the same type as std::atomic_int.
// Look for built-ins. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60932#c13.
#if !defined(__has_builtin) #if !defined(__has_builtin)
#define __has_builtin(x) 0 // Compatibility with non-clang compilers. #define __has_builtin(x) 0 // Compatibility with non-clang compilers.
#endif // !defined(__has_builtin) #endif // !defined(__has_builtin)
@ -33,7 +33,7 @@ extern "C" {
#if (__has_builtin(__atomic_load_n)) || \ #if (__has_builtin(__atomic_load_n)) || \
(defined(__GNUC__) && \ (defined(__GNUC__) && \
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))) (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
// For GCC >= 4.7 and Clang that support __atomic builtins, use those. // For GCC >= 4.7 and Clang versions that support __atomic builtins, use those.
#define VPX_USE_ATOMIC_BUILTINS #define VPX_USE_ATOMIC_BUILTINS
#else #else
// Use platform-specific asm barriers. // Use platform-specific asm barriers.
@ -63,64 +63,40 @@ extern "C" {
#endif // ARCH_X86 || ARCH_X86_64 #endif // ARCH_X86 || ARCH_X86_64
#endif // defined(_MSC_VER) #endif // defined(_MSC_VER)
#endif // atomic builtin availability check #endif // atomic builtin availability check
#endif // stdatomic availability check
// These are wrapped in a struct so that they are not easily accessed directly // These are wrapped in a struct so that they are not easily accessed directly
// on any platform (to discourage programmer errors by setting values directly). // on any platform (to discourage programmer errors by setting values directly).
// This primitive MUST be initialized using vpx_atomic_init or VPX_ATOMIC_INIT // This primitive MUST be initialized using vpx_atomic_init or VPX_ATOMIC_INIT
// (NOT memset) and accessed through vpx_atomic_ functions. // (NOT memset) and accessed through vpx_atomic_ functions.
typedef struct vpx_atomic_int { typedef struct vpx_atomic_int { volatile int value; } vpx_atomic_int;
#if defined(VPX_USE_STD_ATOMIC)
atomic_int value;
#else
volatile int value;
#endif // defined(USE_STD_ATOMIC)
} vpx_atomic_int;
#if defined(VPX_USE_STD_ATOMIC)
#define VPX_ATOMIC_INIT(num) \
{ ATOMIC_VAR_INIT(num) }
#else
#define VPX_ATOMIC_INIT(num) \ #define VPX_ATOMIC_INIT(num) \
{ num } { num }
#endif // defined(VPX_USE_STD_ATOMIC)
// Initialization of an atomic int, not thread safe. // Initialization of an atomic int, not thread safe.
static INLINE void vpx_atomic_init(vpx_atomic_int *atomic, int value) { static INLINE void vpx_atomic_init(vpx_atomic_int *atomic, int value) {
#if defined(VPX_USE_STD_ATOMIC)
atomic_init(&atomic->value, value);
#else
atomic->value = value; atomic->value = value;
#endif // defined(USE_STD_ATOMIC)
} }
static INLINE void vpx_atomic_store_release(vpx_atomic_int *atomic, int value) { static INLINE void vpx_atomic_store_release(vpx_atomic_int *atomic, int value) {
#if defined(VPX_USE_STD_ATOMIC) #if defined(VPX_USE_ATOMIC_BUILTINS)
atomic_store_explicit(&atomic->value, value, memory_order_release);
#elif defined(VPX_USE_ATOMIC_BUILTINS)
__atomic_store_n(&atomic->value, value, __ATOMIC_RELEASE); __atomic_store_n(&atomic->value, value, __ATOMIC_RELEASE);
#else #else
vpx_atomic_memory_barrier(); vpx_atomic_memory_barrier();
atomic->value = value; atomic->value = value;
#endif // defined(VPX_USE_STD_ATOMIC) #endif // defined(VPX_USE_ATOMIC_BUILTINS)
} }
static INLINE int vpx_atomic_load_acquire(const vpx_atomic_int *atomic) { static INLINE int vpx_atomic_load_acquire(const vpx_atomic_int *atomic) {
#if defined(VPX_USE_STD_ATOMIC) #if defined(VPX_USE_ATOMIC_BUILTINS)
// const_cast (in C) that doesn't trigger -Wcast-qual.
return atomic_load_explicit(
(atomic_int *)(uintptr_t)(const void *)&atomic->value,
memory_order_acquire);
#elif defined(VPX_USE_ATOMIC_BUILTINS)
return __atomic_load_n(&atomic->value, __ATOMIC_ACQUIRE); return __atomic_load_n(&atomic->value, __ATOMIC_ACQUIRE);
#else #else
int v = atomic->value; int v = atomic->value;
vpx_atomic_memory_barrier(); vpx_atomic_memory_barrier();
return v; return v;
#endif // defined(VPX_USE_STD_ATOMIC) #endif // defined(VPX_USE_ATOMIC_BUILTINS)
} }
#undef VPX_USE_STD_ATOMIC
#undef VPX_USE_ATOMIC_BUILTINS #undef VPX_USE_ATOMIC_BUILTINS
#undef vpx_atomic_memory_barrier #undef vpx_atomic_memory_barrier