// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "HAL/Platform.h" #include #if PLATFORM_CPU_X86_FAMILY # include #endif #if !defined(TRACE_PRIVATE_THREAD_YIELD) # define TRACE_PRIVATE_THREAD_YIELD 0 #endif namespace UE { namespace Trace { namespace Private { //////////////////////////////////////////////////////////////////////////////// template Type AtomicLoadRelaxed(Type volatile* Source); template Type AtomicLoadAcquire(Type volatile* Source); template void AtomicStoreRelaxed(Type volatile* Target, Type Value); template void AtomicStoreRelease(Type volatile* Target, Type Value); template Type AtomicExchangeAcquire(Type volatile* Target, Type Value); template Type AtomicExchangeRelease(Type volatile* Target, Type Value); template bool AtomicCompareExchangeRelaxed(Type volatile* Target, Type New, Type Expected); template bool AtomicCompareExchangeAcquire(Type volatile* Target, Type New, Type Expected); template bool AtomicCompareExchangeRelease(Type volatile* Target, Type New, Type Expected); template Type AtomicAddRelaxed(Type volatile* Target, Type Value); template Type AtomicAddRelease(Type volatile* Target, Type Value); template Type AtomicAddAcquire(Type volatile* Target, Type Value); template Type AtomicSubRelaxed(Type volatile* Target, Type Value); template Type AtomicSubRelease(Type volatile* Target, Type Value); template Type AtomicSubAcquire(Type volatile* Target, Type Value); void PlatformYield(); //////////////////////////////////////////////////////////////////////////////// inline void PlatformYield() { #if TRACE_PRIVATE_THREAD_YIELD extern void ThreadYield(); ThreadYield(); #elif PLATFORM_USE_SSE2_FOR_THREAD_YIELD _mm_pause(); #elif PLATFORM_CPU_ARM_FAMILY # if defined(_MSC_VER) && !defined(__clang__) // MSVC __yield(); # else __builtin_arm_yield(); # endif #else #error Unsupported architecture! #endif } //////////////////////////////////////////////////////////////////////////////// template inline Type AtomicLoadRelaxed(Type volatile* Source) { std::atomic* T = (std::atomic*) Source; return T->load(std::memory_order_relaxed); } //////////////////////////////////////////////////////////////////////////////// template inline Type AtomicLoadAcquire(Type volatile* Source) { std::atomic* T = (std::atomic*) Source; return T->load(std::memory_order_acquire); } //////////////////////////////////////////////////////////////////////////////// template inline void AtomicStoreRelaxed(Type volatile* Target, Type Value) { std::atomic* T = (std::atomic*) Target; T->store(Value, std::memory_order_relaxed); } //////////////////////////////////////////////////////////////////////////////// template inline void AtomicStoreRelease(Type volatile* Target, Type Value) { std::atomic* T = (std::atomic*) Target; T->store(Value, std::memory_order_release); } //////////////////////////////////////////////////////////////////////////////// template inline Type AtomicExchangeAcquire(Type volatile* Target, Type Value) { std::atomic* T = (std::atomic*) Target; return T->exchange(Value, std::memory_order_acquire); } //////////////////////////////////////////////////////////////////////////////// template inline Type AtomicExchangeRelease(Type volatile* Target, Type Value) { std::atomic* T = (std::atomic*) Target; return T->exchange(Value, std::memory_order_release); } //////////////////////////////////////////////////////////////////////////////// template inline bool AtomicCompareExchangeRelaxed(Type volatile* Target, Type New, Type Expected) { std::atomic* T = (std::atomic*) Target; return T->compare_exchange_weak(Expected, New, std::memory_order_relaxed); } //////////////////////////////////////////////////////////////////////////////// template inline bool AtomicCompareExchangeAcquire(Type volatile* Target, Type New, Type Expected) { std::atomic* T = (std::atomic*) Target; return T->compare_exchange_weak(Expected, New, std::memory_order_acquire); } //////////////////////////////////////////////////////////////////////////////// template inline bool AtomicCompareExchangeRelease(Type volatile* Target, Type New, Type Expected) { std::atomic* T = (std::atomic*) Target; return T->compare_exchange_weak(Expected, New, std::memory_order_release); } //////////////////////////////////////////////////////////////////////////////// template inline Type AtomicAddRelaxed(Type volatile* Target, Type Value) { std::atomic* T = (std::atomic*) Target; return T->fetch_add(Value, std::memory_order_relaxed); } //////////////////////////////////////////////////////////////////////////////// template inline Type AtomicAddAcquire(Type volatile* Target, Type Value) { std::atomic* T = (std::atomic*) Target; return T->fetch_add(Value, std::memory_order_acquire); } //////////////////////////////////////////////////////////////////////////////// template inline Type AtomicAddRelease(Type volatile* Target, Type Value) { std::atomic* T = (std::atomic*) Target; return T->fetch_add(Value, std::memory_order_release); } //////////////////////////////////////////////////////////////////////////////// template inline Type AtomicSubRelaxed(Type volatile* Target, Type Value) { std::atomic* T = (std::atomic*) Target; return T->fetch_sub(Value, std::memory_order_relaxed); } //////////////////////////////////////////////////////////////////////////////// template inline Type AtomicSubAcquire(Type volatile* Target, Type Value) { std::atomic* T = (std::atomic*) Target; return T->fetch_sub(Value, std::memory_order_acquire); } //////////////////////////////////////////////////////////////////////////////// template inline Type AtomicSubRelease(Type volatile* Target, Type Value) { std::atomic* T = (std::atomic*) Target; return T->fetch_sub(Value, std::memory_order_release); } } // namespace Private } // namespace Trace } // namespace UE