1 //===-- Atomic.cpp - Atomic Operations --------------------------*- 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 header file implements atomic operations. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Support/Atomic.h" 15 #include "llvm/Config/llvm-config.h" 16 #if defined(ANDROID_TARGET_BUILD) 17 # include "sys/atomics.h" 18 #endif 19 20 using namespace llvm; 21 22 #if defined(_MSC_VER) 23 #include <windows.h> 24 #undef MemoryFence 25 #endif 26 27 void sys::MemoryFence() { 28 #if LLVM_HAS_ATOMICS == 0 29 return; 30 #else 31 # if defined(__GNUC__) 32 __sync_synchronize(); 33 # elif defined(_MSC_VER) 34 MemoryBarrier(); 35 # else 36 # error No memory fence implementation for your platform! 37 # endif 38 #endif 39 } 40 41 sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, 42 sys::cas_flag new_value, 43 sys::cas_flag old_value) { 44 #if LLVM_HAS_ATOMICS == 0 45 sys::cas_flag result = *ptr; 46 if (result == old_value) 47 *ptr = new_value; 48 return result; 49 #elif defined(ANDROID_TARGET_BUILD) 50 return __atomic_cmpxchg(old_value, new_value, (volatile int*)ptr); 51 #elif defined(__GNUC__) 52 return __sync_val_compare_and_swap(ptr, old_value, new_value); 53 #elif defined(_MSC_VER) 54 return InterlockedCompareExchange(ptr, new_value, old_value); 55 #else 56 # error No compare-and-swap implementation for your platform! 57 #endif 58 } 59 60 sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) { 61 #if LLVM_HAS_ATOMICS == 0 62 ++(*ptr); 63 return *ptr; 64 #elif defined(ANDROID_TARGET_BUILD) 65 return __atomic_inc((volatile int*)ptr); 66 #elif defined(__GNUC__) 67 return __sync_add_and_fetch(ptr, 1); 68 #elif defined(_MSC_VER) 69 return InterlockedIncrement(ptr); 70 #else 71 # error No atomic increment implementation for your platform! 72 #endif 73 } 74 75 sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) { 76 #if LLVM_HAS_ATOMICS == 0 77 --(*ptr); 78 return *ptr; 79 #elif defined(ANDROID_TARGET_BUILD) 80 return __atomic_dec((volatile int*)ptr); 81 #elif defined(__GNUC__) 82 return __sync_sub_and_fetch(ptr, 1); 83 #elif defined(_MSC_VER) 84 return InterlockedDecrement(ptr); 85 #else 86 # error No atomic decrement implementation for your platform! 87 #endif 88 } 89 90 sys::cas_flag sys::AtomicAdd(volatile sys::cas_flag* ptr, sys::cas_flag val) { 91 #if LLVM_HAS_ATOMICS == 0 92 *ptr += val; 93 return *ptr; 94 #elif defined(ANDROID_TARGET_BUILD) 95 sys::cas_flag original, result; 96 do { 97 original = *ptr; 98 result = original + val; 99 } while (__atomic_cmpxchg(original, result, (volatile int*)ptr) != original); 100 return result; 101 #elif defined(__GNUC__) 102 return __sync_add_and_fetch(ptr, val); 103 #elif defined(_MSC_VER) 104 return InterlockedExchangeAdd(ptr, val) + val; 105 #else 106 # error No atomic add implementation for your platform! 107 #endif 108 } 109 110 sys::cas_flag sys::AtomicMul(volatile sys::cas_flag* ptr, sys::cas_flag val) { 111 sys::cas_flag original, result; 112 do { 113 original = *ptr; 114 result = original * val; 115 } while (sys::CompareAndSwap(ptr, result, original) != original); 116 117 return result; 118 } 119 120 sys::cas_flag sys::AtomicDiv(volatile sys::cas_flag* ptr, sys::cas_flag val) { 121 sys::cas_flag original, result; 122 do { 123 original = *ptr; 124 result = original / val; 125 } while (sys::CompareAndSwap(ptr, result, original) != original); 126 127 return result; 128 } 129