blob: d7d59297c5ee2540370a056d1e348a5c6232e86c [file] [log] [blame]
Dmitry Vyukove8cee122012-06-29 18:00:38 +00001//===-- 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
Dmitry Vyukov3c5c9e72012-06-29 18:37:45 +000018extern "C" void _ReadWriteBarrier();
Dmitry Vyukovb379fe52012-06-29 18:28:02 +000019#pragma intrinsic(_ReadWriteBarrier)
Dmitry Vyukov3c5c9e72012-06-29 18:37:45 +000020extern "C" void _mm_mfence();
Dmitry Vyukovb379fe52012-06-29 18:28:02 +000021#pragma intrinsic(_mm_mfence)
Dmitry Vyukov3c5c9e72012-06-29 18:37:45 +000022extern "C" void _mm_pause();
Dmitry Vyukovb379fe52012-06-29 18:28:02 +000023#pragma intrinsic(_mm_pause)
Dmitry Vyukov3c5c9e72012-06-29 18:37:45 +000024extern "C" long _InterlockedExchangeAdd( // NOLINT
25 long volatile * Addend, long Value); // NOLINT
Dmitry Vyukovb379fe52012-06-29 18:28:02 +000026#pragma intrinsic(_InterlockedExchangeAdd)
Dmitry Vyukov179e5dda2012-08-31 14:11:33 +000027extern "C" void *InterlockedCompareExchangePointer(
Dmitry Vyukovfa90fa32012-08-31 14:01:33 +000028 void *volatile *Destination,
29 void *Exchange, void *Comparand);
Dmitry Vyukove8cee122012-06-29 18:00:38 +000030
31namespace __sanitizer {
32
33INLINE void atomic_signal_fence(memory_order) {
34 _ReadWriteBarrier();
35}
36
37INLINE void atomic_thread_fence(memory_order) {
38 _mm_mfence();
39}
40
41INLINE void proc_yield(int cnt) {
42 for (int i = 0; i < cnt; i++)
43 _mm_pause();
44}
45
46template<typename T>
47INLINE typename T::Type atomic_load(
48 const volatile T *a, memory_order mo) {
49 DCHECK(mo & (memory_order_relaxed | memory_order_consume
50 | memory_order_acquire | memory_order_seq_cst));
51 DCHECK(!((uptr)a % sizeof(*a)));
52 typename T::Type v;
53 if (mo == memory_order_relaxed) {
54 v = a->val_dont_use;
55 } else {
56 atomic_signal_fence(memory_order_seq_cst);
57 v = a->val_dont_use;
58 atomic_signal_fence(memory_order_seq_cst);
59 }
60 return v;
61}
62
63template<typename T>
64INLINE 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 if (mo == memory_order_relaxed) {
69 a->val_dont_use = v;
70 } else {
71 atomic_signal_fence(memory_order_seq_cst);
72 a->val_dont_use = v;
73 atomic_signal_fence(memory_order_seq_cst);
74 }
75 if (mo == memory_order_seq_cst)
76 atomic_thread_fence(memory_order_seq_cst);
77}
78
79INLINE u32 atomic_fetch_add(volatile atomic_uint32_t *a,
80 u32 v, memory_order mo) {
81 (void)mo;
82 DCHECK(!((uptr)a % sizeof(*a)));
83 return (u32)_InterlockedExchangeAdd(
84 (volatile long*)&a->val_dont_use, (long)v); // NOLINT
85}
86
87INLINE u8 atomic_exchange(volatile atomic_uint8_t *a,
88 u8 v, memory_order mo) {
89 (void)mo;
90 DCHECK(!((uptr)a % sizeof(*a)));
91 __asm {
92 mov eax, a
Dmitry Vyukovb379fe52012-06-29 18:28:02 +000093 mov cl, v
94 xchg [eax], cl // NOLINT
95 mov v, cl
Dmitry Vyukove8cee122012-06-29 18:00:38 +000096 }
97 return v;
98}
99
100INLINE u16 atomic_exchange(volatile atomic_uint16_t *a,
101 u16 v, memory_order mo) {
102 (void)mo;
103 DCHECK(!((uptr)a % sizeof(*a)));
104 __asm {
105 mov eax, a
Dmitry Vyukovb379fe52012-06-29 18:28:02 +0000106 mov cx, v
107 xchg [eax], cx // NOLINT
108 mov v, cx
Dmitry Vyukove8cee122012-06-29 18:00:38 +0000109 }
110 return v;
111}
112
Dmitry Vyukov179e5dda2012-08-31 14:11:33 +0000113INLINE bool atomic_compare_exchange_strong(volatile atomic_uintptr_t *a,
Dmitry Vyukovfa90fa32012-08-31 14:01:33 +0000114 uptr *cmp,
115 uptr xchg,
116 memory_order mo) {
117 uptr cmpv = *cmp;
Dmitry Vyukov179e5dda2012-08-31 14:11:33 +0000118 uptr prev = (uptr)InterlockedCompareExchangePointer(
Dmitry Vyukovfa90fa32012-08-31 14:01:33 +0000119 (void*volatile*)&a->val_dont_use, (void*)xchg, (void*)cmpv);
120 if (prev == cmpv)
121 return true;
122 *cmp = prev;
123 return false;
124}
125
126template<typename T>
127INLINE bool atomic_compare_exchange_weak(volatile T *a,
128 typename T::Type *cmp,
129 typename T::Type xchg,
130 memory_order mo) {
131 return atomic_compare_exchange_strong(a, cmp, xchg, mo);
132}
133
Dmitry Vyukove8cee122012-06-29 18:00:38 +0000134} // namespace __sanitizer
135
136#endif // SANITIZER_ATOMIC_CLANG_H