diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2013-02-14 11:36:06 +0400 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2013-02-14 11:36:06 +0400 |
commit | ad70f34ff55146a66b761d95e20199b792407f0c (patch) | |
tree | 74936d431453a815efb8142e98d89bf3a6ff3963 | |
parent | 31aba24cf225fde556bd005a0a92278f885822b8 (diff) | |
download | libatomic_ops-ad70f34ff55146a66b761d95e20199b792407f0c.tar.gz |
Define AO_nop_full as compiler barrier for pre-ARMv6 single-core case
* src/atomic_ops/sysdeps/gcc/arm.h (AO_nop_full): Define for pre-ARMv6
as well (as a compiler barrier) if AO_UNIPROCESSOR; refine comment.
* src/atomic_ops/sysdeps/msftc/arm.h (AO_nop_full): Likewise.
* src/atomic_ops/sysdeps/msftc/arm.h: Eliminate duplicated include of
test_and_set_t_is_ao_t.h.
-rw-r--r-- | src/atomic_ops/sysdeps/gcc/arm.h | 107 | ||||
-rw-r--r-- | src/atomic_ops/sysdeps/msftc/arm.h | 13 |
2 files changed, 60 insertions, 60 deletions
diff --git a/src/atomic_ops/sysdeps/gcc/arm.h b/src/atomic_ops/sysdeps/gcc/arm.h index 746f11b..17cb568 100644 --- a/src/atomic_ops/sysdeps/gcc/arm.h +++ b/src/atomic_ops/sysdeps/gcc/arm.h @@ -78,6 +78,61 @@ /* Note: ARMv6M is excluded due to no ARM mode support. */ #endif /* !__thumb2__ */ +#ifdef AO_UNIPROCESSOR + /* If only a single processor (core) is used, AO_UNIPROCESSOR could */ + /* be defined by the client to avoid unnecessary memory barrier. */ + AO_INLINE void + AO_nop_full(void) + { + AO_compiler_barrier(); + } +# define AO_HAVE_nop_full + +#elif defined(AO_ARM_HAVE_DMB) + /* ARMv7 is compatible to ARMv6 but has a simpler command for issuing */ + /* a memory barrier (DMB). Raising it via CP15 should still work */ + /* (but slightly less efficient because it requires the use of */ + /* a general-purpose register). */ + AO_INLINE void + AO_nop_full(void) + { + /* AO_THUMB_GO_ARM is empty. */ + __asm__ __volatile__("dmb" : : : "memory"); + } +# define AO_HAVE_nop_full + + AO_INLINE void + AO_nop_write(void) + { + /* AO_THUMB_GO_ARM is empty. */ + __asm__ __volatile__("dmb st" : : : "memory"); + } +# define AO_HAVE_nop_write + +#elif defined(AO_ARM_HAVE_LDREX) + /* ARMv6 is the first architecture providing support for a simple */ + /* LL/SC. A data memory barrier must be raised via CP15 command. */ + AO_INLINE void + AO_nop_full(void) + { + unsigned dest = 0; + + /* Issue a data memory barrier (keeps ordering of memory */ + /* transactions before and after this operation). */ + __asm__ __volatile__("@AO_nop_full\n" + AO_THUMB_GO_ARM + " mcr p15,0,%0,c7,c10,5\n" + AO_THUMB_RESTORE_MODE + : "=&r"(dest) + : /* empty */ + : AO_THUMB_SWITCH_CLOBBERS "memory"); + } +# define AO_HAVE_nop_full + +#else + /* AO_nop_full() is emulated using AO_test_and_set_full(). */ +#endif /* !AO_UNIPROCESSOR && !AO_ARM_HAVE_LDREX */ + #ifdef AO_ARM_HAVE_LDREX /* AO_t/char/short/int load is simple reading. */ @@ -87,58 +142,6 @@ # define AO_ACCESS_int_CHECK_ALIGNED # include "../all_atomic_only_load.h" - /* ARMv6 is the first architecture providing support for simple */ - /* LL/SC. A data memory barrier must be raised via CP15 command (see */ - /* documentation). ARMv7 is compatible to ARMv6 but has a simpler */ - /* command for issuing a memory barrier (DMB). Raising it via CP15 */ - /* should still work (but slightly less efficient because it requires */ - /* the use of a general-purpose register). If only a single */ - /* processor (core) is used, AO_UNIPROCESSOR could be defined by */ - /* client to avoid unnecessary memory barrier. */ - -# if defined(AO_ARM_HAVE_DMB) && !defined(AO_UNIPROCESSOR) - - AO_INLINE void - AO_nop_full(void) - { - /* AO_THUMB_GO_ARM is empty. */ - __asm__ __volatile__("dmb" : : : "memory"); - } -# define AO_HAVE_nop_full - - AO_INLINE void - AO_nop_write(void) - { - /* AO_THUMB_GO_ARM is empty. */ - __asm__ __volatile__("dmb st" : : : "memory"); - } -# define AO_HAVE_nop_write - -# else - - AO_INLINE void - AO_nop_full(void) - { -# ifndef AO_UNIPROCESSOR - unsigned dest = 0; - - /* Issue a data memory barrier (keeps ordering of memory */ - /* transactions before and after this operation). */ - __asm__ __volatile__("@AO_nop_full\n" - AO_THUMB_GO_ARM - " mcr p15,0,%0,c7,c10,5\n" - AO_THUMB_RESTORE_MODE - : "=&r"(dest) - : /* empty */ - : AO_THUMB_SWITCH_CLOBBERS "memory"); -# else - AO_compiler_barrier(); -# endif - } -# define AO_HAVE_nop_full - -# endif /* !AO_ARM_HAVE_DMB */ - /* "ARM Architecture Reference Manual" (chapter A3.5.3) says that the */ /* single-copy atomic processor accesses are all byte accesses, all */ /* halfword accesses to halfword-aligned locations, all word accesses */ diff --git a/src/atomic_ops/sysdeps/msftc/arm.h b/src/atomic_ops/sysdeps/msftc/arm.h index cd7500a..c01bef1 100644 --- a/src/atomic_ops/sysdeps/msftc/arm.h +++ b/src/atomic_ops/sysdeps/msftc/arm.h @@ -28,8 +28,8 @@ /* FIXME: Do _InterlockedOps really have a full memory barrier? */ /* (MSDN WinCE docs say nothing about it.) */ -#if _M_ARM >= 6 -/* ARMv6 is the first architecture providing support for simple LL/SC. */ +#include "../test_and_set_t_is_ao_t.h" +/* AO_test_and_set_full() is emulated using CAS. */ /* If only a single processor is used, we can define AO_UNIPROCESSOR. */ #ifdef AO_UNIPROCESSOR @@ -39,11 +39,11 @@ } # define AO_HAVE_nop_full #else -/* AO_nop_full() is emulated using AO_test_and_set_full(). */ + /* AO_nop_full() is emulated using AO_test_and_set_full(). */ #endif -#include "../test_and_set_t_is_ao_t.h" -/* AO_test_and_set() is emulated using CAS. */ +#if _M_ARM >= 6 +/* ARMv6 is the first architecture providing support for simple LL/SC. */ AO_INLINE AO_t AO_load(const volatile AO_t *addr) @@ -66,9 +66,6 @@ AO_load(const volatile AO_t *addr) /* else is. It appears that SWP is the only simple memory barrier. */ #include "../all_atomic_load_store.h" -#include "../test_and_set_t_is_ao_t.h" -/* AO_test_and_set_full() is emulated using CAS. */ - #endif /* _M_ARM < 6 */ #define AO_T_IS_INT |