12754fe60SDimitry Andric //===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===// 22754fe60SDimitry Andric // 32754fe60SDimitry Andric // The LLVM Compiler Infrastructure 42754fe60SDimitry Andric // 52754fe60SDimitry Andric // This file is distributed under the University of Illinois Open Source 62754fe60SDimitry Andric // License. See LICENSE.TXT for details. 72754fe60SDimitry Andric // 82754fe60SDimitry Andric //===----------------------------------------------------------------------===// 92754fe60SDimitry Andric // 102754fe60SDimitry Andric // This file implements atomic operations. 112754fe60SDimitry Andric // 122754fe60SDimitry Andric //===----------------------------------------------------------------------===// 132754fe60SDimitry Andric 142754fe60SDimitry Andric #include "llvm/Support/Atomic.h" 152754fe60SDimitry Andric #include "llvm/Config/llvm-config.h" 162754fe60SDimitry Andric 172754fe60SDimitry Andric using namespace llvm; 182754fe60SDimitry Andric 192754fe60SDimitry Andric #if defined(_MSC_VER) 202754fe60SDimitry Andric #include <intrin.h> 212754fe60SDimitry Andric 222754fe60SDimitry Andric // We must include windows.h after intrin.h. 232754fe60SDimitry Andric #include <windows.h> 242754fe60SDimitry Andric #undef MemoryFence 25*86b360adSDimitry Andric #endif 262754fe60SDimitry Andric 272754fe60SDimitry Andric #if defined(__GNUC__) || (defined(__IBMCPP__) && __IBMCPP__ >= 1210) 282754fe60SDimitry Andric #define GNU_ATOMICS 292754fe60SDimitry Andric #endif 302754fe60SDimitry Andric MemoryFence()312754fe60SDimitry Andricvoid sys::MemoryFence() { 322754fe60SDimitry Andric #if LLVM_HAS_ATOMICS == 0 332754fe60SDimitry Andric return; 342754fe60SDimitry Andric #else 352754fe60SDimitry Andric # if defined(GNU_ATOMICS) 362754fe60SDimitry Andric __sync_synchronize(); 372754fe60SDimitry Andric # elif defined(_MSC_VER) 382754fe60SDimitry Andric MemoryBarrier(); 392754fe60SDimitry Andric # else 402754fe60SDimitry Andric # error No memory fence implementation for your platform! 41*86b360adSDimitry Andric # endif 422754fe60SDimitry Andric #endif 432754fe60SDimitry Andric } 442754fe60SDimitry Andric CompareAndSwap(volatile sys::cas_flag * ptr,sys::cas_flag new_value,sys::cas_flag old_value)452754fe60SDimitry Andricsys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, 462754fe60SDimitry Andric sys::cas_flag new_value, 472754fe60SDimitry Andric sys::cas_flag old_value) { 482754fe60SDimitry Andric #if LLVM_HAS_ATOMICS == 0 492754fe60SDimitry Andric sys::cas_flag result = *ptr; 502754fe60SDimitry Andric if (result == old_value) 512754fe60SDimitry Andric *ptr = new_value; 522754fe60SDimitry Andric return result; 532754fe60SDimitry Andric #elif defined(GNU_ATOMICS) 542754fe60SDimitry Andric return __sync_val_compare_and_swap(ptr, old_value, new_value); 552754fe60SDimitry Andric #elif defined(_MSC_VER) 56*86b360adSDimitry Andric return InterlockedCompareExchange(ptr, new_value, old_value); 572754fe60SDimitry Andric #else 582754fe60SDimitry Andric # error No compare-and-swap implementation for your platform! 592754fe60SDimitry Andric #endif 602754fe60SDimitry Andric } 612754fe60SDimitry Andric