Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/coreclr/gc/env/gcenv.interlocked.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
#ifndef __GCENV_INTERLOCKED_H__
#define __GCENV_INTERLOCKED_H__


#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
// Flag to check if atomics feature is available on
// the machine
extern bool g_arm64_atomics_present;
#endif


// Interlocked operations
class Interlocked
{
Expand Down
54 changes: 45 additions & 9 deletions src/coreclr/gc/env/gcenv.interlocked.inl
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,16 @@ __forceinline T Interlocked::Exchange(T volatile *destination, T value)
{
#ifdef _MSC_VER
static_assert(sizeof(long) == sizeof(T), "Size of long must be the same as size of T");
return _InterlockedExchange((long*)destination, value);
#ifdef TARGET_ARM64
if (g_arm64_atomics_present)
{
return (T) __swpal32((unsigned __int32*) destination, (unsigned __int32)value);
}
else
#endif // TARGET_ARM64
{
return _InterlockedExchange((long*)destination, value);
}
#else
T result = __atomic_exchange_n(destination, value, __ATOMIC_ACQ_REL);
ArmInterlockedOperationBarrier();
Expand All @@ -91,12 +100,21 @@ __forceinline T Interlocked::CompareExchange(T volatile *destination, T exchange
{
#ifdef _MSC_VER
static_assert(sizeof(long) == sizeof(T), "Size of long must be the same as size of T");
return _InterlockedCompareExchange((long*)destination, exchange, comparand);
#ifdef TARGET_ARM64
if (g_arm64_atomics_present)
{
return (T) __casal32((unsigned __int32*) destination, (unsigned __int32)comparand, (unsigned __int32)exchange);
}
else
#endif // TARGET_ARM64
{
return _InterlockedCompareExchange((long*)destination, exchange, comparand);
}
#else
T result = __sync_val_compare_and_swap(destination, comparand, exchange);
ArmInterlockedOperationBarrier();
return result;
#endif
#endif // _MSC_VER
}

// Perform an atomic addition of two 32-bit values and return the original value of the addend.
Expand Down Expand Up @@ -192,31 +210,49 @@ __forceinline T Interlocked::ExchangePointer(T volatile * destination, T value)
{
#ifdef _MSC_VER
#ifdef HOST_64BIT
return (T)(TADDR)_InterlockedExchangePointer((void* volatile *)destination, value);
#ifdef TARGET_ARM64
if (g_arm64_atomics_present)
{
return (T)(TADDR)__swpal64((unsigned __int64 volatile*) destination, (unsigned __int64)value);
}
else
#endif // TARGET_ARM64
{
return (T)(TADDR)_InterlockedExchangePointer((void* volatile *)destination, value);
}
#else
return (T)(TADDR)_InterlockedExchange((long volatile *)(void* volatile *)destination, (long)(void*)value);
#endif
#endif // HOST_64BIT
#else
T result = (T)(TADDR)__atomic_exchange_n((void* volatile *)destination, value, __ATOMIC_ACQ_REL);
ArmInterlockedOperationBarrier();
return result;
#endif
#endif // _MSC_VER
}

template <typename T>
__forceinline T Interlocked::ExchangePointer(T volatile * destination, std::nullptr_t value)
{
#ifdef _MSC_VER
#ifdef HOST_64BIT
return (T)(TADDR)_InterlockedExchangePointer((void* volatile *)destination, value);
#ifdef TARGET_ARM64
if (g_arm64_atomics_present)
{
return (T)(TADDR)__swpal64((unsigned __int64 volatile*) destination, (unsigned __int64)value);
}
else
#endif // TARGET_ARM64
{
return (T)(TADDR)_InterlockedExchangePointer((void* volatile *)destination, value);
}
#else
return (T)(TADDR)_InterlockedExchange((long volatile *)(void* volatile *)destination, (long)(void*)value);
#endif
#endif // HOST_64BIT
#else
T result = (T)(TADDR)__atomic_exchange_n((void* volatile *)destination, value, __ATOMIC_ACQ_REL);
ArmInterlockedOperationBarrier();
return result;
#endif
#endif // _MSC_VER
}

// Performs an atomic compare-and-exchange operation on the specified pointers.
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/gc/gccommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ IGCHeapInternal* g_theGCHeap;
IGCHandleManager* g_theGCHandleManager;

#ifdef BUILD_AS_STANDALONE

#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
// Flag to check if atomics feature is available on
// the machine. OFF for standalone.
bool g_arm64_atomics_present = false;
#endif // defined(TARGET_WINDOWS) && defined(TARGET_ARM64)

IGCToCLR* g_theGCToCLR;
#endif // BUILD_AS_STANDALONE

Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/gc/sample/GCSample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,20 @@

#include "common.h"


#include "gcenv.h"

#include "gc.h"
#include "objecthandle.h"

#include "gcdesc.h"

#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
// Flag to check if atomics feature is available on
// the machine. OFF for GCSample.
bool g_arm64_atomics_present = false;
#endif

//
// The fast paths for object allocation and write barriers is performance critical. They are often
// hand written in assembly code, etc.
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ uint32_t PalEventWrite(REGHANDLE arg1, const EVENT_DESCRIPTOR * arg2, uint32_t a
#define REDHAWK_PALEXPORT extern "C"
#define REDHAWK_PALAPI __stdcall

#if defined(HOST_ARM64)
// Flag to check if atomics feature is available on
// the machine. OFF for GCSample.
bool g_arm64_atomics_present = false;
#endif

// Index for the fiber local storage of the attached thread pointer
static uint32_t g_flsIndex = FLS_OUT_OF_INDEXES;

Expand Down Expand Up @@ -690,6 +696,7 @@ REDHAWK_PALIMPORT void REDHAWK_PALAPI PAL_GetCpuCapabilityFlags(int* flags)
if (IsProcessorFeaturePresent(PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE))
{
*flags |= ARM64IntrinsicConstants_Atomics;
g_arm64_atomics_present = true;
}
}

Expand Down