diff --git a/repos/base/include/spec/arm/cpu/atomic.h b/repos/base/include/spec/arm/cpu/atomic.h index 7081338d5b..8b50423b1a 100644 --- a/repos/base/include/spec/arm/cpu/atomic.h +++ b/repos/base/include/spec/arm/cpu/atomic.h @@ -2,6 +2,7 @@ * \brief Atomic operations for ARM * \author Norman Feske * \author Stefan Kalkowski + * \author Martin Stein * \date 2007-04-28 */ @@ -34,25 +35,33 @@ namespace Genode { */ inline int cmpxchg(volatile int *dest, int cmp_val, int new_val) { - unsigned long equal, not_exclusive; + int result; + asm volatile ( - __asm__ __volatile__( - "@ cmpxchg\n" - " 1: \n" - " ldrex %0, [%2] \n" - " cmp %0, %3 \n" - " bne 2f \n" - " strexeq %0, %4, [%2]\n" - " teqeq %0, #0 \n" - " bne 1b \n" - " moveq %1, #1 \n" - " 2: \n" - " movne %1, #0 \n" - : "=&r" (not_exclusive), "=&r" (equal) - : "r" (dest), "r" (cmp_val), "r" (new_val) + /* compare values */ + "1:\n" + "ldrex %0, [%1]\n" + "cmp %0, %2\n" + + /* if not equal, return with result 0 */ + "movne %0, #0\n" + "bne 2f\n" + + /* if equal, try to override memory value exclusively */ + "strex %0, %3, [%1]\n" + "cmp %0, #0\n" + + /* if access wasn't exclusive, go back to comparison */ + "bne 1b\n" + + /* if access was exclusive, return with result 1 */ + "mov %0, #1\n" + "2:\n" + : "=&r" (result) : "r" (dest), "r" (cmp_val), "r" (new_val) : "cc"); + Genode::memory_barrier(); - return equal && !not_exclusive; + return result; } }