sanitizer_atomic.h revision a3eca8192505f4796194dd24eb051019f402de99
1//===-- sanitizer_atomic.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// 12//===----------------------------------------------------------------------===// 13 14#ifndef SANITIZER_ATOMIC_H 15#define SANITIZER_ATOMIC_H 16 17#include "sanitizer_internal_defs.h" 18 19namespace __sanitizer { 20 21enum memory_order { 22 memory_order_relaxed = 1 << 0, 23 memory_order_consume = 1 << 1, 24 memory_order_acquire = 1 << 2, 25 memory_order_release = 1 << 3, 26 memory_order_acq_rel = 1 << 4, 27 memory_order_seq_cst = 1 << 5, 28}; 29 30struct atomic_uint8_t { 31 typedef u8 Type; 32 volatile Type val_dont_use; 33}; 34 35struct atomic_uint16_t { 36 typedef u16 Type; 37 volatile Type val_dont_use; 38}; 39 40struct atomic_uint32_t { 41 typedef u32 Type; 42 volatile Type val_dont_use; 43}; 44 45struct atomic_uint64_t { 46 typedef u64 Type; 47 volatile Type val_dont_use; 48}; 49 50struct atomic_uintptr_t { 51 typedef uptr Type; 52 volatile Type val_dont_use; 53}; 54 55INLINE void atomic_signal_fence(memory_order) { 56 __asm__ __volatile__("" ::: "memory"); 57} 58 59INLINE void atomic_thread_fence(memory_order) { 60 __sync_synchronize(); 61} 62 63INLINE void proc_yield(int cnt) { 64 __asm__ __volatile__("" ::: "memory"); 65#if defined(__i386__) || defined(__x86_64__) 66 for (int i = 0; i < cnt; i++) 67 __asm__ __volatile__("pause"); 68#endif 69 __asm__ __volatile__("" ::: "memory"); 70} 71 72template<typename T> 73INLINE typename T::Type atomic_load( 74 const volatile T *a, memory_order mo) { 75 DCHECK(mo & (memory_order_relaxed | memory_order_consume 76 | memory_order_acquire | memory_order_seq_cst)); 77 DCHECK(!((uptr)a % sizeof(*a))); 78 typename T::Type v; 79 if (mo == memory_order_relaxed) { 80 v = a->val_dont_use; 81 } else { 82 atomic_signal_fence(memory_order_seq_cst); 83 v = a->val_dont_use; 84 atomic_signal_fence(memory_order_seq_cst); 85 } 86 return v; 87} 88 89template<typename T> 90INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { 91 DCHECK(mo & (memory_order_relaxed | memory_order_release 92 | memory_order_seq_cst)); 93 DCHECK(!((uptr)a % sizeof(*a))); 94 if (mo == memory_order_relaxed) { 95 a->val_dont_use = v; 96 } else { 97 atomic_signal_fence(memory_order_seq_cst); 98 a->val_dont_use = v; 99 atomic_signal_fence(memory_order_seq_cst); 100 } 101 if (mo == memory_order_seq_cst) 102 atomic_thread_fence(memory_order_seq_cst); 103} 104 105template<typename T> 106INLINE typename T::Type atomic_fetch_add(volatile T *a, 107 typename T::Type v, memory_order mo) { 108 (void)mo; 109 DCHECK(!((uptr)a % sizeof(*a))); 110 return __sync_fetch_and_add(&a->val_dont_use, v); 111} 112 113template<typename T> 114INLINE typename T::Type atomic_fetch_sub(volatile T *a, 115 typename T::Type v, memory_order mo) { 116 (void)mo; 117 DCHECK(!((uptr)a % sizeof(*a))); 118 return __sync_fetch_and_add(&a->val_dont_use, -v); 119} 120 121template<typename T> 122INLINE typename T::Type atomic_exchange(volatile T *a, 123 typename T::Type v, memory_order mo) { 124 DCHECK(!((uptr)a % sizeof(*a))); 125 if (mo & (memory_order_release | memory_order_acq_rel | memory_order_seq_cst)) 126 __sync_synchronize(); 127 v = __sync_lock_test_and_set(&a->val_dont_use, v); 128 if (mo == memory_order_seq_cst) 129 __sync_synchronize(); 130 return v; 131} 132 133template<typename T> 134INLINE bool atomic_compare_exchange_strong(volatile T *a, 135 typename T::Type *cmp, 136 typename T::Type xchg, 137 memory_order mo) { 138 typedef typename T::Type Type; 139 Type cmpv = *cmp; 140 Type prev = __sync_val_compare_and_swap(&a->val_dont_use, cmpv, xchg); 141 if (prev == cmpv) 142 return true; 143 *cmp = prev; 144 return false; 145} 146 147template<typename T> 148INLINE bool atomic_compare_exchange_weak(volatile T *a, 149 typename T::Type *cmp, 150 typename T::Type xchg, 151 memory_order mo) { 152 return atomic_compare_exchange_strong(a, cmp, xchg, mo); 153} 154 155} // namespace __sanitizer 156 157#endif // SANITIZER_ATOMIC_H 158