git: cd22fd0549c9 - main - powerpc: Add ISA 2.06 sub-word atomic set/clear

From: Justin Hibbits <jhibbits_at_FreeBSD.org>
Date: Sat, 17 Jan 2026 04:10:13 UTC
The branch main has been updated by jhibbits:

URL: https://cgit.FreeBSD.org/src/commit/?id=cd22fd0549c9a65b8806fd013f98be89c34c44f7

commit cd22fd0549c9a65b8806fd013f98be89c34c44f7
Author:     Justin Hibbits <jhibbits@FreeBSD.org>
AuthorDate: 2025-09-22 14:35:59 +0000
Commit:     Justin Hibbits <jhibbits@FreeBSD.org>
CommitDate: 2026-01-17 04:10:02 +0000

    powerpc: Add ISA 2.06 sub-word atomic set/clear
    
    Add atomic_set/clear_short/char for doing 8-bit and 16-bit operations
    more efficiently on "newer" architectures (POWER7 and later).
    
    Piggybacks on b31abc95eb.
---
 sys/powerpc/include/atomic.h | 82 ++++++++++++++++++++++++++++++--------------
 1 file changed, 56 insertions(+), 26 deletions(-)

diff --git a/sys/powerpc/include/atomic.h b/sys/powerpc/include/atomic.h
index b2d7549e5bd0..60fb678e6b41 100644
--- a/sys/powerpc/include/atomic.h
+++ b/sys/powerpc/include/atomic.h
@@ -165,6 +165,28 @@ _ATOMIC_ADD(long)
  * { *p &= ~v; }
  */
 
+#ifdef	ISA_206_ATOMICS
+#define __atomic_clear_char(p, v, t)				\
+    __asm __volatile(						\
+	"1:	lbarx	%0, 0, %2\n"				\
+	"	andc	%0, %0, %3\n"				\
+	"	stbcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cr0", "memory")					\
+    /* __atomic_clear_short */
+#define __atomic_clear_short(p, v, t)				\
+    __asm __volatile(						\
+	"1:	lharx	%0, 0, %2\n"				\
+	"	andc	%0, %0, %3\n"				\
+	"	sthcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cr0", "memory")					\
+    /* __atomic_clear_short */
+#endif
 #define __atomic_clear_int(p, v, t)				\
     __asm __volatile(						\
 	"1:	lwarx	%0, 0, %2\n"				\
@@ -222,6 +244,11 @@ _ATOMIC_ADD(long)
     }								\
     /* _ATOMIC_CLEAR */
 
+#ifdef	ISA_206_ATOMICS
+_ATOMIC_CLEAR(char)
+_ATOMIC_CLEAR(short)
+#endif
+
 _ATOMIC_CLEAR(int)
 _ATOMIC_CLEAR(long)
 
@@ -265,6 +292,28 @@ _ATOMIC_CLEAR(long)
  * atomic_set(p, v)
  * { *p |= v; }
  */
+#ifdef	ISA_206_ATOMICS
+#define __atomic_set_char(p, v, t)				\
+    __asm __volatile(						\
+	"1:	lbarx	%0, 0, %2\n"				\
+	"	or	%0, %3, %0\n"				\
+	"	stbcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cr0", "memory")					\
+    /* __atomic_set_char */
+#define __atomic_set_short(p, v, t)				\
+    __asm __volatile(						\
+	"1:	lharx	%0, 0, %2\n"				\
+	"	or	%0, %3, %0\n"				\
+	"	sthcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cr0", "memory")					\
+    /* __atomic_set_short */
+#endif
 
 #define __atomic_set_int(p, v, t)				\
     __asm __volatile(						\
@@ -323,6 +372,11 @@ _ATOMIC_CLEAR(long)
     }								\
     /* _ATOMIC_SET */
 
+#ifdef	ISA_206_ATOMICS
+_ATOMIC_SET(char)
+_ATOMIC_SET(short)
+#endif
+
 _ATOMIC_SET(int)
 _ATOMIC_SET(long)
 
@@ -1140,34 +1194,10 @@ atomic_thread_fence_seq_cst(void)
 #define	atomic_set_short	atomic_set_16
 #define	atomic_clear_short	atomic_clear_16
 #else
-
-static __inline void
-atomic_set_short(volatile u_short *p, u_short bit)
-{
-	u_short v;
-
-	v = atomic_load_short(p);
-	for (;;) {
-		if (atomic_fcmpset_16(p, &v, v | bit))
-			break;
-	}
-}
-
-static __inline void
-atomic_clear_short(volatile u_short *p, u_short bit)
-{
-	u_short v;
-
-	v = atomic_load_short(p);
-	for (;;) {
-		if (atomic_fcmpset_16(p, &v, v & ~bit))
-			break;
-	}
-}
-
+#define	atomic_set_8		atomic_set_char
+#define	atomic_clear_8		atomic_clear_char
 #define	atomic_set_16		atomic_set_short
 #define	atomic_clear_16		atomic_clear_short
-
 #endif	/* ISA_206_ATOMICS */
 
 /* These need sys/_atomic_subword.h on non-ISA-2.06-atomic platforms. */