1 | //===-- sanitizer_atomic_clang.h --------------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file is a part of ThreadSanitizer/AddressSanitizer runtime. |
10 | // Not intended for direct inclusion. Include sanitizer_atomic.h. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef SANITIZER_ATOMIC_CLANG_H |
15 | #define SANITIZER_ATOMIC_CLANG_H |
16 | |
17 | #if defined(__i386__) || defined(__x86_64__) |
18 | # include "sanitizer_atomic_clang_x86.h" |
19 | #else |
20 | # include "sanitizer_atomic_clang_other.h" |
21 | #endif |
22 | |
23 | namespace __sanitizer { |
24 | |
25 | // We would like to just use compiler builtin atomic operations |
26 | // for loads and stores, but they are mostly broken in clang: |
27 | // - they lead to vastly inefficient code generation |
28 | // (http://llvm.org/bugs/show_bug.cgi?id=17281) |
29 | // - 64-bit atomic operations are not implemented on x86_32 |
30 | // (http://llvm.org/bugs/show_bug.cgi?id=15034) |
31 | // - they are not implemented on ARM |
32 | // error: undefined reference to '__atomic_load_4' |
33 | |
34 | // See http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html |
35 | // for mappings of the memory model to different processors. |
36 | |
37 | inline void atomic_signal_fence(memory_order) { |
38 | __asm__ __volatile__("" ::: "memory" ); |
39 | } |
40 | |
41 | inline void atomic_thread_fence(memory_order) { |
42 | __sync_synchronize(); |
43 | } |
44 | |
45 | template<typename T> |
46 | inline typename T::Type atomic_fetch_add(volatile T *a, |
47 | typename T::Type v, memory_order mo) { |
48 | (void)mo; |
49 | DCHECK(!((uptr)a % sizeof(*a))); |
50 | return __sync_fetch_and_add(&a->val_dont_use, v); |
51 | } |
52 | |
53 | template<typename T> |
54 | inline typename T::Type atomic_fetch_sub(volatile T *a, |
55 | typename T::Type v, memory_order mo) { |
56 | (void)mo; |
57 | DCHECK(!((uptr)a % sizeof(*a))); |
58 | return __sync_fetch_and_add(&a->val_dont_use, -v); |
59 | } |
60 | |
61 | template<typename T> |
62 | inline typename T::Type atomic_exchange(volatile T *a, |
63 | typename T::Type v, memory_order mo) { |
64 | DCHECK(!((uptr)a % sizeof(*a))); |
65 | if (mo & (memory_order_release | memory_order_acq_rel | memory_order_seq_cst)) |
66 | __sync_synchronize(); |
67 | v = __sync_lock_test_and_set(&a->val_dont_use, v); |
68 | if (mo == memory_order_seq_cst) |
69 | __sync_synchronize(); |
70 | return v; |
71 | } |
72 | |
73 | template <typename T> |
74 | inline bool atomic_compare_exchange_strong(volatile T *a, typename T::Type *cmp, |
75 | typename T::Type xchg, |
76 | memory_order mo) { |
77 | // Transitioned from __sync_val_compare_and_swap to support targets like |
78 | // SPARC V8 that cannot inline atomic cmpxchg. __atomic_compare_exchange |
79 | // can then be resolved from libatomic. __ATOMIC_SEQ_CST is used to best |
80 | // match the __sync builtin memory order. |
81 | return __atomic_compare_exchange(&a->val_dont_use, cmp, &xchg, false, |
82 | __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); |
83 | } |
84 | |
85 | template<typename T> |
86 | inline bool atomic_compare_exchange_weak(volatile T *a, |
87 | typename T::Type *cmp, |
88 | typename T::Type xchg, |
89 | memory_order mo) { |
90 | return atomic_compare_exchange_strong(a, cmp, xchg, mo); |
91 | } |
92 | |
93 | } // namespace __sanitizer |
94 | |
95 | // This include provides explicit template instantiations for atomic_uint64_t |
96 | // on MIPS32, which does not directly support 8 byte atomics. It has to |
97 | // proceed the template definitions above. |
98 | #if defined(_MIPS_SIM) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 |
99 | # include "sanitizer_atomic_clang_mips.h" |
100 | #endif |
101 | |
102 | #undef ATOMIC_ORDER |
103 | |
104 | #endif // SANITIZER_ATOMIC_CLANG_H |
105 | |