sanitizer_atomic_msvc.h revision b6eb56f5a03b4dba8de79465274a73d1ecbca7f2
1//===-- sanitizer_atomic_msvc.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_MSVC_H 16#define SANITIZER_ATOMIC_MSVC_H 17 18#include <intrin.h> 19 20namespace __sanitizer { 21 22INLINE void atomic_signal_fence(memory_order) { 23 _ReadWriteBarrier(); 24} 25 26INLINE void atomic_thread_fence(memory_order) { 27 _mm_mfence(); 28} 29 30INLINE void proc_yield(int cnt) { 31 for (int i = 0; i < cnt; i++) 32 _mm_pause(); 33} 34 35template<typename T> 36INLINE typename T::Type atomic_load( 37 const volatile T *a, memory_order mo) { 38 DCHECK(mo & (memory_order_relaxed | memory_order_consume 39 | memory_order_acquire | memory_order_seq_cst)); 40 DCHECK(!((uptr)a % sizeof(*a))); 41 typename T::Type v; 42 if (mo == memory_order_relaxed) { 43 v = a->val_dont_use; 44 } else { 45 atomic_signal_fence(memory_order_seq_cst); 46 v = a->val_dont_use; 47 atomic_signal_fence(memory_order_seq_cst); 48 } 49 return v; 50} 51 52template<typename T> 53INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { 54 DCHECK(mo & (memory_order_relaxed | memory_order_release 55 | memory_order_seq_cst)); 56 DCHECK(!((uptr)a % sizeof(*a))); 57 if (mo == memory_order_relaxed) { 58 a->val_dont_use = v; 59 } else { 60 atomic_signal_fence(memory_order_seq_cst); 61 a->val_dont_use = v; 62 atomic_signal_fence(memory_order_seq_cst); 63 } 64 if (mo == memory_order_seq_cst) 65 atomic_thread_fence(memory_order_seq_cst); 66} 67 68INLINE u32 atomic_fetch_add(volatile atomic_uint32_t *a, 69 u32 v, memory_order mo) { 70 (void)mo; 71 DCHECK(!((uptr)a % sizeof(*a))); 72 return (u32)_InterlockedExchangeAdd( 73 (volatile long*)&a->val_dont_use, (long)v); // NOLINT 74} 75 76INLINE u8 atomic_exchange(volatile atomic_uint8_t *a, 77 u8 v, memory_order mo) { 78 (void)mo; 79 DCHECK(!((uptr)a % sizeof(*a))); 80 __asm { 81 mov eax, a 82 mov cx, v 83 xchg [eax], cx // NOLINT 84 mov v, cx 85 } 86 return v; 87} 88 89INLINE u16 atomic_exchange(volatile atomic_uint16_t *a, 90 u16 v, memory_order mo) { 91 (void)mo; 92 DCHECK(!((uptr)a % sizeof(*a))); 93 __asm { 94 mov eax, a 95 mov cl, v 96 xchg [eax], cl // NOLINT 97 mov v, cl 98 } 99 return v; 100} 101 102} // namespace __sanitizer 103 104#endif // SANITIZER_ATOMIC_CLANG_H 105