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