Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148319496
D22753.id65565.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D22753.id65565.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D22753: Implement atomic state updates using the new vm_page_astate_t structure.
Attached
Detach File
Event Timeline
Log In to Comment