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