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 17 using namespace llvm; 18 19 #if defined(_MSC_VER) 20 #include <windows.h> 21 #undef MemoryFence 22 #endif 23 24 void 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 38 sys::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 55 sys::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 68 sys::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 81 sys::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 94 sys::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 104 sys::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