1*0b57cec5SDimitry Andric //===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file implements atomic operations. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "llvm/Support/Atomic.h" 14*0b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric using namespace llvm; 17*0b57cec5SDimitry Andric 18*0b57cec5SDimitry Andric #if defined(_MSC_VER) 19*0b57cec5SDimitry Andric #include <intrin.h> 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric // We must include windows.h after intrin.h. 22*0b57cec5SDimitry Andric #include <windows.h> 23*0b57cec5SDimitry Andric #undef MemoryFence 24*0b57cec5SDimitry Andric #endif 25*0b57cec5SDimitry Andric 26*0b57cec5SDimitry Andric #if defined(__GNUC__) || (defined(__IBMCPP__) && __IBMCPP__ >= 1210) 27*0b57cec5SDimitry Andric #define GNU_ATOMICS 28*0b57cec5SDimitry Andric #endif 29*0b57cec5SDimitry Andric MemoryFence()30*0b57cec5SDimitry Andricvoid sys::MemoryFence() { 31*0b57cec5SDimitry Andric #if LLVM_HAS_ATOMICS == 0 32*0b57cec5SDimitry Andric return; 33*0b57cec5SDimitry Andric #else 34*0b57cec5SDimitry Andric # if defined(GNU_ATOMICS) 35*0b57cec5SDimitry Andric __sync_synchronize(); 36*0b57cec5SDimitry Andric # elif defined(_MSC_VER) 37*0b57cec5SDimitry Andric MemoryBarrier(); 38*0b57cec5SDimitry Andric # else 39*0b57cec5SDimitry Andric # error No memory fence implementation for your platform! 40*0b57cec5SDimitry Andric # endif 41*0b57cec5SDimitry Andric #endif 42*0b57cec5SDimitry Andric } 43*0b57cec5SDimitry Andric CompareAndSwap(volatile sys::cas_flag * ptr,sys::cas_flag new_value,sys::cas_flag old_value)44*0b57cec5SDimitry Andricsys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, 45*0b57cec5SDimitry Andric sys::cas_flag new_value, 46*0b57cec5SDimitry Andric sys::cas_flag old_value) { 47*0b57cec5SDimitry Andric #if LLVM_HAS_ATOMICS == 0 48*0b57cec5SDimitry Andric sys::cas_flag result = *ptr; 49*0b57cec5SDimitry Andric if (result == old_value) 50*0b57cec5SDimitry Andric *ptr = new_value; 51*0b57cec5SDimitry Andric return result; 52*0b57cec5SDimitry Andric #elif defined(GNU_ATOMICS) 53*0b57cec5SDimitry Andric return __sync_val_compare_and_swap(ptr, old_value, new_value); 54*0b57cec5SDimitry Andric #elif defined(_MSC_VER) 55*0b57cec5SDimitry Andric return InterlockedCompareExchange(ptr, new_value, old_value); 56*0b57cec5SDimitry Andric #else 57*0b57cec5SDimitry Andric # error No compare-and-swap implementation for your platform! 58*0b57cec5SDimitry Andric #endif 59*0b57cec5SDimitry Andric } 60