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 17 using 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 28 void 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 42 sys::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 59 sys::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 72 sys::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 85 sys::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 98 sys::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 108 sys::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