Inline vm_page_aflags_clear() and vm_page_aflags_set().

Add comments stating that neither these functions nor the flags that they
are used to manipulate are part of the KBI.
This commit is contained in:
Alan Cox 2012-08-03 01:48:15 +00:00
parent 0f3fae6159
commit 369763e31a
2 changed files with 79 additions and 64 deletions

View File

@ -450,63 +450,6 @@ vm_page_startup(vm_offset_t vaddr)
return (vaddr);
}
CTASSERT(offsetof(struct vm_page, aflags) % sizeof(uint32_t) == 0);
void
vm_page_aflag_set(vm_page_t m, uint8_t bits)
{
uint32_t *addr, val;
/*
* The PGA_WRITEABLE flag can only be set if the page is managed and
* VPO_BUSY. Currently, this flag is only set by pmap_enter().
*/
KASSERT((bits & PGA_WRITEABLE) == 0 ||
(m->oflags & (VPO_UNMANAGED | VPO_BUSY)) == VPO_BUSY,
("PGA_WRITEABLE and !VPO_BUSY"));
/*
* We want to use atomic updates for m->aflags, which is a
* byte wide. Not all architectures provide atomic operations
* on the single-byte destination. Punt and access the whole
* 4-byte word with an atomic update. Parallel non-atomic
* updates to the fields included in the update by proximity
* are handled properly by atomics.
*/
addr = (void *)&m->aflags;
MPASS(((uintptr_t)addr & (sizeof(uint32_t) - 1)) == 0);
val = bits;
#if BYTE_ORDER == BIG_ENDIAN
val <<= 24;
#endif
atomic_set_32(addr, val);
}
void
vm_page_aflag_clear(vm_page_t m, uint8_t bits)
{
uint32_t *addr, val;
/*
* The PGA_REFERENCED flag can only be cleared if the object
* containing the page is locked.
*/
KASSERT((bits & PGA_REFERENCED) == 0 || VM_OBJECT_LOCKED(m->object),
("PGA_REFERENCED and !VM_OBJECT_LOCKED"));
/*
* See the comment in vm_page_aflag_set().
*/
addr = (void *)&m->aflags;
MPASS(((uintptr_t)addr & (sizeof(uint32_t) - 1)) == 0);
val = bits;
#if BYTE_ORDER == BIG_ENDIAN
val <<= 24;
#endif
atomic_clear_32(addr, val);
}
void
vm_page_reference(vm_page_t m)
{

View File

@ -239,13 +239,14 @@ extern struct vpglocks pa_lock[];
#define vm_page_queue_free_mtx vm_page_queue_free_lock.data
/*
* These are the flags defined for vm_page.
*
* aflags are updated by atomic accesses. Use the vm_page_aflag_set()
* and vm_page_aflag_clear() functions to set and clear the flags.
* The vm_page's aflags are updated using atomic operations. To set or clear
* these flags, the functions vm_page_aflag_set() and vm_page_aflag_clear()
* must be used. Neither these flags nor these functions are part of the KBI.
*
* PGA_REFERENCED may be cleared only if the object containing the page is
* locked. It is set by both the MI and MD VM layers.
* locked. It is set by both the MI and MD VM layers. However, kernel
* loadable modules should not directly set this flag. They should call
* vm_page_reference() instead.
*
* PGA_WRITEABLE is set exclusively on managed pages by pmap_enter(). When it
* does so, the page must be VPO_BUSY. The MI VM layer must never access this
@ -281,8 +282,12 @@ extern struct vpglocks pa_lock[];
#ifdef _KERNEL
#include <sys/systm.h>
#include <vm/vm_param.h>
#include <machine/atomic.h>
/*
* Each pageable resident page falls into one of five lists:
*
@ -349,8 +354,6 @@ extern struct vpglocks vm_page_queue_lock;
#define VM_ALLOC_COUNT_SHIFT 16
#define VM_ALLOC_COUNT(count) ((count) << VM_ALLOC_COUNT_SHIFT)
void vm_page_aflag_set(vm_page_t m, uint8_t bits);
void vm_page_aflag_clear(vm_page_t m, uint8_t bits);
void vm_page_busy(vm_page_t m);
void vm_page_flash(vm_page_t m);
void vm_page_io_start(vm_page_t m);
@ -427,6 +430,75 @@ void vm_page_object_lock_assert(vm_page_t m);
#define VM_PAGE_OBJECT_LOCK_ASSERT(m) (void)0
#endif
/*
* We want to use atomic updates for the aflags field, which is 8 bits wide.
* However, not all architectures support atomic operations on 8-bit
* destinations. In order that we can easily use a 32-bit operation, we
* require that the aflags field be 32-bit aligned.
*/
CTASSERT(offsetof(struct vm_page, aflags) % sizeof(uint32_t) == 0);
/*
* Clear the given bits in the specified page.
*/
static inline void
vm_page_aflag_clear(vm_page_t m, uint8_t bits)
{
uint32_t *addr, val;
/*
* The PGA_REFERENCED flag can only be cleared if the object
* containing the page is locked.
*/
if ((bits & PGA_REFERENCED) != 0)
VM_PAGE_OBJECT_LOCK_ASSERT(m);
/*
* Access the whole 32-bit word containing the aflags field with an
* atomic update. Parallel non-atomic updates to the other fields
* within this word are handled properly by the atomic update.
*/
addr = (void *)&m->aflags;
KASSERT(((uintptr_t)addr & (sizeof(uint32_t) - 1)) == 0,
("vm_page_aflag_clear: aflags is misaligned"));
val = bits;
#if BYTE_ORDER == BIG_ENDIAN
val <<= 24;
#endif
atomic_clear_32(addr, val);
}
/*
* Set the given bits in the specified page.
*/
static inline void
vm_page_aflag_set(vm_page_t m, uint8_t bits)
{
uint32_t *addr, val;
/*
* The PGA_WRITEABLE flag can only be set if the page is managed and
* VPO_BUSY. Currently, this flag is only set by pmap_enter().
*/
KASSERT((bits & PGA_WRITEABLE) == 0 ||
(m->oflags & (VPO_UNMANAGED | VPO_BUSY)) == VPO_BUSY,
("vm_page_aflag_set: PGA_WRITEABLE and !VPO_BUSY"));
/*
* Access the whole 32-bit word containing the aflags field with an
* atomic update. Parallel non-atomic updates to the other fields
* within this word are handled properly by the atomic update.
*/
addr = (void *)&m->aflags;
KASSERT(((uintptr_t)addr & (sizeof(uint32_t) - 1)) == 0,
("vm_page_aflag_set: aflags is misaligned"));
val = bits;
#if BYTE_ORDER == BIG_ENDIAN
val <<= 24;
#endif
atomic_set_32(addr, val);
}
/*
* vm_page_dirty:
*