1447762daSMichael J. Spencer //===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===// 2447762daSMichael J. Spencer // 3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6447762daSMichael J. Spencer // 7447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 8447762daSMichael J. Spencer // 9cfe341f5SHans Wennborg // This file implements atomic operations. 10447762daSMichael J. Spencer // 11447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 12447762daSMichael J. Spencer 13447762daSMichael J. Spencer #include "llvm/Support/Atomic.h" 149e5b178eSDylan Noblesmith #include "llvm/Config/llvm-config.h" 15447762daSMichael J. Spencer 16447762daSMichael J. Spencer using namespace llvm; 17447762daSMichael J. Spencer 18447762daSMichael J. Spencer #if defined(_MSC_VER) 190a920e76SNico Weber #include <intrin.h> 20aaeada6cSChandler Carruth 210a920e76SNico Weber // We must include windows.h after intrin.h. 22447762daSMichael J. Spencer #include <windows.h> 23447762daSMichael J. Spencer #undef MemoryFence 24447762daSMichael J. Spencer #endif 25447762daSMichael J. Spencer 262f92f610SRafael Espindola #if defined(__GNUC__) || (defined(__IBMCPP__) && __IBMCPP__ >= 1210) 272f92f610SRafael Espindola #define GNU_ATOMICS 282f92f610SRafael Espindola #endif 292f92f610SRafael Espindola MemoryFence()30447762daSMichael J. Spencervoid sys::MemoryFence() { 314418a602SEric Christopher #if LLVM_HAS_ATOMICS == 0 32447762daSMichael J. Spencer return; 33447762daSMichael J. Spencer #else 342f92f610SRafael Espindola # if defined(GNU_ATOMICS) 35447762daSMichael J. Spencer __sync_synchronize(); 36447762daSMichael J. Spencer # elif defined(_MSC_VER) 37447762daSMichael J. Spencer MemoryBarrier(); 38447762daSMichael J. Spencer # else 39447762daSMichael J. Spencer # error No memory fence implementation for your platform! 40447762daSMichael J. Spencer # endif 41447762daSMichael J. Spencer #endif 42447762daSMichael J. Spencer } 43447762daSMichael J. Spencer CompareAndSwap(volatile sys::cas_flag * ptr,sys::cas_flag new_value,sys::cas_flag old_value)44447762daSMichael J. Spencersys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, 45447762daSMichael J. Spencer sys::cas_flag new_value, 46447762daSMichael J. Spencer sys::cas_flag old_value) { 474418a602SEric Christopher #if LLVM_HAS_ATOMICS == 0 48447762daSMichael J. Spencer sys::cas_flag result = *ptr; 49447762daSMichael J. Spencer if (result == old_value) 50447762daSMichael J. Spencer *ptr = new_value; 51447762daSMichael J. Spencer return result; 522f92f610SRafael Espindola #elif defined(GNU_ATOMICS) 53447762daSMichael J. Spencer return __sync_val_compare_and_swap(ptr, old_value, new_value); 54447762daSMichael J. Spencer #elif defined(_MSC_VER) 55447762daSMichael J. Spencer return InterlockedCompareExchange(ptr, new_value, old_value); 56447762daSMichael J. Spencer #else 57447762daSMichael J. Spencer # error No compare-and-swap implementation for your platform! 58447762daSMichael J. Spencer #endif 59447762daSMichael J. Spencer } 60