[Concept,19/19] asm-generic: atomic: Add xchg() and try_cmpxchg() macros
Commit Message
From: Simon Glass <simon.glass@canonical.com>
Move xchg and try_cmpxchg macros to asm-generic/atomic.h alongside
cmpxchg, as they are all atomic exchange operations.
Add:
- try_cmpxchg() - compare and exchange with boolean return and
old value update on failure
- xchg() - atomic exchange, stores new value and returns old
These are single-threaded implementations for U-Boot.
Add #ifndef guards to all three macros (cmpxchg, try_cmpxchg, xchg)
to avoid redefinition warnings on architectures like MIPS that provide
their own implementations.
Signed-off-by: Simon Glass <simon.glass@canonical.com>
Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
---
fs/ext4l/ext4_uboot.h | 12 ++----------
include/asm-generic/atomic.h | 37 ++++++++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+), 10 deletions(-)
@@ -949,14 +949,7 @@ typedef unsigned int projid_t;
* Additional stubs for inode.c
*/
-/* try_cmpxchg - compare and exchange with return value */
-#define try_cmpxchg(ptr, old, new) ({ \
- typeof(*(old)) __old = *(old); \
- typeof(*(ptr)) __ret = cmpxchg(ptr, __old, (new)); \
- if (__ret != __old) \
- *(old) = __ret; \
- __ret == __old; \
-})
+/* try_cmpxchg is now in asm-generic/atomic.h */
/* hash_64 - simple 64-bit hash */
#define hash_64(val, bits) ((unsigned long)((val) >> (64 - (bits))))
@@ -1743,8 +1736,7 @@ static inline unsigned long ext4_find_next_bit_le(const void *addr,
/* refcount operations are now in linux/refcount.h */
-/* xchg - exchange value atomically */
-#define xchg(ptr, new) ({ typeof(*(ptr)) __old = *(ptr); *(ptr) = (new); __old; })
+/* xchg is now in asm-generic/atomic.h */
/* printk_ratelimited is in linux/printk.h */
@@ -209,6 +209,7 @@ static inline void atomic64_dec(volatile atomic64_t *v)
* Single-threaded version for U-Boot. Atomically compares *ptr with old
* and if equal, stores new. Returns the original value of *ptr.
*/
+#ifndef cmpxchg
#define cmpxchg(ptr, old, new) ({ \
typeof(*(ptr)) __cmpxchg_old = (old); \
typeof(*(ptr)) __cmpxchg_new = (new); \
@@ -217,5 +218,41 @@ static inline void atomic64_dec(volatile atomic64_t *v)
*(ptr) = __cmpxchg_new; \
__cmpxchg_ret; \
})
+#endif
+
+/**
+ * try_cmpxchg - compare and exchange with boolean return
+ * @ptr: pointer to the value
+ * @oldp: pointer to expected old value (updated on failure)
+ * @new: new value to store if current equals old
+ *
+ * Returns true if exchange succeeded, false otherwise.
+ * On failure, *oldp is updated with the current value.
+ */
+#ifndef try_cmpxchg
+#define try_cmpxchg(ptr, oldp, new) ({ \
+ typeof(*(oldp)) __old = *(oldp); \
+ typeof(*(ptr)) __ret = cmpxchg(ptr, __old, (new)); \
+ if (__ret != __old) \
+ *(oldp) = __ret; \
+ __ret == __old; \
+})
+#endif
+
+/**
+ * xchg - exchange value atomically
+ * @ptr: pointer to the value
+ * @new: new value to store
+ *
+ * Atomically stores new value and returns the old value.
+ * Single-threaded version for U-Boot.
+ */
+#ifndef xchg
+#define xchg(ptr, new) ({ \
+ typeof(*(ptr)) __xchg_old = *(ptr); \
+ *(ptr) = (new); \
+ __xchg_old; \
+})
+#endif
#endif