LLVM API Documentation
00001 //===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements atomic operations. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/Support/Atomic.h" 00015 #include "llvm/Config/llvm-config.h" 00016 00017 using namespace llvm; 00018 00019 #if defined(_MSC_VER) 00020 #include <Intrin.h> 00021 #include <windows.h> 00022 #undef MemoryFence 00023 #endif 00024 00025 #if defined(__GNUC__) || (defined(__IBMCPP__) && __IBMCPP__ >= 1210) 00026 #define GNU_ATOMICS 00027 #endif 00028 00029 void sys::MemoryFence() { 00030 #if LLVM_HAS_ATOMICS == 0 00031 return; 00032 #else 00033 # if defined(GNU_ATOMICS) 00034 __sync_synchronize(); 00035 # elif defined(_MSC_VER) 00036 MemoryBarrier(); 00037 # else 00038 # error No memory fence implementation for your platform! 00039 # endif 00040 #endif 00041 } 00042 00043 sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, 00044 sys::cas_flag new_value, 00045 sys::cas_flag old_value) { 00046 #if LLVM_HAS_ATOMICS == 0 00047 sys::cas_flag result = *ptr; 00048 if (result == old_value) 00049 *ptr = new_value; 00050 return result; 00051 #elif defined(GNU_ATOMICS) 00052 return __sync_val_compare_and_swap(ptr, old_value, new_value); 00053 #elif defined(_MSC_VER) 00054 return InterlockedCompareExchange(ptr, new_value, old_value); 00055 #else 00056 # error No compare-and-swap implementation for your platform! 00057 #endif 00058 } 00059 00060 sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) { 00061 #if LLVM_HAS_ATOMICS == 0 00062 ++(*ptr); 00063 return *ptr; 00064 #elif defined(GNU_ATOMICS) 00065 return __sync_add_and_fetch(ptr, 1); 00066 #elif defined(_MSC_VER) 00067 return InterlockedIncrement(ptr); 00068 #else 00069 # error No atomic increment implementation for your platform! 00070 #endif 00071 } 00072 00073 sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) { 00074 #if LLVM_HAS_ATOMICS == 0 00075 --(*ptr); 00076 return *ptr; 00077 #elif defined(GNU_ATOMICS) 00078 return __sync_sub_and_fetch(ptr, 1); 00079 #elif defined(_MSC_VER) 00080 return InterlockedDecrement(ptr); 00081 #else 00082 # error No atomic decrement implementation for your platform! 00083 #endif 00084 } 00085 00086 sys::cas_flag sys::AtomicAdd(volatile sys::cas_flag* ptr, sys::cas_flag val) { 00087 #if LLVM_HAS_ATOMICS == 0 00088 *ptr += val; 00089 return *ptr; 00090 #elif defined(GNU_ATOMICS) 00091 return __sync_add_and_fetch(ptr, val); 00092 #elif defined(_MSC_VER) 00093 return InterlockedExchangeAdd(ptr, val) + val; 00094 #else 00095 # error No atomic add implementation for your platform! 00096 #endif 00097 } 00098 00099 sys::cas_flag sys::AtomicMul(volatile sys::cas_flag* ptr, sys::cas_flag val) { 00100 sys::cas_flag original, result; 00101 do { 00102 original = *ptr; 00103 result = original * val; 00104 } while (sys::CompareAndSwap(ptr, result, original) != original); 00105 00106 return result; 00107 } 00108 00109 sys::cas_flag sys::AtomicDiv(volatile sys::cas_flag* ptr, sys::cas_flag val) { 00110 sys::cas_flag original, result; 00111 do { 00112 original = *ptr; 00113 result = original / val; 00114 } while (sys::CompareAndSwap(ptr, result, original) != original); 00115 00116 return result; 00117 }