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 */
 }
 
 /*

Reply via email to