Index: opal/include/opal/sys/arm/atomic.h =================================================================== --- opal/include/opal/sys/arm/atomic.h (revision 26270) +++ opal/include/opal/sys/arm/atomic.h (working copy) @@ -18,47 +18,66 @@ * $HEADER$ */ +/* + * ARMv5 and earlier lack robust atomic operations and therefore this file uses + * Linux kernel support where needed. The kernel also provides memory barriers + * and this file uses them for ARMv5 and earlier processors, which lack the + * memory barrier instruction. These kernel functions are available on kernel + * versions 2.6.15 and greater. + * See Documentation/arm/kernel_user_helpers.txt in the kernel tree for details + */ + #ifndef OMPI_SYS_ARCH_ATOMIC_H #define OMPI_SYS_ARCH_ATOMIC_H 1 #if OPAL_WANT_SMP_LOCKS +#if (OPAL_ASM_ARM_VERSION >= 7) + +#define OPAL_HAVE_ATOMIC_MEM_BARRIER 1 +/* use the DMB instruction if available... */ + #define MB() __asm__ __volatile__ ("dmb" : : : "memory") #define RMB() __asm__ __volatile__ ("dmb" : : : "memory") #define WMB() __asm__ __volatile__ ("dmb" : : : "memory") +#elif (OPAL_ASM_ARM_VERSION == 6) + +#define OPAL_HAVE_ATOMIC_MEM_BARRIER 1 +/* ...or the v6-specific equivalent... */ + +#define MB() __asm__ __volatile__ ("mcr p15, 0, r0, c7, c10, 5" : : : "memory") +#define RMB() MB() +#define WMB() MB() + #else -#define MB() -#define RMB() -#define WMB() +#define OPAL_HAVE_ATOMIC_MEM_BARRIER 1 +/* ...otherwise use the Linux kernel-provided barrier */ +#define MB() (*((void (*)(void))(0xffff0fa0)))() +#define RMB() MB() +#define WMB() MB() #endif +#else -/********************************************************************** - * - * Define constants for ARMv7 - * - *********************************************************************/ -#define OPAL_HAVE_ATOMIC_MEM_BARRIER 1 +#define MB() +#define RMB() +#define WMB() -#define OPAL_HAVE_ATOMIC_CMPSET_32 1 +#endif /* OPAL_WANT_SMP_LOCKS */ -#define OPAL_HAVE_ATOMIC_CMPSET_64 1 -#define OPAL_HAVE_ATOMIC_MATH_32 1 -#define OPAL_HAVE_ATOMIC_ADD_32 1 -#define OPAL_HAVE_ATOMIC_SUB_32 1 - /********************************************************************** * * Memory Barriers * *********************************************************************/ -#if OMPI_GCC_INLINE_ASSEMBLY +#if (OMPI_GCC_INLINE_ASSEMBLY || (OPAL_ASM_ARM_VERSION < 6)) + static inline void opal_atomic_mb(void) { @@ -79,13 +98,19 @@ WMB(); } +#endif + /********************************************************************** * * Atomic math operations * *********************************************************************/ +#if (OPAL_ASM_ARM_VERSION >= 6 && OMPI_GCC_INLINE_ASSEMBLY) + +#define OPAL_HAVE_ATOMIC_CMPSET_32 1 +#define OPAL_HAVE_ATOMIC_MATH_32 1 static inline int opal_atomic_cmpset_32(volatile int32_t *addr, int32_t oldval, int32_t newval) { @@ -131,7 +156,9 @@ return opal_atomic_cmpset_32(addr, oldval, newval); } +#if (OPAL_ASM_SUPPORT_64BIT == 1) +#define OPAL_HAVE_ATOMIC_CMPSET_64 1 static inline int opal_atomic_cmpset_64(volatile int64_t *addr, int64_t oldval, int64_t newval) { @@ -181,7 +208,10 @@ return opal_atomic_cmpset_64(addr, oldval, newval); } +#endif + +#define OPAL_HAVE_ATOMIC_ADD_32 1 static inline int32_t opal_atomic_add_32(volatile int32_t* v, int inc) { int32_t t; @@ -202,7 +232,7 @@ return t; } - +#define OPAL_HAVE_ATOMIC_SUB_32 1 static inline int32_t opal_atomic_sub_32(volatile int32_t* v, int dec) { int32_t t; @@ -222,7 +252,28 @@ return t; } +#else /* OPAL_ASM_ARM_VERSION <=5 or no GCC inline assembly */ -#endif /* OMPI_GCC_INLINE_ASSEMBLY */ +#define OPAL_HAVE_ATOMIC_CMPSET_32 1 +#define __kuser_cmpxchg (*((int (*)(int, int, volatile int*))(0xffff0fc0))) +static inline int opal_atomic_cmpset_32(volatile int32_t *addr, + int32_t oldval, int32_t newval) +{ + return !(__kuser_cmpxchg(oldval, newval, addr)); +} +static inline int opal_atomic_cmpset_acq_32(volatile int32_t *addr, + int32_t oldval, int32_t newval) +{ + return opal_atomic_cmpset_32(addr, oldval, newval); +} + +static inline int opal_atomic_cmpset_rel_32(volatile int32_t *addr, + int32_t oldval, int32_t newval) +{ + return opal_atomic_cmpset_32(addr, oldval, newval); +} + +#endif + #endif /* ! OMPI_SYS_ARCH_ATOMIC_H */ Index: opal/config/opal_config_asm.m4 =================================================================== --- opal/config/opal_config_asm.m4 (revision 26270) +++ opal/config/opal_config_asm.m4 (working copy) @@ -915,9 +915,31 @@ armv7*) ompi_cv_asm_arch="ARM" OPAL_ASM_SUPPORT_64BIT=1 + OPAL_ASM_ARM_VERSION=7 + AC_DEFINE_UNQUOTED([OPAL_ASM_ARM_VERSION], [$OPAL_ASM_ARM_VERSION], + [What ARM assembly version to use]) OMPI_GCC_INLINE_ASSIGN='"mov %0, #0" : "=&r"(ret)' ;; + armv6*) + ompi_cv_asm_arch="ARM" + OPAL_ASM_SUPPORT_64BIT=0 + OPAL_ASM_ARM_VERSION=6 + AC_DEFINE_UNQUOTED([OPAL_ASM_ARM_VERSION], [$OPAL_ASM_ARM_VERSION], + [What ARM assembly version to use]) + OMPI_GCC_INLINE_ASSIGN='"mov %0, #0" : "=&r"(ret)' + ;; + + armv5*linux*|armv4*linux*) + # uses Linux kernel helpers for some atomic operations + ompi_cv_asm_arch="ARM" + OPAL_ASM_SUPPORT_64BIT=0 + OPAL_ASM_ARM_VERSION=5 + AC_DEFINE_UNQUOTED([OPAL_ASM_ARM_VERSION], [$OPAL_ASM_ARM_VERSION], + [What ARM assembly version to use]) + OMPI_GCC_INLINE_ASSIGN='"mov %0, #0" : "=&r"(ret)' + ;; + mips-*|mips64*) # Should really find some way to make sure that we are on # a MIPS III machine (r4000 and later)