| 4949 | } |
| 4950 | |
| 4951 | static inline vm_page_bits_t |
| 4952 | vm_page_bits_swap(vm_page_t m, vm_page_bits_t *bits, vm_page_bits_t newbits) |
| 4953 | { |
| 4954 | #if PAGE_SIZE == 32768 |
| 4955 | uint64_t old; |
| 4956 | |
| 4957 | old = *bits; |
| 4958 | while (atomic_fcmpset_64(bits, &old, newbits) == 0); |
| 4959 | return (old); |
| 4960 | #elif PAGE_SIZE == 16384 |
| 4961 | uint32_t old; |
| 4962 | |
| 4963 | old = *bits; |
| 4964 | while (atomic_fcmpset_32(bits, &old, newbits) == 0); |
| 4965 | return (old); |
| 4966 | #elif (PAGE_SIZE == 8192) && defined(atomic_fcmpset_16) |
| 4967 | uint16_t old; |
| 4968 | |
| 4969 | old = *bits; |
| 4970 | while (atomic_fcmpset_16(bits, &old, newbits) == 0); |
| 4971 | return (old); |
| 4972 | #elif (PAGE_SIZE == 4096) && defined(atomic_fcmpset_8) |
| 4973 | uint8_t old; |
| 4974 | |
| 4975 | old = *bits; |
| 4976 | while (atomic_fcmpset_8(bits, &old, newbits) == 0); |
| 4977 | return (old); |
| 4978 | #else /* PAGE_SIZE <= 4096*/ |
| 4979 | uintptr_t addr; |
| 4980 | uint32_t old, new, mask; |
| 4981 | int shift; |
| 4982 | |
| 4983 | addr = (uintptr_t)bits; |
| 4984 | /* |
| 4985 | * Use a trick to perform a 32-bit atomic on the |
| 4986 | * containing aligned word, to not depend on the existence |
| 4987 | * of atomic_{set, swap, clear}_{8, 16}. |
| 4988 | */ |
| 4989 | shift = addr & (sizeof(uint32_t) - 1); |
| 4990 | #if BYTE_ORDER == BIG_ENDIAN |
| 4991 | shift = (sizeof(uint32_t) - sizeof(vm_page_bits_t) - shift) * NBBY; |
| 4992 | #else |
| 4993 | shift *= NBBY; |
| 4994 | #endif |
| 4995 | addr &= ~(sizeof(uint32_t) - 1); |
| 4996 | mask = VM_PAGE_BITS_ALL << shift; |
| 4997 | |
| 4998 | old = *bits; |
| 4999 | do { |
| 5000 | new = old & ~mask; |
| 5001 | new |= newbits << shift; |
| 5002 | } while (atomic_fcmpset_32((uint32_t *)addr, &old, new) == 0); |
| 5003 | return (old >> shift); |
| 5004 | #endif /* PAGE_SIZE */ |
| 5005 | } |
| 5006 | |
| 5007 | /* |
| 5008 | * vm_page_set_valid_range: |
no test coverage detected