summaryrefslogtreecommitdiff
path: root/src/gc
diff options
context:
space:
mode:
authorKoundinya Veluri <kouvel@users.noreply.github.com>2018-04-16 18:13:50 -0700
committerJan Kotas <jkotas@microsoft.com>2018-04-16 18:13:50 -0700
commit535a4311f5702ecd57090f8fb397932ba5aa5ecf (patch)
treed1d5a48bb8da8a8ec9974b01698753da2d5ca722 /src/gc
parentb92a05399001ad1fc7a301dcbc73b9389516248c (diff)
downloadcoreclr-535a4311f5702ecd57090f8fb397932ba5aa5ecf.tar.gz
coreclr-535a4311f5702ecd57090f8fb397932ba5aa5ecf.tar.bz2
coreclr-535a4311f5702ecd57090f8fb397932ba5aa5ecf.zip
[Arm64] Add memory barrier after interlocked operations (#17595)
Fixes https://github.com/dotnet/coreclr/issues/17591
Diffstat (limited to 'src/gc')
-rw-r--r--src/gc/env/gcenv.interlocked.h6
-rw-r--r--src/gc/env/gcenv.interlocked.inl48
2 files changed, 45 insertions, 9 deletions
diff --git a/src/gc/env/gcenv.interlocked.h b/src/gc/env/gcenv.interlocked.h
index 1b1035958e..1da222de75 100644
--- a/src/gc/env/gcenv.interlocked.h
+++ b/src/gc/env/gcenv.interlocked.h
@@ -10,6 +10,12 @@
// Interlocked operations
class Interlocked
{
+private:
+
+#ifndef _MSC_VER
+ static void ArmInterlockedOperationBarrier();
+#endif // !_MSC_VER
+
public:
// Increment the value of the specified 32-bit variable as an atomic operation.
diff --git a/src/gc/env/gcenv.interlocked.inl b/src/gc/env/gcenv.interlocked.inl
index fd4f839970..3eaaa3ae59 100644
--- a/src/gc/env/gcenv.interlocked.inl
+++ b/src/gc/env/gcenv.interlocked.inl
@@ -11,6 +11,16 @@
#include <intrin.h>
#endif // _MSC_VER
+#ifndef _MSC_VER
+__forceinline void Interlocked::ArmInterlockedOperationBarrier()
+{
+#ifdef _ARM64_
+ // See PAL_ArmInterlockedOperationBarrier() in the PAL
+ __sync_synchronize();
+#endif // _ARM64_
+}
+#endif // !_MSC_VER
+
// Increment the value of the specified 32-bit variable as an atomic operation.
// Parameters:
// addend - variable to be incremented
@@ -23,7 +33,9 @@ __forceinline T Interlocked::Increment(T volatile *addend)
static_assert(sizeof(long) == sizeof(T), "Size of long must be the same as size of T");
return _InterlockedIncrement((long*)addend);
#else
- return __sync_add_and_fetch(addend, 1);
+ T result = __sync_add_and_fetch(addend, 1);
+ ArmInterlockedOperationBarrier();
+ return result;
#endif
}
@@ -39,7 +51,9 @@ __forceinline T Interlocked::Decrement(T volatile *addend)
static_assert(sizeof(long) == sizeof(T), "Size of long must be the same as size of T");
return _InterlockedDecrement((long*)addend);
#else
- return __sync_sub_and_fetch(addend, 1);
+ T result = __sync_sub_and_fetch(addend, 1);
+ ArmInterlockedOperationBarrier();
+ return result;
#endif
}
@@ -56,7 +70,9 @@ __forceinline T Interlocked::Exchange(T volatile *destination, T value)
static_assert(sizeof(long) == sizeof(T), "Size of long must be the same as size of T");
return _InterlockedExchange((long*)destination, value);
#else
- return __sync_swap(destination, value);
+ T result = __sync_swap(destination, value);
+ ArmInterlockedOperationBarrier();
+ return result;
#endif
}
@@ -75,7 +91,9 @@ __forceinline T Interlocked::CompareExchange(T volatile *destination, T exchange
static_assert(sizeof(long) == sizeof(T), "Size of long must be the same as size of T");
return _InterlockedCompareExchange((long*)destination, exchange, comparand);
#else
- return __sync_val_compare_and_swap(destination, comparand, exchange);
+ T result = __sync_val_compare_and_swap(destination, comparand, exchange);
+ ArmInterlockedOperationBarrier();
+ return result;
#endif
}
@@ -92,7 +110,9 @@ __forceinline T Interlocked::ExchangeAdd(T volatile *addend, T value)
static_assert(sizeof(long) == sizeof(T), "Size of long must be the same as size of T");
return _InterlockedExchangeAdd((long*)addend, value);
#else
- return __sync_fetch_and_add(addend, value);
+ T result = __sync_fetch_and_add(addend, value);
+ ArmInterlockedOperationBarrier();
+ return result;
#endif
}
@@ -108,6 +128,7 @@ __forceinline void Interlocked::And(T volatile *destination, T value)
_InterlockedAnd((long*)destination, value);
#else
__sync_and_and_fetch(destination, value);
+ ArmInterlockedOperationBarrier();
#endif
}
@@ -123,6 +144,7 @@ __forceinline void Interlocked::Or(T volatile *destination, T value)
_InterlockedOr((long*)destination, value);
#else
__sync_or_and_fetch(destination, value);
+ ArmInterlockedOperationBarrier();
#endif
}
@@ -142,7 +164,9 @@ __forceinline T Interlocked::ExchangePointer(T volatile * destination, T value)
return (T)(TADDR)_InterlockedExchange((long volatile *)(void* volatile *)destination, (long)(void*)value);
#endif
#else
- return (T)(TADDR)__sync_swap((void* volatile *)destination, value);
+ T result = (T)(TADDR)__sync_swap((void* volatile *)destination, value);
+ ArmInterlockedOperationBarrier();
+ return result;
#endif
}
@@ -156,7 +180,9 @@ __forceinline T Interlocked::ExchangePointer(T volatile * destination, std::null
return (T)(TADDR)_InterlockedExchange((long volatile *)(void* volatile *)destination, (long)(void*)value);
#endif
#else
- return (T)(TADDR)__sync_swap((void* volatile *)destination, value);
+ T result = (T)(TADDR)__sync_swap((void* volatile *)destination, value);
+ ArmInterlockedOperationBarrier();
+ return result;
#endif
}
@@ -178,7 +204,9 @@ __forceinline T Interlocked::CompareExchangePointer(T volatile *destination, T e
return (T)(TADDR)_InterlockedCompareExchange((long volatile *)(void* volatile *)destination, (long)(void*)exchange, (long)(void*)comparand);
#endif
#else
- return (T)(TADDR)__sync_val_compare_and_swap((void* volatile *)destination, comparand, exchange);
+ T result = (T)(TADDR)__sync_val_compare_and_swap((void* volatile *)destination, comparand, exchange);
+ ArmInterlockedOperationBarrier();
+ return result;
#endif
}
@@ -192,7 +220,9 @@ __forceinline T Interlocked::CompareExchangePointer(T volatile *destination, T e
return (T)(TADDR)_InterlockedCompareExchange((long volatile *)(void* volatile *)destination, (long)(void*)exchange, (long)(void*)comparand);
#endif
#else
- return (T)(TADDR)__sync_val_compare_and_swap((void* volatile *)destination, (void*)comparand, (void*)exchange);
+ T result = (T)(TADDR)__sync_val_compare_and_swap((void* volatile *)destination, (void*)comparand, (void*)exchange);
+ ArmInterlockedOperationBarrier();
+ return result;
#endif
}