summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Trantham <patrick.trantham@fuel7.com>2012-04-13 10:48:15 -0500
committerMartin Sustrik <sustrik@250bpm.com>2012-04-29 07:30:32 +0200
commit98d4e212bc6379888c006aadb89eb1b96e0b3ddb (patch)
treeb7a4468d26d3c4363efbd75b4c49988699bc2cab
parent4cd65e7c488379f4f4a719a6400c839b61c61f7c (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.hpp34
-rw-r--r--src/atomic_ptr.hpp37
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