Page MenuHomeFreeBSD

D58261.id182042.diff
No OneTemporary

D58261.id182042.diff

diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -774,6 +774,18 @@
return (a);
}
+/*
+ * Load a snapshot of a page's 32-bit atomic state, with acquire semantics.
+ */
+static inline vm_page_astate_t
+vm_page_astate_load_acq(vm_page_t m)
+{
+ vm_page_astate_t a;
+
+ a._bits = atomic_load_acq_32(&m->a._bits);
+ return (a);
+}
+
/*
* Atomically compare and set a page's atomic state.
*/
@@ -791,6 +803,26 @@
return (atomic_fcmpset_32(&m->a._bits, &old->_bits, new._bits) != 0);
}
+/*
+ * Atomically compare and set a page's atomic state, with release
+ * semantics.
+ */
+static inline bool
+vm_page_astate_fcmpset_rel(vm_page_t m, vm_page_astate_t *old,
+ vm_page_astate_t new)
+{
+
+ 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_rel_32(&m->a._bits, &old->_bits, new._bits) !=
+ 0);
+}
+
/*
* Clear the given bits in the specified page.
*/
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -3685,6 +3685,22 @@
return (false);
}
+static __always_inline bool
+vm_page_pqstate_fcmpset_rel(vm_page_t m, vm_page_astate_t *old,
+ vm_page_astate_t new)
+{
+ vm_page_astate_t tmp;
+
+ tmp = *old;
+ do {
+ if (__predict_true(vm_page_astate_fcmpset_rel(m, old, new)))
+ return (true);
+ counter_u64_add(pqstate_commit_retries, 1);
+ } while (old->_bits == tmp._bits);
+
+ return (false);
+}
+
/*
* Do the work of committing a queue state update that moves the page out of
* its current queue.
@@ -3715,7 +3731,8 @@
next = TAILQ_NEXT(m, plinks.q);
TAILQ_REMOVE(&pq->pq_pl, m, plinks.q);
vm_pagequeue_cnt_dec(pq);
- if (!vm_page_pqstate_fcmpset(m, old, new)) {
+ /* See vm_page_dequeue(). */
+ if (!vm_page_pqstate_fcmpset_rel(m, old, new)) {
if (next == NULL)
TAILQ_INSERT_TAIL(&pq->pq_pl, m, plinks.q);
else
@@ -4027,7 +4044,12 @@
{
vm_page_astate_t new, old;
- old = vm_page_astate_load(m);
+ /*
+ * Synchronize with _vm_page_pqstate_commit_dequeue(): make sure
+ * that the page's queue linkage field updates are visible before
+ * returning.
+ */
+ old = vm_page_astate_load_acq(m);
do {
if (__predict_true(old.queue == PQ_NONE)) {
KASSERT((old.flags & PGA_QUEUE_STATE_MASK) == 0,

File Metadata

Mime Type
text/plain
Expires
Thu, Sep 17, 1:14 AM (5 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35144589
Default Alt Text
D58261.id182042.diff (2 KB)

Event Timeline