Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
Use half-fences for volatile loads/stores on Windows ARM64 (#27384)
Browse files Browse the repository at this point in the history
* Use half-fences for volatile load/stores on Windows ARM64

* Updated Volatile.h in gc/env as well.
unified on type names and warning suppression.
  • Loading branch information
VSadov authored and jkotas committed Oct 25, 2019
1 parent ed525ba commit c128dba
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 0 deletions.
54 changes: 54 additions & 0 deletions src/gc/env/volatile.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ struct RemoveVolatile<volatile T>
// Starting at version 3.8, clang errors out on initializing of type int * to volatile int *. To fix this, we add two templates to cast away volatility
// Helper structures for casting away volatileness

#if defined(_ARM64_) && defined(_MSC_VER)
#include <arm64intr.h>
#endif

template<typename T>
inline
Expand All @@ -145,6 +148,32 @@ T VolatileLoad(T const * pt)
val = *(T volatile const *)pt;
asm volatile ("dmb ishld" : : : "memory");
}
#elif defined(_ARM64_) && defined(_MSC_VER)
// silence warnings on casts in branches that are not taken.
#pragma warning(push)
#pragma warning(disable : 4302)
#pragma warning(disable : 4311)
#pragma warning(disable : 4312)
T val;
switch (sizeof(T))
{
case 1:
val = (typename RemoveVolatile<T>::type)__ldar8 ((unsigned __int8 volatile*)pt);
break;
case 2:
val = (typename RemoveVolatile<T>::type)__ldar16((unsigned __int16 volatile*)pt);
break;
case 4:
val = (typename RemoveVolatile<T>::type)__ldar32((unsigned __int32 volatile*)pt);
break;
case 8:
val = (typename RemoveVolatile<T>::type)__ldar64((unsigned __int64 volatile*)pt);
break;
default:
val = *(T volatile const*)pt;
__dmb(_ARM64_BARRIER_ISHLD);
}
#pragma warning(pop)
#else
T val = *(T volatile const *)pt;
VOLATILE_MEMORY_BARRIER();
Expand Down Expand Up @@ -199,6 +228,31 @@ void VolatileStore(T* pt, T val)
VOLATILE_MEMORY_BARRIER();
*(T volatile *)pt = val;
}
#elif defined(_ARM64_) && defined(_MSC_VER)
// silence warnings on casts in branches that are not taken.
#pragma warning(push)
#pragma warning(disable : 4302)
#pragma warning(disable : 4311)
#pragma warning(disable : 4312)
switch (sizeof(T))
{
case 1:
__stlr8 ((unsigned __int8 volatile*)pt, (unsigned __int8) val);
break;
case 2:
__stlr16((unsigned __int16 volatile*)pt, (unsigned __int16)val);
break;
case 4:
__stlr32((unsigned __int32 volatile*)pt, (unsigned __int32)val);
break;
case 8:
__stlr64((unsigned __int64 volatile*)pt ,(unsigned __int64)val);
break;
default:
__dmb(_ARM64_BARRIER_ISH);
*(T volatile *)pt = val;
}
#pragma warning(pop)
#else
VOLATILE_MEMORY_BARRIER();
*(T volatile *)pt = val;
Expand Down
54 changes: 54 additions & 0 deletions src/inc/volatile.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ struct RemoveVolatile<volatile T>
// Starting at version 3.8, clang errors out on initializing of type int * to volatile int *. To fix this, we add two templates to cast away volatility
// Helper structures for casting away volatileness

#if defined(_ARM64_) && defined(_MSC_VER)
#include <arm64intr.h>
#endif

template<typename T>
inline
Expand All @@ -149,6 +152,32 @@ T VolatileLoad(T const * pt)
val = *(T volatile const *)pt;
asm volatile ("dmb ishld" : : : "memory");
}
#elif defined(_ARM64_) && defined(_MSC_VER)
// silence warnings on casts in branches that are not taken.
#pragma warning(push)
#pragma warning(disable : 4302)
#pragma warning(disable : 4311)
#pragma warning(disable : 4312)
T val;
switch (sizeof(T))
{
case 1:
val = (typename RemoveVolatile<T>::type)__ldar8 ((unsigned __int8 volatile*)pt);
break;
case 2:
val = (typename RemoveVolatile<T>::type)__ldar16((unsigned __int16 volatile*)pt);
break;
case 4:
val = (typename RemoveVolatile<T>::type)__ldar32((unsigned __int32 volatile*)pt);
break;
case 8:
val = (typename RemoveVolatile<T>::type)__ldar64((unsigned __int64 volatile*)pt);
break;
default:
val = *(T volatile const*)pt;
__dmb(_ARM64_BARRIER_ISHLD);
}
#pragma warning(pop)
#else
T val = *(T volatile const *)pt;
VOLATILE_MEMORY_BARRIER();
Expand Down Expand Up @@ -208,6 +237,31 @@ void VolatileStore(T* pt, T val)
VOLATILE_MEMORY_BARRIER();
*(T volatile *)pt = val;
}
#elif defined(_ARM64_) && defined(_MSC_VER)
// silence warnings on casts in branches that are not taken.
#pragma warning(push)
#pragma warning(disable : 4302)
#pragma warning(disable : 4311)
#pragma warning(disable : 4312)
switch (sizeof(T))
{
case 1:
__stlr8 ((unsigned __int8 volatile*)pt, (unsigned __int8) val);
break;
case 2:
__stlr16((unsigned __int16 volatile*)pt, (unsigned __int16)val);
break;
case 4:
__stlr32((unsigned __int32 volatile*)pt, (unsigned __int32)val);
break;
case 8:
__stlr64((unsigned __int64 volatile*)pt ,(unsigned __int64)val);
break;
default:
__dmb(_ARM64_BARRIER_ISH);
*(T volatile *)pt = val;
}
#pragma warning(pop)
#else
VOLATILE_MEMORY_BARRIER();
*(T volatile *)pt = val;
Expand Down

0 comments on commit c128dba

Please sign in to comment.