git: fb63bc67483e - main - atomic: Implement atomic_{set,clear}_8 in _atomic_subword.h
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 03 Aug 2026 15:23:05 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=fb63bc67483ee52245d6161150702974da3d001c
commit fb63bc67483ee52245d6161150702974da3d001c
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-08-03 14:02:33 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
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 */
}
/*