]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/sanitizer_common/sanitizer_atomic_clang_x86.h
Vendor import of compiler-rt trunk r351319 (just before the release_80
[FreeBSD/FreeBSD.git] / lib / sanitizer_common / sanitizer_atomic_clang_x86.h
1 //===-- sanitizer_atomic_clang_x86.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_X86_H
16 #define SANITIZER_ATOMIC_CLANG_X86_H
17
18 namespace __sanitizer {
19
20 INLINE void proc_yield(int cnt) {
21   __asm__ __volatile__("" ::: "memory");
22   for (int i = 0; i < cnt; i++)
23     __asm__ __volatile__("pause");
24   __asm__ __volatile__("" ::: "memory");
25 }
26
27 template<typename T>
28 INLINE typename T::Type atomic_load(
29     const volatile T *a, memory_order mo) {
30   DCHECK(mo & (memory_order_relaxed | memory_order_consume
31       | memory_order_acquire | memory_order_seq_cst));
32   DCHECK(!((uptr)a % sizeof(*a)));
33   typename T::Type v;
34
35   if (sizeof(*a) < 8 || sizeof(void*) == 8) {
36     // Assume that aligned loads are atomic.
37     if (mo == memory_order_relaxed) {
38       v = a->val_dont_use;
39     } else if (mo == memory_order_consume) {
40       // Assume that processor respects data dependencies
41       // (and that compiler won't break them).
42       __asm__ __volatile__("" ::: "memory");
43       v = a->val_dont_use;
44       __asm__ __volatile__("" ::: "memory");
45     } else if (mo == memory_order_acquire) {
46       __asm__ __volatile__("" ::: "memory");
47       v = a->val_dont_use;
48       // On x86 loads are implicitly acquire.
49       __asm__ __volatile__("" ::: "memory");
50     } else {  // seq_cst
51       // On x86 plain MOV is enough for seq_cst store.
52       __asm__ __volatile__("" ::: "memory");
53       v = a->val_dont_use;
54       __asm__ __volatile__("" ::: "memory");
55     }
56   } else {
57     // 64-bit load on 32-bit platform.
58     __asm__ __volatile__(
59         "movq %1, %%mm0;"  // Use mmx reg for 64-bit atomic moves
60         "movq %%mm0, %0;"  // (ptr could be read-only)
61         "emms;"            // Empty mmx state/Reset FP regs
62         : "=m" (v)
63         : "m" (a->val_dont_use)
64         : // mark the mmx registers as clobbered
65 #ifdef __MMX__
66           "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
67 #endif  // #ifdef __MMX__
68           "memory");
69   }
70   return v;
71 }
72
73 template<typename T>
74 INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
75   DCHECK(mo & (memory_order_relaxed | memory_order_release
76       | memory_order_seq_cst));
77   DCHECK(!((uptr)a % sizeof(*a)));
78
79   if (sizeof(*a) < 8 || sizeof(void*) == 8) {
80     // Assume that aligned loads are atomic.
81     if (mo == memory_order_relaxed) {
82       a->val_dont_use = v;
83     } else if (mo == memory_order_release) {
84       // On x86 stores are implicitly release.
85       __asm__ __volatile__("" ::: "memory");
86       a->val_dont_use = v;
87       __asm__ __volatile__("" ::: "memory");
88     } else {  // seq_cst
89       // On x86 stores are implicitly release.
90       __asm__ __volatile__("" ::: "memory");
91       a->val_dont_use = v;
92       __sync_synchronize();
93     }
94   } else {
95     // 64-bit store on 32-bit platform.
96     __asm__ __volatile__(
97         "movq %1, %%mm0;"  // Use mmx reg for 64-bit atomic moves
98         "movq %%mm0, %0;"
99         "emms;"            // Empty mmx state/Reset FP regs
100         : "=m" (a->val_dont_use)
101         : "m" (v)
102         : // mark the mmx registers as clobbered
103 #ifdef __MMX__
104           "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
105 #endif  // #ifdef __MMX__
106           "memory");
107     if (mo == memory_order_seq_cst)
108       __sync_synchronize();
109   }
110 }
111
112 }  // namespace __sanitizer
113
114 #endif  // #ifndef SANITIZER_ATOMIC_CLANG_X86_H