summaryrefslogtreecommitdiffstats
path: root/sys/vm/vm_page.h
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2012-08-03 01:48:15 +0000
committeralc <alc@FreeBSD.org>2012-08-03 01:48:15 +0000
commit5b4712b5a1c865efad377e8493e31ac125d837c7 (patch)
treefeac91ca3709b2a50de97b74a3f44576f91012df /sys/vm/vm_page.h
parent6f0d7f5c9334687c2452ded29416115eb0dc218d (diff)
downloadFreeBSD-src-5b4712b5a1c865efad377e8493e31ac125d837c7.zip
FreeBSD-src-5b4712b5a1c865efad377e8493e31ac125d837c7.tar.gz
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.
Diffstat (limited to 'sys/vm/vm_page.h')
-rw-r--r--sys/vm/vm_page.h86
1 files changed, 79 insertions, 7 deletions
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index 8d3d50a..5b68e06 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -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);
@@ -428,6 +431,75 @@ void vm_page_object_lock_assert(vm_page_t m);
#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:
*
* Set all bits in the page's dirty field.
OpenPOWER on IntegriCloud