diff --git a/base/include/arm/cpu/atomic.h b/base/include/arm/cpu/atomic.h new file mode 100644 index 000000000..3015444d4 --- /dev/null +++ b/base/include/arm/cpu/atomic.h @@ -0,0 +1,54 @@ +/* + * \brief Atomic operations for ARM + * \author Norman Feske + * \author Stefan Kalkowski + * \date 2007-04-28 + */ + +/* + * Copyright (C) 2007-2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__ARM__CPU__ATOMIC_H_ +#define _INCLUDE__ARM__CPU__ATOMIC_H_ + +namespace Genode { + + /** + * Atomic compare and exchange + * + * This function compares the value at dest with cmp_val. + * If both values are equal, dest is set to new_val. If + * both values are different, the value at dest remains + * unchanged. + * + * \return 1 if the value was successfully changed to new_val, + * 0 if cmp_val and the value at dest differ. + */ + inline int cmpxchg(volatile int *dest, int cmp_val, int new_val) + { + unsigned long equal, not_exclusive; + + __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) + : "cc"); + return equal && !not_exclusive; + } +} + +#endif /* _INCLUDE__ARM__CPU__ATOMIC_H_ */