summaryrefslogtreecommitdiff
path: root/includes/stg/SMP.h
diff options
context:
space:
mode:
authorKarel Gardas <karel.gardas@centrum.cz>2011-07-05 20:10:18 +0200
committerManuel M T Chakravarty <chak@cse.unsw.edu.au>2011-08-10 22:03:41 +1000
commit330dff34ddc45eb0adc8d098a55f491cce0ea108 (patch)
treeabb6c649cda480eb52bf48e55bf8a9261b505250 /includes/stg/SMP.h
parente44642590550547675bffd37d395008eb978f119 (diff)
downloadhaskell-330dff34ddc45eb0adc8d098a55f491cce0ea108.tar.gz
implement ARMv6/7 specific xchg function
Diffstat (limited to 'includes/stg/SMP.h')
-rw-r--r--includes/stg/SMP.h20
1 files changed, 18 insertions, 2 deletions
diff --git a/includes/stg/SMP.h b/includes/stg/SMP.h
index d093439182..0b7592d690 100644
--- a/includes/stg/SMP.h
+++ b/includes/stg/SMP.h
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------------
*
- * (c) The GHC Team, 2005-2009
+ * (c) The GHC Team, 2005-2011
*
* Macros for multi-CPU support
*
@@ -136,10 +136,26 @@ xchg(StgPtr p, StgWord w)
: "+r" (result), "+m" (*p)
: /* no input-only operands */
);
-#elif arm_HOST_ARCH
+#elif arm_HOST_ARCH && defined(PRE_ARMv6)
__asm__ __volatile__ ("swp %0, %1, [%2]"
: "=&r" (result)
: "r" (w), "r" (p) : "memory");
+#elif arm_HOST_ARCH && !defined(PRE_ARMv6)
+ // swp instruction which is used in PRE_ARMv6 code above
+ // is deprecated in AMRv6 and later. ARM, Ltd. *highly* recommends
+ // to use ldrex/strex instruction pair for the same purpose
+ // see chapter: Synchronization and semaphores in ARM Architecture
+ // Reference manual
+ StgWord tmp;
+ __asm__ __volatile__ (
+ "1: ldrex %0, [%3]\n"
+ " strex %1, %2, [%3]\n"
+ " teq %1, #1\n"
+ " beq 1b\n"
+ : "=&r" (result), "=&r" (tmp)
+ : "r" (w), "r" (p)
+ : "memory"
+ );
#elif !defined(WITHSMP)
#error xchg() unimplemented on this architecture
result = *p;