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 "cutils/atomic.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 android_atomic_cmpxchg((int32_t)old_value, (int32_t)new_value, 51 (volatile int*)ptr); 52 #elif defined(__GNUC__) 53 return __sync_val_compare_and_swap(ptr, old_value, new_value); 54 #elif defined(_MSC_VER) 55 return InterlockedCompareExchange(ptr, new_value, old_value); 56 #else 57 # error No compare-and-swap implementation for your platform! 58 #endif 59 } 60 61 sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) { 62 #if LLVM_HAS_ATOMICS == 0 63 ++(*ptr); 64 return *ptr; 65 #elif defined(ANDROID_TARGET_BUILD) 66 return android_atomic_inc((volatile int*)ptr); 67 #elif defined(__GNUC__) 68 return __sync_add_and_fetch(ptr, 1); 69 #elif defined(_MSC_VER) 70 return InterlockedIncrement(ptr); 71 #else 72 # error No atomic increment implementation for your platform! 73 #endif 74 } 75 76 sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) { 77 #if LLVM_HAS_ATOMICS == 0 78 --(*ptr); 79 return *ptr; 80 #elif defined(ANDROID_TARGET_BUILD) 81 return android_atomic_dec((volatile int*)ptr); 82 #elif defined(__GNUC__) 83 return __sync_sub_and_fetch(ptr, 1); 84 #elif defined(_MSC_VER) 85 return InterlockedDecrement(ptr); 86 #else 87 # error No atomic decrement implementation for your platform! 88 #endif 89 } 90 91 sys::cas_flag sys::AtomicAdd(volatile sys::cas_flag* ptr, sys::cas_flag val) { 92 #if LLVM_HAS_ATOMICS == 0 93 *ptr += val; 94 return *ptr; 95 #elif defined(ANDROID_TARGET_BUILD) 96 return android_atomic_add((int32_t)val, (volatile int*)ptr); 97 #elif defined(__GNUC__) 98 return __sync_add_and_fetch(ptr, val); 99 #elif defined(_MSC_VER) 100 return InterlockedExchangeAdd(ptr, val) + val; 101 #else 102 # error No atomic add implementation for your platform! 103 #endif 104 } 105 106 sys::cas_flag sys::AtomicMul(volatile sys::cas_flag* ptr, sys::cas_flag val) { 107 sys::cas_flag original, result; 108 do { 109 original = *ptr; 110 result = original * val; 111 } while (sys::CompareAndSwap(ptr, result, original) != original); 112 113 return result; 114 } 115 116 sys::cas_flag sys::AtomicDiv(volatile sys::cas_flag* ptr, sys::cas_flag val) { 117 sys::cas_flag original, result; 118 do { 119 original = *ptr; 120 result = original / val; 121 } while (sys::CompareAndSwap(ptr, result, original) != original); 122 123 return result; 124 } 125