Skip to content

Commit 6be8d27

Browse files
authored
Windows/Arm64: Use 8.1 atomic instructions if they are available (#70921)
* Use Fast compareexchange, acquire/release * working windows version * remove printf * some more #ifdef * fix some #ifdef * optimize EnterObjMonitorHelperSpin * Remove FastInterlockedCompareExchange64 for now
1 parent 9876d8c commit 6be8d27

File tree

6 files changed

+103
-0
lines changed

6 files changed

+103
-0
lines changed

src/coreclr/utilcode/util.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@
2323

2424
#ifndef DACCESS_COMPILE
2525
UINT32 g_nClrInstanceId = 0;
26+
27+
#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
28+
// Flag to check if atomics feature is available on
29+
// the machine
30+
bool g_arm64_atomics_present = false;
31+
#endif
32+
2633
#endif //!DACCESS_COMPILE
2734

2835
//*****************************************************************************

src/coreclr/vm/codeman.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,6 +1566,7 @@ void EEJitManager::SetCpuInfo()
15661566
if (IsProcessorFeaturePresent(PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE))
15671567
{
15681568
CPUCompileFlags.Set(InstructionSet_Atomics);
1569+
g_arm64_atomics_present = true;
15691570
}
15701571

15711572
// PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE (43)

src/coreclr/vm/syncblk.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,7 +1652,11 @@ AwareLock::EnterHelperResult ObjHeader::EnterObjMonitorHelperSpin(Thread* pCurTh
16521652
}
16531653

16541654
LONG newValue = oldValue | tid;
1655+
#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
1656+
if (FastInterlockedCompareExchangeAcquire((LONG*)&m_SyncBlockValue, newValue, oldValue) == oldValue)
1657+
#else
16551658
if (InterlockedCompareExchangeAcquire((LONG*)&m_SyncBlockValue, newValue, oldValue) == oldValue)
1659+
#endif
16561660
{
16571661
return AwareLock::EnterHelperResult_Entered;
16581662
}

src/coreclr/vm/syncblk.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,13 +382,21 @@ class AwareLock
382382
LockState CompareExchange(LockState toState, LockState fromState)
383383
{
384384
LIMITED_METHOD_CONTRACT;
385+
#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
386+
return (UINT32)FastInterlockedCompareExchange((LONG *)&m_state, (LONG)toState, (LONG)fromState);
387+
#else
385388
return (UINT32)InterlockedCompareExchange((LONG *)&m_state, (LONG)toState, (LONG)fromState);
389+
#endif
386390
}
387391

388392
LockState CompareExchangeAcquire(LockState toState, LockState fromState)
389393
{
390394
LIMITED_METHOD_CONTRACT;
395+
#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
396+
return (UINT32)FastInterlockedCompareExchangeAcquire((LONG *)&m_state, (LONG)toState, (LONG)fromState);
397+
#else
391398
return (UINT32)InterlockedCompareExchangeAcquire((LONG *)&m_state, (LONG)toState, (LONG)fromState);
399+
#endif
392400
}
393401

394402
public:

src/coreclr/vm/syncblk.inl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,11 @@ FORCEINLINE AwareLock::EnterHelperResult ObjHeader::EnterObjMonitorHelper(Thread
602602
}
603603

604604
LONG newValue = oldValue | tid;
605+
#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
606+
if (FastInterlockedCompareExchangeAcquire((LONG*)&m_SyncBlockValue, newValue, oldValue) == oldValue)
607+
#else
605608
if (InterlockedCompareExchangeAcquire((LONG*)&m_SyncBlockValue, newValue, oldValue) == oldValue)
609+
#endif
606610
{
607611
return AwareLock::EnterHelperResult_Entered;
608612
}
@@ -650,7 +654,11 @@ FORCEINLINE AwareLock::EnterHelperResult ObjHeader::EnterObjMonitorHelper(Thread
650654
return AwareLock::EnterHelperResult_UseSlowPath;
651655
}
652656

657+
#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
658+
if (FastInterlockedCompareExchangeAcquire((LONG*)&m_SyncBlockValue, newValue, oldValue) == oldValue)
659+
#else
653660
if (InterlockedCompareExchangeAcquire((LONG*)&m_SyncBlockValue, newValue, oldValue) == oldValue)
661+
#endif
654662
{
655663
return AwareLock::EnterHelperResult_Entered;
656664
}
@@ -723,7 +731,12 @@ FORCEINLINE AwareLock::LeaveHelperAction ObjHeader::LeaveObjMonitorHelper(Thread
723731
{
724732
// We are leaving the lock
725733
DWORD newValue = (syncBlockValue & (~SBLK_MASK_LOCK_THREADID));
734+
735+
#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
736+
if (FastInterlockedCompareExchangeRelease((LONG*)&m_SyncBlockValue, newValue, syncBlockValue) != (LONG)syncBlockValue)
737+
#else
726738
if (InterlockedCompareExchangeRelease((LONG*)&m_SyncBlockValue, newValue, syncBlockValue) != (LONG)syncBlockValue)
739+
#endif
727740
{
728741
return AwareLock::LeaveHelperAction_Yield;
729742
}
@@ -732,7 +745,11 @@ FORCEINLINE AwareLock::LeaveHelperAction ObjHeader::LeaveObjMonitorHelper(Thread
732745
{
733746
// recursion and ThinLock
734747
DWORD newValue = syncBlockValue - SBLK_LOCK_RECLEVEL_INC;
748+
#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
749+
if (FastInterlockedCompareExchangeRelease((LONG*)&m_SyncBlockValue, newValue, syncBlockValue) != (LONG)syncBlockValue)
750+
#else
735751
if (InterlockedCompareExchangeRelease((LONG*)&m_SyncBlockValue, newValue, syncBlockValue) != (LONG)syncBlockValue)
752+
#endif
736753
{
737754
return AwareLock::LeaveHelperAction_Yield;
738755
}

src/coreclr/vm/util.hpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@
2525
#define MAX_CACHE_LINE_SIZE 64
2626
#endif
2727

28+
#ifndef DACCESS_COMPILE
29+
#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
30+
// Flag to check if atomics feature is available on
31+
// the machine
32+
extern bool g_arm64_atomics_present;
33+
#endif
34+
#endif
35+
2836
#ifndef TARGET_UNIX
2937
// Copied from malloc.h: don't want to bring in the whole header file.
3038
void * __cdecl _alloca(size_t);
@@ -71,6 +79,64 @@ BOOL inline FitsInU4(unsigned __int64 val)
7179
return val == (unsigned __int64)(unsigned __int32)val;
7280
}
7381

82+
#if defined(DACCESS_COMPILE)
83+
#define FastInterlockedCompareExchange InterlockedCompareExchange
84+
#define FastInterlockedCompareExchangeAcquire InterlockedCompareExchangeAcquire
85+
#define FastInterlockedCompareExchangeRelease InterlockedCompareExchangeRelease
86+
#else
87+
88+
#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
89+
90+
FORCEINLINE LONG FastInterlockedCompareExchange(
91+
LONG volatile *Destination,
92+
LONG Exchange,
93+
LONG Comperand)
94+
{
95+
if (g_arm64_atomics_present)
96+
{
97+
return (LONG) __casal32((unsigned __int32*) Destination, (unsigned __int32)Comperand, (unsigned __int32)Exchange);
98+
}
99+
else
100+
{
101+
return InterlockedCompareExchange(Destination, Exchange, Comperand);
102+
}
103+
}
104+
105+
FORCEINLINE LONG FastInterlockedCompareExchangeAcquire(
106+
IN OUT LONG volatile *Destination,
107+
IN LONG Exchange,
108+
IN LONG Comperand
109+
)
110+
{
111+
if (g_arm64_atomics_present)
112+
{
113+
return (LONG) __casa32((unsigned __int32*) Destination, (unsigned __int32)Comperand, (unsigned __int32)Exchange);
114+
}
115+
else
116+
{
117+
return InterlockedCompareExchangeAcquire(Destination, Exchange, Comperand);
118+
}
119+
}
120+
121+
FORCEINLINE LONG FastInterlockedCompareExchangeRelease(
122+
IN OUT LONG volatile *Destination,
123+
IN LONG Exchange,
124+
IN LONG Comperand
125+
)
126+
{
127+
if (g_arm64_atomics_present)
128+
{
129+
return (LONG) __casl32((unsigned __int32*) Destination, (unsigned __int32)Comperand, (unsigned __int32)Exchange);
130+
}
131+
else
132+
{
133+
return InterlockedCompareExchangeRelease(Destination, Exchange, Comperand);
134+
}
135+
}
136+
137+
#endif // defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
138+
139+
#endif //defined(DACCESS_COMPILE)
74140

75141

76142
//************************************************************************

0 commit comments

Comments
 (0)