From b04a70177b0ec20371a915805a34db242fc273be Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Thu, 13 Nov 2014 13:41:15 +0100 Subject: [PATCH] base & arm: simplify and optimize cmpxchg The old inline assembly provided two output operands that were afterwards combined for a return value. However, the second output operand isn't necessary when using the "Acquiring a Lock" example-code of the ARM manual "Barrier Litmus Tests and Cookbook". This saves two logical operations per acquisition try. Additionally better documentation is now provided. Fixes #1292 --- repos/base/include/spec/arm/cpu/atomic.h | 41 +++++++++++++++--------- 1 file changed, 25 insertions(+), 16 deletions(-) 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; } }