1 //===-- sanitizer_atomic_msvc.h ---------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
11 // Not intended for direct inclusion. Include sanitizer_atomic.h.
13 //===----------------------------------------------------------------------===//
15 #ifndef SANITIZER_ATOMIC_MSVC_H
16 #define SANITIZER_ATOMIC_MSVC_H
18 extern "C" void _ReadWriteBarrier();
19 #pragma intrinsic(_ReadWriteBarrier)
20 extern "C" void _mm_mfence();
21 #pragma intrinsic(_mm_mfence)
22 extern "C" void _mm_pause();
23 #pragma intrinsic(_mm_pause)
24 extern "C" char _InterlockedExchange8( // NOLINT
25 char volatile *Addend, char Value); // NOLINT
26 #pragma intrinsic(_InterlockedExchange8)
27 extern "C" short _InterlockedExchange16( // NOLINT
28 short volatile *Addend, short Value); // NOLINT
29 #pragma intrinsic(_InterlockedExchange16)
30 extern "C" long _InterlockedExchange( // NOLINT
31 long volatile *Addend, long Value); // NOLINT
32 #pragma intrinsic(_InterlockedExchange)
33 extern "C" long _InterlockedExchangeAdd( // NOLINT
34 long volatile * Addend, long Value); // NOLINT
35 #pragma intrinsic(_InterlockedExchangeAdd)
36 extern "C" char _InterlockedCompareExchange8( // NOLINT
37 char volatile *Destination, // NOLINT
38 char Exchange, char Comparand); // NOLINT
39 #pragma intrinsic(_InterlockedCompareExchange8)
40 extern "C" short _InterlockedCompareExchange16( // NOLINT
41 short volatile *Destination, // NOLINT
42 short Exchange, short Comparand); // NOLINT
43 #pragma intrinsic(_InterlockedCompareExchange16)
45 long long _InterlockedCompareExchange64( // NOLINT
46 long long volatile *Destination, // NOLINT
47 long long Exchange, long long Comparand); // NOLINT
48 #pragma intrinsic(_InterlockedCompareExchange64)
49 extern "C" void *_InterlockedCompareExchangePointer(
50 void *volatile *Destination,
51 void *Exchange, void *Comparand);
52 #pragma intrinsic(_InterlockedCompareExchangePointer)
54 long __cdecl _InterlockedCompareExchange( // NOLINT
55 long volatile *Destination, // NOLINT
56 long Exchange, long Comparand); // NOLINT
57 #pragma intrinsic(_InterlockedCompareExchange)
60 extern "C" long long _InterlockedExchangeAdd64( // NOLINT
61 long long volatile * Addend, long long Value); // NOLINT
62 #pragma intrinsic(_InterlockedExchangeAdd64)
65 namespace __sanitizer {
67 INLINE void atomic_signal_fence(memory_order) {
71 INLINE void atomic_thread_fence(memory_order) {
75 INLINE void proc_yield(int cnt) {
76 for (int i = 0; i < cnt; i++)
81 INLINE typename T::Type atomic_load(
82 const volatile T *a, memory_order mo) {
83 DCHECK(mo & (memory_order_relaxed | memory_order_consume
84 | memory_order_acquire | memory_order_seq_cst));
85 DCHECK(!((uptr)a % sizeof(*a)));
87 // FIXME(dvyukov): 64-bit load is not atomic on 32-bits.
88 if (mo == memory_order_relaxed) {
91 atomic_signal_fence(memory_order_seq_cst);
93 atomic_signal_fence(memory_order_seq_cst);
99 INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
100 DCHECK(mo & (memory_order_relaxed | memory_order_release
101 | memory_order_seq_cst));
102 DCHECK(!((uptr)a % sizeof(*a)));
103 // FIXME(dvyukov): 64-bit store is not atomic on 32-bits.
104 if (mo == memory_order_relaxed) {
107 atomic_signal_fence(memory_order_seq_cst);
109 atomic_signal_fence(memory_order_seq_cst);
111 if (mo == memory_order_seq_cst)
112 atomic_thread_fence(memory_order_seq_cst);
115 INLINE u32 atomic_fetch_add(volatile atomic_uint32_t *a,
116 u32 v, memory_order mo) {
118 DCHECK(!((uptr)a % sizeof(*a)));
119 return (u32)_InterlockedExchangeAdd(
120 (volatile long*)&a->val_dont_use, (long)v); // NOLINT
123 INLINE uptr atomic_fetch_add(volatile atomic_uintptr_t *a,
124 uptr v, memory_order mo) {
126 DCHECK(!((uptr)a % sizeof(*a)));
128 return (uptr)_InterlockedExchangeAdd64(
129 (volatile long long*)&a->val_dont_use, (long long)v); // NOLINT
131 return (uptr)_InterlockedExchangeAdd(
132 (volatile long*)&a->val_dont_use, (long)v); // NOLINT
136 INLINE u32 atomic_fetch_sub(volatile atomic_uint32_t *a,
137 u32 v, memory_order mo) {
139 DCHECK(!((uptr)a % sizeof(*a)));
140 return (u32)_InterlockedExchangeAdd(
141 (volatile long*)&a->val_dont_use, -(long)v); // NOLINT
144 INLINE uptr atomic_fetch_sub(volatile atomic_uintptr_t *a,
145 uptr v, memory_order mo) {
147 DCHECK(!((uptr)a % sizeof(*a)));
149 return (uptr)_InterlockedExchangeAdd64(
150 (volatile long long*)&a->val_dont_use, -(long long)v); // NOLINT
152 return (uptr)_InterlockedExchangeAdd(
153 (volatile long*)&a->val_dont_use, -(long)v); // NOLINT
157 INLINE u8 atomic_exchange(volatile atomic_uint8_t *a,
158 u8 v, memory_order mo) {
160 DCHECK(!((uptr)a % sizeof(*a)));
161 return (u8)_InterlockedExchange8((volatile char*)&a->val_dont_use, v);
164 INLINE u16 atomic_exchange(volatile atomic_uint16_t *a,
165 u16 v, memory_order mo) {
167 DCHECK(!((uptr)a % sizeof(*a)));
168 return (u16)_InterlockedExchange16((volatile short*)&a->val_dont_use, v);
171 INLINE u32 atomic_exchange(volatile atomic_uint32_t *a,
172 u32 v, memory_order mo) {
174 DCHECK(!((uptr)a % sizeof(*a)));
175 return (u32)_InterlockedExchange((volatile long*)&a->val_dont_use, v);
178 INLINE bool atomic_compare_exchange_strong(volatile atomic_uint8_t *a,
183 DCHECK(!((uptr)a % sizeof(*a)));
186 u8 prev = (u8)_InterlockedCompareExchange8(
187 (volatile char*)&a->val_dont_use, (char)xchgv, (char)cmpv);
194 lock cmpxchg [ecx], dl
204 INLINE bool atomic_compare_exchange_strong(volatile atomic_uintptr_t *a,
209 uptr prev = (uptr)_InterlockedCompareExchangePointer(
210 (void*volatile*)&a->val_dont_use, (void*)xchg, (void*)cmpv);
217 INLINE bool atomic_compare_exchange_strong(volatile atomic_uint16_t *a,
222 u16 prev = (u16)_InterlockedCompareExchange16(
223 (volatile short*)&a->val_dont_use, (short)xchg, (short)cmpv);
230 INLINE bool atomic_compare_exchange_strong(volatile atomic_uint32_t *a,
235 u32 prev = (u32)_InterlockedCompareExchange(
236 (volatile long*)&a->val_dont_use, (long)xchg, (long)cmpv);
243 INLINE bool atomic_compare_exchange_strong(volatile atomic_uint64_t *a,
248 u64 prev = (u64)_InterlockedCompareExchange64(
249 (volatile long long*)&a->val_dont_use, (long long)xchg, (long long)cmpv);
257 INLINE bool atomic_compare_exchange_weak(volatile T *a,
258 typename T::Type *cmp,
259 typename T::Type xchg,
261 return atomic_compare_exchange_strong(a, cmp, xchg, mo);
264 } // namespace __sanitizer
266 #endif // SANITIZER_ATOMIC_CLANG_H