Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F172084557
D58261.id182042.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
2 KB
Referenced Files
None
Subscribers
None
D58261.id182042.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D58261: vm_page: Fix dequeue on arches with weak ordering
Attached
Detach File
Event Timeline
Log In to Comment