Skip to content
Permalink
Browse files

Add memory barriers to interlocked operations on ARM, since the runti…

…me code depends on it.
  • Loading branch information...
vargaz committed Jan 10, 2012
1 parent 42cdbf3 commit 488d55a58debebeb0c4727d2f012dd70d6c2412b
Showing with 27 additions and 4 deletions.
  1. +27 −4 mono/io-layer/atomic.h
@@ -744,18 +744,25 @@ static inline gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
#elif defined(__arm__)
#define WAPI_ATOMIC_ASM

/*
* Atomic operations on ARM doesn't contain memory barriers, and the runtime code
* depends on this, so we add them explicitly.
*/

static inline gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch, gint32 comp)
{
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7__)
gint32 ret, tmp;
__asm__ __volatile__ ( "1:\n"
"dmb\n"
"mov %0, #0\n"
"ldrex %1, [%2]\n"
"teq %1, %3\n"
"it eq\n"
"strexeq %0, %4, [%2]\n"
"teq %0, #0\n"
"bne 1b\n"
"dmb\n"
: "=&r" (tmp), "=&r" (ret)
: "r" (dest), "r" (comp), "r" (exch)
: "memory", "cc");
@@ -786,14 +793,17 @@ static inline gpointer InterlockedCompareExchangePointer(volatile gpointer *dest
{
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7__)
gpointer ret, tmp;
__asm__ __volatile__ ( "1:\n"
__asm__ __volatile__ (
"dmb\n"
"1:\n"
"mov %0, #0\n"
"ldrex %1, [%2]\n"
"teq %1, %3\n"
"it eq\n"
"strexeq %0, %4, [%2]\n"
"teq %0, #0\n"
"bne 1b\n"
"dmb\n"
: "=&r" (tmp), "=&r" (ret)
: "r" (dest), "r" (comp), "r" (exch)
: "memory", "cc");
@@ -824,12 +834,15 @@ static inline gint32 InterlockedIncrement(volatile gint32 *dest)
{
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7__)
gint32 ret, flag;
__asm__ __volatile__ ( "1:\n"
__asm__ __volatile__ (
"dmb\n"
"1:\n"
"ldrex %0, [%2]\n"
"add %0, %0, %3\n"
"strex %1, %0, [%2]\n"
"teq %1, #0\n"
"bne 1b\n"
"dmb\n"
: "=&r" (ret), "=&r" (flag)
: "r" (dest), "r" (1)
: "memory", "cc");
@@ -857,12 +870,15 @@ static inline gint32 InterlockedDecrement(volatile gint32 *dest)
{
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7__)
gint32 ret, flag;
__asm__ __volatile__ ( "1:\n"
__asm__ __volatile__ (
"dmb\n"
"1:\n"
"ldrex %0, [%2]\n"
"sub %0, %0, %3\n"
"strex %1, %0, [%2]\n"
"teq %1, #0\n"
"bne 1b\n"
"dmb\n"
: "=&r" (ret), "=&r" (flag)
: "r" (dest), "r" (1)
: "memory", "cc");
@@ -891,11 +907,13 @@ static inline gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7__)
gint32 ret, flag;
__asm__ __volatile__ (
"dmb\n"
"1:\n"
"ldrex %0, [%3]\n"
"strex %1, %2, [%3]\n"
"teq %1, #0\n"
"bne 1b\n"
"dmb\n"
: "=&r" (ret), "=&r" (flag)
: "r" (exch), "r" (dest)
: "memory", "cc");
@@ -916,11 +934,13 @@ static inline gpointer InterlockedExchangePointer(volatile gpointer *dest, gpoin
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7__)
gpointer ret, flag;
__asm__ __volatile__ (
"dmb\n"
"1:\n"
"ldrex %0, [%3]\n"
"strex %1, %2, [%3]\n"
"teq %1, #0\n"
"bne 1b\n"
"dmb\n"
: "=&r" (ret), "=&r" (flag)
: "r" (exch), "r" (dest)
: "memory", "cc");
@@ -940,12 +960,15 @@ static inline gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
{
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7__)
gint32 ret, tmp, flag;
__asm__ __volatile__ ( "1:\n"
__asm__ __volatile__ (
"dmb\n"
"1:\n"
"ldrex %0, [%3]\n"
"add %1, %0, %4\n"
"strex %2, %1, [%3]\n"
"teq %2, #0\n"
"bne 1b\n"
"dmb\n"
: "=&r" (ret), "=&r" (tmp), "=&r" (flag)
: "r" (dest), "r" (add)
: "memory", "cc");

0 comments on commit 488d55a

Please sign in to comment.
You can’t perform that action at this time.