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/config.h" 16#if defined(ANDROID_TARGET_BUILD) 17# include "sys/atomics.h" 18#endif 19 20using namespace llvm; 21 22#if defined(_MSC_VER) 23#include <windows.h> 24#undef MemoryFence 25#endif 26 27void 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 41sys::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 60sys::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 75sys::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 90sys::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 110sys::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 120sys::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