1 //===-- sanitizer_atomic_clang.h --------------------------------*- C++ -*-===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
9 // Not intended for direct inclusion. Include sanitizer_atomic.h.
11 //===----------------------------------------------------------------------===//
13 #ifndef SANITIZER_ATOMIC_CLANG_H
14 #define SANITIZER_ATOMIC_CLANG_H
16 namespace __sanitizer
{
18 INLINE
void atomic_signal_fence(memory_order
) {
19 __asm__
__volatile__("" ::: "memory");
22 INLINE
void atomic_thread_fence(memory_order
) {
26 INLINE
void proc_yield(int cnt
) {
27 __asm__
__volatile__("" ::: "memory");
28 #if defined(__i386__) || defined(__x86_64__)
29 for (int i
= 0; i
< cnt
; i
++)
30 __asm__
__volatile__("pause");
32 __asm__
__volatile__("" ::: "memory");
36 INLINE 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
)));
42 if (mo
== memory_order_relaxed
) {
45 atomic_signal_fence(memory_order_seq_cst
);
47 atomic_signal_fence(memory_order_seq_cst
);
53 INLINE
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
) {
60 atomic_signal_fence(memory_order_seq_cst
);
62 atomic_signal_fence(memory_order_seq_cst
);
64 if (mo
== memory_order_seq_cst
)
65 atomic_thread_fence(memory_order_seq_cst
);
69 INLINE typename
T::Type
atomic_fetch_add(volatile T
*a
,
70 typename
T::Type v
, memory_order mo
) {
72 DCHECK(!((uptr
)a
% sizeof(*a
)));
73 return __sync_fetch_and_add(&a
->val_dont_use
, v
);
77 INLINE typename
T::Type
atomic_fetch_sub(volatile T
*a
,
78 typename
T::Type v
, memory_order mo
) {
80 DCHECK(!((uptr
)a
% sizeof(*a
)));
81 return __sync_fetch_and_add(&a
->val_dont_use
, -v
);
85 INLINE typename
T::Type
atomic_exchange(volatile T
*a
,
86 typename
T::Type v
, memory_order mo
) {
87 DCHECK(!((uptr
)a
% sizeof(*a
)));
88 if (mo
& (memory_order_release
| memory_order_acq_rel
| memory_order_seq_cst
))
90 v
= __sync_lock_test_and_set(&a
->val_dont_use
, v
);
91 if (mo
== memory_order_seq_cst
)
97 INLINE
bool atomic_compare_exchange_strong(volatile T
*a
,
98 typename
T::Type
*cmp
,
99 typename
T::Type xchg
,
101 typedef typename
T::Type Type
;
103 Type prev
= __sync_val_compare_and_swap(&a
->val_dont_use
, cmpv
, xchg
);
111 INLINE
bool atomic_compare_exchange_weak(volatile T
*a
,
112 typename
T::Type
*cmp
,
113 typename
T::Type xchg
,
115 return atomic_compare_exchange_strong(a
, cmp
, xchg
, mo
);
118 } // namespace __sanitizer
120 #endif // SANITIZER_ATOMIC_CLANG_H