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