diff options
author | Patrick Trantham <patrick.trantham@fuel7.com> | 2012-04-13 10:48:15 -0500 |
---|---|---|
committer | Martin Sustrik <sustrik@250bpm.com> | 2012-04-29 07:30:32 +0200 |
commit | 98d4e212bc6379888c006aadb89eb1b96e0b3ddb (patch) | |
tree | b7a4468d26d3c4363efbd75b4c49988699bc2cab | |
parent | 4cd65e7c488379f4f4a719a6400c839b61c61f7c (diff) |
Implement atomic operations for armv7a
This commit implements atomic operations for the armv7a architecture
using gcc inline assembly. This offers higher performance compared to
pthread mutexes.
Tested on an am3517 evm, clocked at 600MHz:
./inproc_thr 200 1000000
------------------------
53-60K messages / sec, pthread mutexes
73-90K messages / sec, assembly atomic ops
./inproc_lat 200 1000000
------------------------
average latency: 42.234 [us], pthread mutexes
average latency: 35.496 [us], assembly atomic ops
-rw-r--r-- | src/atomic_counter.hpp | 34 | ||||
-rw-r--r-- | src/atomic_ptr.hpp | 37 |
2 files changed, 69 insertions, 2 deletions
diff --git a/src/atomic_counter.hpp b/src/atomic_counter.hpp index 914afdc..07002af 100644 --- a/src/atomic_counter.hpp +++ b/src/atomic_counter.hpp @@ -1,7 +1,7 @@ /* Copyright (c) 2009-2012 250bpm s.r.o. Copyright (c) 2007-2009 iMatix Corporation - Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file + Copyright (c) 2007-2012 Other contributors as noted in the AUTHORS file This file is part of Crossroads I/O project. @@ -29,6 +29,8 @@ #define XS_ATOMIC_COUNTER_MUTEX #elif (defined __i386__ || defined __x86_64__) && defined __GNUC__ #define XS_ATOMIC_COUNTER_X86 +#elif defined __ARM_ARCH_7A__ && defined __GNUC__ +#define XS_ATOMIC_COUNTER_ARM #elif defined XS_HAVE_WINDOWS #define XS_ATOMIC_COUNTER_WINDOWS #elif (defined XS_HAVE_SOLARIS || defined XS_HAVE_NETBSD) @@ -88,6 +90,19 @@ namespace xs : "=r" (old_value), "=m" (value) : "0" (increment_), "m" (value) : "cc", "memory"); +#elif defined XS_ATOMIC_COUNTER_ARM + integer_t flag, tmp; + __asm__ volatile ( + " dmb sy\n\t" + "1: ldrex %0, [%5]\n\t" + " add %2, %0, %4\n\t" + " strex %1, %2, [%5]\n\t" + " teq %1, #0\n\t" + " bne 1b\n\t" + " dmb sy\n\t" + : "=&r"(old_value), "=&r"(flag), "=&r"(tmp), "+Qo"(value) + : "Ir"(increment_), "r"(&value) + : "cc"); #elif defined XS_ATOMIC_COUNTER_MUTEX sync.lock (); old_value = value; @@ -118,6 +133,20 @@ namespace xs : "0" (oldval), "m" (*val) : "cc", "memory"); return oldval != decrement; +#elif defined XS_ATOMIC_COUNTER_ARM + integer_t old_value, flag, tmp; + __asm__ volatile ( + " dmb sy\n\t" + "1: ldrex %0, [%5]\n\t" + " sub %2, %0, %4\n\t" + " strex %1, %2, [%5]\n\t" + " teq %1, #0\n\t" + " bne 1b\n\t" + " dmb sy\n\t" + : "=&r"(old_value), "=&r"(flag), "=&r"(tmp), "+Qo"(value) + : "Ir"(decrement), "r"(&value) + : "cc"); + return old_value - decrement != 0; #elif defined XS_ATOMIC_COUNTER_MUTEX sync.lock (); value -= decrement; @@ -157,6 +186,9 @@ namespace xs #if defined XS_ATOMIC_COUNTER_X86 #undef XS_ATOMIC_COUNTER_X86 #endif +#if defined XS_ATOMIC_COUNTER_ARM +#undef XS_ATOMIC_COUNTER_ARM +#endif #if defined XS_ATOMIC_COUNTER_MUTEX #undef XS_ATOMIC_COUNTER_MUTEX #endif diff --git a/src/atomic_ptr.hpp b/src/atomic_ptr.hpp index b197aa1..8d4c770 100644 --- a/src/atomic_ptr.hpp +++ b/src/atomic_ptr.hpp @@ -1,7 +1,7 @@ /* Copyright (c) 2009-2012 250bpm s.r.o. Copyright (c) 2007-2009 iMatix Corporation - Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file + Copyright (c) 2007-2012 Other contributors as noted in the AUTHORS file This file is part of Crossroads I/O project. @@ -30,6 +30,8 @@ #define XS_ATOMIC_PTR_MUTEX #elif (defined __i386__ || defined __x86_64__) && defined __GNUC__ #define XS_ATOMIC_PTR_X86 +#elif defined __ARM_ARCH_7A__ && defined __GNUC__ +#define XS_ATOMIC_PTR_ARM #elif defined XS_HAVE_WINDOWS #define XS_ATOMIC_PTR_WINDOWS #elif (defined XS_HAVE_SOLARIS || defined XS_HAVE_NETBSD) @@ -89,6 +91,20 @@ namespace xs : "=r" (old), "=m" (ptr) : "m" (ptr), "0" (val_)); return old; +#elif defined XS_ATOMIC_PTR_ARM + T* old; + unsigned int flag; + __asm__ volatile ( + " dmb sy\n\t" + "1: ldrex %1, [%3]\n\t" + " strex %0, %4, [%3]\n\t" + " teq %0, #0\n\t" + " bne 1b\n\t" + " dmb sy\n\t" + : "=&r"(flag), "=&r"(old), "+Qo"(ptr) + : "r"(&ptr), "r"(val_) + : "cc"); + return old; #elif defined XS_ATOMIC_PTR_MUTEX sync.lock (); T *old = (T*) ptr; @@ -119,6 +135,22 @@ namespace xs : "r" (val_), "m" (ptr), "0" (cmp_) : "cc"); return old; +#elif defined XS_ATOMIC_PTR_ARM + T *old; + unsigned int flag; + __asm__ volatile ( + " dmb sy\n\t" + "1: ldrex %1, [%3]\n\t" + " mov %0, #0\n\t" + " teq %1, %4\n\t" + " strexeq %0, %5, [%3]\n\t" + " teq %0, #0\n\t" + " bne 1b\n\t" + " dmb sy\n\t" + : "=&r"(flag), "=&r"(old), "+Qo"(ptr) + : "r"(&ptr), "r"(cmp_), "r"(val_) + : "cc"); + return old; #elif defined XS_ATOMIC_PTR_MUTEX sync.lock (); T *old = (T*) ptr; @@ -154,6 +186,9 @@ namespace xs #if defined XS_ATOMIC_PTR_X86 #undef XS_ATOMIC_PTR_X86 #endif +#if defined XS_ATOMIC_PTR_ARM +#undef XS_ATOMIC_PTR_ARM +#endif #if defined XS_ATOMIC_PTR_MUTEX #undef XS_ATOMIC_PTR_MUTEX #endif |