]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_other.h
MFV r339792:
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / sanitizer_common / sanitizer_atomic_clang_other.h
1 //===-- sanitizer_atomic_clang_other.h --------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
11 // Not intended for direct inclusion. Include sanitizer_atomic.h.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef SANITIZER_ATOMIC_CLANG_OTHER_H
16 #define SANITIZER_ATOMIC_CLANG_OTHER_H
17
18 namespace __sanitizer {
19
20
21 INLINE void proc_yield(int cnt) {
22   __asm__ __volatile__("" ::: "memory");
23 }
24
25 template<typename T>
26 INLINE typename T::Type atomic_load(
27     const volatile T *a, memory_order mo) {
28   DCHECK(mo & (memory_order_relaxed | memory_order_consume
29       | memory_order_acquire | memory_order_seq_cst));
30   DCHECK(!((uptr)a % sizeof(*a)));
31   typename T::Type v;
32
33   if (sizeof(*a) < 8 || sizeof(void*) == 8) {
34     // Assume that aligned loads are atomic.
35     if (mo == memory_order_relaxed) {
36       v = a->val_dont_use;
37     } else if (mo == memory_order_consume) {
38       // Assume that processor respects data dependencies
39       // (and that compiler won't break them).
40       __asm__ __volatile__("" ::: "memory");
41       v = a->val_dont_use;
42       __asm__ __volatile__("" ::: "memory");
43     } else if (mo == memory_order_acquire) {
44       __asm__ __volatile__("" ::: "memory");
45       v = a->val_dont_use;
46       __sync_synchronize();
47     } else {  // seq_cst
48       // E.g. on POWER we need a hw fence even before the store.
49       __sync_synchronize();
50       v = a->val_dont_use;
51       __sync_synchronize();
52     }
53   } else {
54     // 64-bit load on 32-bit platform.
55     // Gross, but simple and reliable.
56     // Assume that it is not in read-only memory.
57     v = __sync_fetch_and_add(
58         const_cast<typename T::Type volatile *>(&a->val_dont_use), 0);
59   }
60   return v;
61 }
62
63 template<typename T>
64 INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
65   DCHECK(mo & (memory_order_relaxed | memory_order_release
66       | memory_order_seq_cst));
67   DCHECK(!((uptr)a % sizeof(*a)));
68
69   if (sizeof(*a) < 8 || sizeof(void*) == 8) {
70     // Assume that aligned loads are atomic.
71     if (mo == memory_order_relaxed) {
72       a->val_dont_use = v;
73     } else if (mo == memory_order_release) {
74       __sync_synchronize();
75       a->val_dont_use = v;
76       __asm__ __volatile__("" ::: "memory");
77     } else {  // seq_cst
78       __sync_synchronize();
79       a->val_dont_use = v;
80       __sync_synchronize();
81     }
82   } else {
83     // 64-bit store on 32-bit platform.
84     // Gross, but simple and reliable.
85     typename T::Type cmp = a->val_dont_use;
86     typename T::Type cur;
87     for (;;) {
88       cur = __sync_val_compare_and_swap(&a->val_dont_use, cmp, v);
89       if (cmp == v)
90         break;
91       cmp = cur;
92     }
93   }
94 }
95
96 }  // namespace __sanitizer
97
98 #endif  // #ifndef SANITIZER_ATOMIC_CLANG_OTHER_H