1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2017 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker *
4*fb1b10abSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker */
10*fb1b10abSAndroid Build Coastguard Worker
11*fb1b10abSAndroid Build Coastguard Worker #ifndef VPX_VPX_UTIL_VPX_ATOMICS_H_
12*fb1b10abSAndroid Build Coastguard Worker #define VPX_VPX_UTIL_VPX_ATOMICS_H_
13*fb1b10abSAndroid Build Coastguard Worker
14*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_config.h"
15*fb1b10abSAndroid Build Coastguard Worker
16*fb1b10abSAndroid Build Coastguard Worker #ifdef __cplusplus
17*fb1b10abSAndroid Build Coastguard Worker extern "C" {
18*fb1b10abSAndroid Build Coastguard Worker #endif // __cplusplus
19*fb1b10abSAndroid Build Coastguard Worker
20*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD
21*fb1b10abSAndroid Build Coastguard Worker
22*fb1b10abSAndroid Build Coastguard Worker // Look for built-in atomic support. We cannot use <stdatomic.h> or <atomic>
23*fb1b10abSAndroid Build Coastguard Worker // since neither is guaranteed to exist on both C and C++ platforms, and we need
24*fb1b10abSAndroid Build Coastguard Worker // to back the atomic type with the same type (g++ needs to be able to use
25*fb1b10abSAndroid Build Coastguard Worker // gcc-built code). g++ 6 doesn't support _Atomic as a keyword and can't use the
26*fb1b10abSAndroid Build Coastguard Worker // stdatomic.h header. Even if both <stdatomic.h> and <atomic> existed it's not
27*fb1b10abSAndroid Build Coastguard Worker // guaranteed that atomic_int is the same type as std::atomic_int.
28*fb1b10abSAndroid Build Coastguard Worker // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60932#c13.
29*fb1b10abSAndroid Build Coastguard Worker #if !defined(__has_builtin)
30*fb1b10abSAndroid Build Coastguard Worker #define __has_builtin(x) 0 // Compatibility with non-clang compilers.
31*fb1b10abSAndroid Build Coastguard Worker #endif // !defined(__has_builtin)
32*fb1b10abSAndroid Build Coastguard Worker
33*fb1b10abSAndroid Build Coastguard Worker #if (__has_builtin(__atomic_load_n)) || \
34*fb1b10abSAndroid Build Coastguard Worker (defined(__GNUC__) && \
35*fb1b10abSAndroid Build Coastguard Worker (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
36*fb1b10abSAndroid Build Coastguard Worker // For GCC >= 4.7 and Clang versions that support __atomic builtins, use those.
37*fb1b10abSAndroid Build Coastguard Worker #define VPX_USE_ATOMIC_BUILTINS
38*fb1b10abSAndroid Build Coastguard Worker #else
39*fb1b10abSAndroid Build Coastguard Worker // Use platform-specific asm barriers.
40*fb1b10abSAndroid Build Coastguard Worker #if defined(_MSC_VER)
41*fb1b10abSAndroid Build Coastguard Worker // TODO(pbos): This assumes that newer versions of MSVC are building with the
42*fb1b10abSAndroid Build Coastguard Worker // default /volatile:ms (or older, where this is always true. Consider adding
43*fb1b10abSAndroid Build Coastguard Worker // support for using <atomic> instead of stdatomic.h when building C++11 under
44*fb1b10abSAndroid Build Coastguard Worker // MSVC. It's unclear what to do for plain C under /volatile:iso (inline asm?),
45*fb1b10abSAndroid Build Coastguard Worker // there're no explicit Interlocked* functions for only storing or loading
46*fb1b10abSAndroid Build Coastguard Worker // (presumably because volatile has historically implied that on MSVC).
47*fb1b10abSAndroid Build Coastguard Worker //
48*fb1b10abSAndroid Build Coastguard Worker // For earlier versions of MSVC or the default /volatile:ms volatile int are
49*fb1b10abSAndroid Build Coastguard Worker // acquire/release and require no barrier.
50*fb1b10abSAndroid Build Coastguard Worker #define vpx_atomic_memory_barrier() \
51*fb1b10abSAndroid Build Coastguard Worker do { \
52*fb1b10abSAndroid Build Coastguard Worker } while (0)
53*fb1b10abSAndroid Build Coastguard Worker #else
54*fb1b10abSAndroid Build Coastguard Worker #if VPX_ARCH_X86 || VPX_ARCH_X86_64
55*fb1b10abSAndroid Build Coastguard Worker // Use a compiler barrier on x86, no runtime penalty.
56*fb1b10abSAndroid Build Coastguard Worker #define vpx_atomic_memory_barrier() __asm__ __volatile__("" ::: "memory")
57*fb1b10abSAndroid Build Coastguard Worker #elif VPX_ARCH_ARM
58*fb1b10abSAndroid Build Coastguard Worker #define vpx_atomic_memory_barrier() __asm__ __volatile__("dmb ish" ::: "memory")
59*fb1b10abSAndroid Build Coastguard Worker #elif VPX_ARCH_MIPS
60*fb1b10abSAndroid Build Coastguard Worker #define vpx_atomic_memory_barrier() __asm__ __volatile__("sync" ::: "memory")
61*fb1b10abSAndroid Build Coastguard Worker #else
62*fb1b10abSAndroid Build Coastguard Worker #error Unsupported architecture!
63*fb1b10abSAndroid Build Coastguard Worker #endif // VPX_ARCH_X86 || VPX_ARCH_X86_64
64*fb1b10abSAndroid Build Coastguard Worker #endif // defined(_MSC_VER)
65*fb1b10abSAndroid Build Coastguard Worker #endif // atomic builtin availability check
66*fb1b10abSAndroid Build Coastguard Worker
67*fb1b10abSAndroid Build Coastguard Worker // These are wrapped in a struct so that they are not easily accessed directly
68*fb1b10abSAndroid Build Coastguard Worker // on any platform (to discourage programmer errors by setting values directly).
69*fb1b10abSAndroid Build Coastguard Worker // This primitive MUST be initialized using vpx_atomic_init or VPX_ATOMIC_INIT
70*fb1b10abSAndroid Build Coastguard Worker // (NOT memset) and accessed through vpx_atomic_ functions.
71*fb1b10abSAndroid Build Coastguard Worker typedef struct vpx_atomic_int {
72*fb1b10abSAndroid Build Coastguard Worker volatile int value;
73*fb1b10abSAndroid Build Coastguard Worker } vpx_atomic_int;
74*fb1b10abSAndroid Build Coastguard Worker
75*fb1b10abSAndroid Build Coastguard Worker #define VPX_ATOMIC_INIT(num) \
76*fb1b10abSAndroid Build Coastguard Worker { num }
77*fb1b10abSAndroid Build Coastguard Worker
78*fb1b10abSAndroid Build Coastguard Worker // Initialization of an atomic int, not thread safe.
vpx_atomic_init(vpx_atomic_int * atomic,int value)79*fb1b10abSAndroid Build Coastguard Worker static INLINE void vpx_atomic_init(vpx_atomic_int *atomic, int value) {
80*fb1b10abSAndroid Build Coastguard Worker atomic->value = value;
81*fb1b10abSAndroid Build Coastguard Worker }
82*fb1b10abSAndroid Build Coastguard Worker
vpx_atomic_store_release(vpx_atomic_int * atomic,int value)83*fb1b10abSAndroid Build Coastguard Worker static INLINE void vpx_atomic_store_release(vpx_atomic_int *atomic, int value) {
84*fb1b10abSAndroid Build Coastguard Worker #if defined(VPX_USE_ATOMIC_BUILTINS)
85*fb1b10abSAndroid Build Coastguard Worker __atomic_store_n(&atomic->value, value, __ATOMIC_RELEASE);
86*fb1b10abSAndroid Build Coastguard Worker #else
87*fb1b10abSAndroid Build Coastguard Worker vpx_atomic_memory_barrier();
88*fb1b10abSAndroid Build Coastguard Worker atomic->value = value;
89*fb1b10abSAndroid Build Coastguard Worker #endif // defined(VPX_USE_ATOMIC_BUILTINS)
90*fb1b10abSAndroid Build Coastguard Worker }
91*fb1b10abSAndroid Build Coastguard Worker
vpx_atomic_load_acquire(const vpx_atomic_int * atomic)92*fb1b10abSAndroid Build Coastguard Worker static INLINE int vpx_atomic_load_acquire(const vpx_atomic_int *atomic) {
93*fb1b10abSAndroid Build Coastguard Worker #if defined(VPX_USE_ATOMIC_BUILTINS)
94*fb1b10abSAndroid Build Coastguard Worker return __atomic_load_n(&atomic->value, __ATOMIC_ACQUIRE);
95*fb1b10abSAndroid Build Coastguard Worker #else
96*fb1b10abSAndroid Build Coastguard Worker int v = atomic->value;
97*fb1b10abSAndroid Build Coastguard Worker vpx_atomic_memory_barrier();
98*fb1b10abSAndroid Build Coastguard Worker return v;
99*fb1b10abSAndroid Build Coastguard Worker #endif // defined(VPX_USE_ATOMIC_BUILTINS)
100*fb1b10abSAndroid Build Coastguard Worker }
101*fb1b10abSAndroid Build Coastguard Worker
102*fb1b10abSAndroid Build Coastguard Worker #undef VPX_USE_ATOMIC_BUILTINS
103*fb1b10abSAndroid Build Coastguard Worker #undef vpx_atomic_memory_barrier
104*fb1b10abSAndroid Build Coastguard Worker
105*fb1b10abSAndroid Build Coastguard Worker #endif /* CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD */
106*fb1b10abSAndroid Build Coastguard Worker
107*fb1b10abSAndroid Build Coastguard Worker #ifdef __cplusplus
108*fb1b10abSAndroid Build Coastguard Worker } // extern "C"
109*fb1b10abSAndroid Build Coastguard Worker #endif // __cplusplus
110*fb1b10abSAndroid Build Coastguard Worker
111*fb1b10abSAndroid Build Coastguard Worker #endif // VPX_VPX_UTIL_VPX_ATOMICS_H_
112