Page MenuHomeFreeBSD

D22753.id65565.diff
No OneTemporary

D22753.id65565.diff

Index: head/sys/vm/vm_page.h
===================================================================
--- head/sys/vm/vm_page.h
+++ head/sys/vm/vm_page.h
@@ -439,8 +439,8 @@
#define PGA_REQUEUE_HEAD 0x0040 /* page requeue should bypass LRU */
#define PGA_NOSYNC 0x0080 /* do not collect for syncer */
-#define PGA_QUEUE_STATE_MASK (PGA_ENQUEUED | PGA_DEQUEUE | PGA_REQUEUE | \
- PGA_REQUEUE_HEAD)
+#define PGA_QUEUE_OP_MASK (PGA_DEQUEUE | PGA_REQUEUE | PGA_REQUEUE_HEAD)
+#define PGA_QUEUE_STATE_MASK (PGA_ENQUEUED | PGA_QUEUE_OP_MASK)
/*
* Page flags. If changed at any other time than page allocation or
@@ -756,36 +756,37 @@
#define VM_PAGE_ASSERT_PGA_WRITEABLE(m, bits) (void)0
#endif
+#define VM_PAGE_AFLAG_SHIFT (__offsetof(vm_page_astate_t, flags) * NBBY)
+
/*
- * 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.
+ * Load a snapshot of a page's 32-bit atomic state.
*/
-_Static_assert(offsetof(struct vm_page, a.flags) % sizeof(uint32_t) == 0,
- "aflags field is not 32-bit aligned");
+static inline vm_page_astate_t
+vm_page_astate_load(vm_page_t m)
+{
+ vm_page_astate_t a;
+ a._bits = atomic_load_32(&m->a);
+ return (a);
+}
+
/*
- * We want to be able to update the aflags and queue fields atomically in
- * the same operation.
+ * Atomically compare and set a page's atomic state.
*/
-_Static_assert(offsetof(struct vm_page, a.flags) / sizeof(uint32_t) ==
- offsetof(struct vm_page, a.queue) / sizeof(uint32_t),
- "aflags and queue fields do not belong to the same 32-bit word");
-_Static_assert(offsetof(struct vm_page, a.queue) % sizeof(uint32_t) == 2,
- "queue field is at an unexpected offset");
-_Static_assert(sizeof(((struct vm_page *)NULL)->a.queue) == 1,
- "queue field has an unexpected size");
+static inline bool
+vm_page_astate_fcmpset(vm_page_t m, vm_page_astate_t *old, vm_page_astate_t new)
+{
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define VM_PAGE_AFLAG_SHIFT 0
-#define VM_PAGE_QUEUE_SHIFT 16
-#else
-#define VM_PAGE_AFLAG_SHIFT 16
-#define VM_PAGE_QUEUE_SHIFT 8
-#endif
-#define VM_PAGE_QUEUE_MASK (0xff << VM_PAGE_QUEUE_SHIFT)
+ KASSERT(new.queue == PQ_INACTIVE || (new.flags & PGA_REQUEUE_HEAD) == 0,
+ ("%s: invalid head requeue request for page %p", __func__, m));
+ KASSERT((new.flags & PGA_ENQUEUED) == 0 || new.queue != PQ_NONE,
+ ("%s: setting PGA_ENQUEUED with PQ_NONE in page %p", __func__, m));
+ KASSERT(new._bits != old->_bits,
+ ("%s: bits are unchanged", __func__));
+ return (atomic_fcmpset_32(&m->a._bits, &old->_bits, new._bits) != 0);
+}
+
/*
* Clear the given bits in the specified page.
*/
@@ -805,7 +806,7 @@
* atomic update. Parallel non-atomic updates to the other fields
* within this word are handled properly by the atomic update.
*/
- addr = (void *)&m->a.flags;
+ addr = (void *)&m->a;
val = bits << VM_PAGE_AFLAG_SHIFT;
atomic_clear_32(addr, val);
}
@@ -825,7 +826,7 @@
* atomic update. Parallel non-atomic updates to the other fields
* within this word are handled properly by the atomic update.
*/
- addr = (void *)&m->a.flags;
+ addr = (void *)&m->a;
val = bits << VM_PAGE_AFLAG_SHIFT;
atomic_set_32(addr, val);
}
@@ -841,24 +842,16 @@
vm_page_pqstate_cmpset(vm_page_t m, uint32_t oldq, uint32_t newq,
uint32_t fflags, uint32_t nflags)
{
- uint32_t *addr, nval, oval, qsmask;
+ vm_page_astate_t new, old;
- fflags <<= VM_PAGE_AFLAG_SHIFT;
- nflags <<= VM_PAGE_AFLAG_SHIFT;
- newq <<= VM_PAGE_QUEUE_SHIFT;
- oldq <<= VM_PAGE_QUEUE_SHIFT;
- qsmask = ((PGA_DEQUEUE | PGA_REQUEUE | PGA_REQUEUE_HEAD) <<
- VM_PAGE_AFLAG_SHIFT) | VM_PAGE_QUEUE_MASK;
-
- addr = (void *)&m->a.flags;
- oval = atomic_load_32(addr);
+ old = vm_page_astate_load(m);
do {
- if ((oval & fflags) != 0)
+ if ((old.flags & fflags) != 0 || old.queue != oldq)
return (false);
- if ((oval & VM_PAGE_QUEUE_MASK) != oldq)
- return (false);
- nval = (oval & ~qsmask) | nflags | newq;
- } while (!atomic_fcmpset_32(addr, &oval, nval));
+ new = old;
+ new.flags = (new.flags & ~PGA_QUEUE_OP_MASK) | nflags;
+ new.queue = newq;
+ } while (!vm_page_astate_fcmpset(m, &old, new));
return (true);
}

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 18, 3:53 AM (6 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29876973
Default Alt Text
D22753.id65565.diff (4 KB)

Event Timeline