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