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 // FIXME(dvyukov): 64-bit load is not atomic on 32-bits.
43 if (mo
== memory_order_relaxed
) {
46 atomic_signal_fence(memory_order_seq_cst
);
48 atomic_signal_fence(memory_order_seq_cst
);
54 INLINE
void atomic_store(volatile T
*a
, typename
T::Type v
, memory_order mo
) {
55 DCHECK(mo
& (memory_order_relaxed
| memory_order_release
56 | memory_order_seq_cst
));
57 DCHECK(!((uptr
)a
% sizeof(*a
)));
58 // FIXME(dvyukov): 64-bit store is not atomic on 32-bits.
59 if (mo
== memory_order_relaxed
) {
62 atomic_signal_fence(memory_order_seq_cst
);
64 atomic_signal_fence(memory_order_seq_cst
);
66 if (mo
== memory_order_seq_cst
)
67 atomic_thread_fence(memory_order_seq_cst
);
71 INLINE typename
T::Type
atomic_fetch_add(volatile T
*a
,
72 typename
T::Type v
, memory_order mo
) {
74 DCHECK(!((uptr
)a
% sizeof(*a
)));
75 return __sync_fetch_and_add(&a
->val_dont_use
, v
);
79 INLINE typename
T::Type
atomic_fetch_sub(volatile T
*a
,
80 typename
T::Type v
, memory_order mo
) {
82 DCHECK(!((uptr
)a
% sizeof(*a
)));
83 return __sync_fetch_and_add(&a
->val_dont_use
, -v
);
87 INLINE typename
T::Type
atomic_exchange(volatile T
*a
,
88 typename
T::Type v
, memory_order mo
) {
89 DCHECK(!((uptr
)a
% sizeof(*a
)));
90 if (mo
& (memory_order_release
| memory_order_acq_rel
| memory_order_seq_cst
))
92 v
= __sync_lock_test_and_set(&a
->val_dont_use
, v
);
93 if (mo
== memory_order_seq_cst
)
99 INLINE
bool atomic_compare_exchange_strong(volatile T
*a
,
100 typename
T::Type
*cmp
,
101 typename
T::Type xchg
,
103 typedef typename
T::Type Type
;
105 Type prev
= __sync_val_compare_and_swap(&a
->val_dont_use
, cmpv
, xchg
);
113 INLINE
bool atomic_compare_exchange_weak(volatile T
*a
,
114 typename
T::Type
*cmp
,
115 typename
T::Type xchg
,
117 return atomic_compare_exchange_strong(a
, cmp
, xchg
, mo
);
120 } // namespace __sanitizer
122 #endif // SANITIZER_ATOMIC_CLANG_H