git: fb63bc67483e - main - atomic: Implement atomic_{set,clear}_8 in _atomic_subword.h

Mark Johnston <[email protected]> Mon, 03 Aug 2026 15:23:05 +0000
Newsgroups gmane.os.freebsd.devel.cvs.src
Message-ID <6a70b259.3b34b.2d962251__30754.975932517$1785770626$gmane$org@gitrepo.freebsd.org>
The branch main has been updated by markj:

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

commit fb63bc67483ee52245d6161150702974da3d001c
Author:     Mark Johnston <[email protected]>
AuthorDate: 2026-08-03 14:02:33 +0000
Commit:     Mark Johnston <[email protected]>
CommitDate: 2026-08-03 15:22:13 +0000

    atomic: Implement atomic_{set,clear}_8 in _atomic_subword.h
    
    Reimplement atomic_{set,clear}_16 using atomic_set_32.
    
    Remove emulation of these operations from vm_page.c.
    
    Reviewed by:    alc, kib
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D58580
---
 sys/sys/_atomic_subword.h | 54 +++++++++++++++++++++++----------
 sys/vm/vm_page.c          | 76 ++++++-----------------------------------------
 2 files changed, 48 insertions(+), 82 deletions(-)

diff --git a/sys/sys/_atomic_subword.h b/sys/sys/_atomic_subword.h
index 284e2bfa340f..907fef0bb193 100644
--- a/sys/sys/_atomic_subword.h
+++ b/sys/sys/_atomic_subword.h
@@ -201,21 +201,42 @@ atomic_load_acq_16(const volatile uint16_t *p)
 }
 #endif
 
-#undef _ATOMIC_WORD_ALIGNED
-#undef _ATOMIC_BYTE_SHIFT
-#undef _ATOMIC_HWORD_SHIFT
+#ifndef atomic_set_8
+static __inline void
+atomic_set_8(volatile uint8_t *p, uint8_t bit)
+{
+	uint32_t *addr;
+	int shift;
+
+	addr = _ATOMIC_WORD_ALIGNED(p);
+	shift = _ATOMIC_BYTE_SHIFT(p);
+	atomic_set_32(addr, (uint32_t)bit << shift);
+}
+#endif
 
 #ifndef atomic_set_16
 static __inline void
 atomic_set_16(volatile uint16_t *p, uint16_t bit)
 {
-	uint16_t v;
+	uint32_t *addr;
+	int shift;
+
+	addr = _ATOMIC_WORD_ALIGNED(p);
+	shift = _ATOMIC_HWORD_SHIFT(p);
+	atomic_set_32(addr, (uint32_t)bit << shift);
+}
+#endif
+
+#ifndef atomic_clear_8
+static __inline void
+atomic_clear_8(volatile uint8_t *p, uint8_t bit)
+{
+	uint32_t *addr;
+	int shift;
 
-	v = atomic_load_16(p);
-	for (;;) {
-		if (atomic_fcmpset_16(p, &v, v | bit))
-			break;
-	}
+	addr = _ATOMIC_WORD_ALIGNED(p);
+	shift = _ATOMIC_BYTE_SHIFT(p);
+	atomic_clear_32(addr, (uint32_t)bit << shift);
 }
 #endif
 
@@ -223,14 +244,17 @@ atomic_set_16(volatile uint16_t *p, uint16_t bit)
 static __inline void
 atomic_clear_16(volatile uint16_t *p, uint16_t bit)
 {
-	uint16_t v;
+	uint32_t *addr;
+	int shift;
 
-	v = atomic_load_16(p);
-	for (;;) {
-		if (atomic_fcmpset_16(p, &v, v & ~bit))
-			break;
-	}
+	addr = _ATOMIC_WORD_ALIGNED(p);
+	shift = _ATOMIC_HWORD_SHIFT(p);
+	atomic_clear_32(addr, (uint32_t)bit << shift);
 }
 #endif
 
+#undef _ATOMIC_WORD_ALIGNED
+#undef _ATOMIC_BYTE_SHIFT
+#undef _ATOMIC_HWORD_SHIFT
+
 #endif	/* _SYS__ATOMIC_SUBWORD_H_ */
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 130d084815f6..98d0472c8487 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -5378,67 +5378,33 @@ vm_page_bits(int base, int size)
 void
 vm_page_bits_set(vm_page_t m, vm_page_bits_t *bits, vm_page_bits_t set)
 {
-
 #if PAGE_SIZE == 32768
 	atomic_set_64((uint64_t *)bits, set);
 #elif PAGE_SIZE == 16384
 	atomic_set_32((uint32_t *)bits, set);
-#elif (PAGE_SIZE == 8192) && defined(atomic_set_16)
+#elif PAGE_SIZE == 8192
 	atomic_set_16((uint16_t *)bits, set);
-#elif (PAGE_SIZE == 4096) && defined(atomic_set_8)
+#elif PAGE_SIZE == 4096
 	atomic_set_8((uint8_t *)bits, set);
-#else		/* PAGE_SIZE <= 8192 */
-	uintptr_t addr;
-	int shift;
-
-	addr = (uintptr_t)bits;
-	/*
-	 * Use a trick to perform a 32-bit atomic on the
-	 * containing aligned word, to not depend on the existence
-	 * of atomic_{set, clear}_{8, 16}.
-	 */
-	shift = addr & (sizeof(uint32_t) - 1);
-#if BYTE_ORDER == BIG_ENDIAN
-	shift = (sizeof(uint32_t) - sizeof(vm_page_bits_t) - shift) * NBBY;
 #else
-	shift *= NBBY;
+#error unhandled page size
 #endif
-	addr &= ~(sizeof(uint32_t) - 1);
-	atomic_set_32((uint32_t *)addr, set << shift);
-#endif		/* PAGE_SIZE */
 }
 
 static inline void
 vm_page_bits_clear(vm_page_t m, vm_page_bits_t *bits, vm_page_bits_t clear)
 {
-
 #if PAGE_SIZE == 32768
 	atomic_clear_64((uint64_t *)bits, clear);
 #elif PAGE_SIZE == 16384
 	atomic_clear_32((uint32_t *)bits, clear);
-#elif (PAGE_SIZE == 8192) && defined(atomic_clear_16)
+#elif PAGE_SIZE == 8192
 	atomic_clear_16((uint16_t *)bits, clear);
-#elif (PAGE_SIZE == 4096) && defined(atomic_clear_8)
+#elif PAGE_SIZE == 4096
 	atomic_clear_8((uint8_t *)bits, clear);
-#else		/* PAGE_SIZE <= 8192 */
-	uintptr_t addr;
-	int shift;
-
-	addr = (uintptr_t)bits;
-	/*
-	 * Use a trick to perform a 32-bit atomic on the
-	 * containing aligned word, to not depend on the existence
-	 * of atomic_{set, clear}_{8, 16}.
-	 */
-	shift = addr & (sizeof(uint32_t) - 1);
-#if BYTE_ORDER == BIG_ENDIAN
-	shift = (sizeof(uint32_t) - sizeof(vm_page_bits_t) - shift) * NBBY;
 #else
-	shift *= NBBY;
+#error unhandled page size
 #endif
-	addr &= ~(sizeof(uint32_t) - 1);
-	atomic_clear_32((uint32_t *)addr, clear << shift);
-#endif		/* PAGE_SIZE */
 }
 
 static inline vm_page_bits_t
@@ -5456,45 +5422,21 @@ vm_page_bits_swap(vm_page_t m, vm_page_bits_t *bits, vm_page_bits_t newbits)
 	old = *bits;
 	while (atomic_fcmpset_32(bits, &old, newbits) == 0);
 	return (old);
-#elif (PAGE_SIZE == 8192) && defined(atomic_fcmpset_16)
+#elif PAGE_SIZE == 8192
 	uint16_t old;
 
 	old = *bits;
 	while (atomic_fcmpset_16(bits, &old, newbits) == 0);
 	return (old);
-#elif (PAGE_SIZE == 4096) && defined(atomic_fcmpset_8)
+#elif PAGE_SIZE == 4096
 	uint8_t old;
 
 	old = *bits;
 	while (atomic_fcmpset_8(bits, &old, newbits) == 0);
 	return (old);
-#else		/* PAGE_SIZE <= 4096*/
-	uintptr_t addr;
-	uint32_t old, new, mask;
-	int shift;
-
-	addr = (uintptr_t)bits;
-	/*
-	 * Use a trick to perform a 32-bit atomic on the
-	 * containing aligned word, to not depend on the existence
-	 * of atomic_{set, swap, clear}_{8, 16}.
-	 */
-	shift = addr & (sizeof(uint32_t) - 1);
-#if BYTE_ORDER == BIG_ENDIAN
-	shift = (sizeof(uint32_t) - sizeof(vm_page_bits_t) - shift) * NBBY;
 #else
-	shift *= NBBY;
+#error unhandled page size
 #endif
-	addr &= ~(sizeof(uint32_t) - 1);
-	mask = VM_PAGE_BITS_ALL << shift;
-
-	old = *bits;
-	do {
-		new = old & ~mask;
-		new |= newbits << shift;
-	} while (atomic_fcmpset_32((uint32_t *)addr, &old, new) == 0);
-	return (old >> shift);
-#endif		/* PAGE_SIZE */
 }
 
 /*