aboutsummaryrefslogtreecommitdiff
path: root/sys/vm/vm_page.h
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2018-08-23 20:34:22 +0000
committerMark Johnston <markj@FreeBSD.org>2018-08-23 20:34:22 +0000
commit99d92d732f3bbbcd9bea43298341ab44f7bd4a5f (patch)
tree3add724fc6ea9ffd5c1fa2a0d6ae7c7f1a004586 /sys/vm/vm_page.h
parent608226d5596fb7683e9b649d01e3241624f77b3c (diff)
downloadsrc-99d92d732f3bbbcd9bea43298341ab44f7bd4a5f.tar.gz
src-99d92d732f3bbbcd9bea43298341ab44f7bd4a5f.zip
Ensure that queue state is cleared when vm_page_dequeue() returns.
Per-page queue state is updated non-atomically, with either the page lock or the page queue lock held. When vm_page_dequeue() is called without the page lock, in rare cases a different thread may be concurrently dequeuing the page with the pagequeue lock held. Because of the non-atomic update, vm_page_dequeue() might return before queue state is completely updated, which can lead to race conditions. Restrict the vm_page_dequeue() interface so that it must be called either with the page lock held or on a free page, and busy wait when a different thread is concurrently updating queue state, which must happen in a critical section. While here, do some related cleanup: inline vm_page_dequeue_locked() into its only caller and delete a prototype for the unimplemented vm_page_requeue_locked(). Replace the volatile qualifier for "queue" added in r333703 with explicit uses of atomic_load_8() where required. Reported and tested by: pho Reviewed by: alc Differential Revision: https://reviews.freebsd.org/D15980
Notes
Notes: svn path=/head/; revision=338276
Diffstat (limited to 'sys/vm/vm_page.h')
-rw-r--r--sys/vm/vm_page.h4
1 files changed, 1 insertions, 3 deletions
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index 5f3852d5fc48..d6a4115b89be 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -208,7 +208,7 @@ struct vm_page {
uint16_t flags; /* page PG_* flags (P) */
uint8_t aflags; /* access is atomic */
uint8_t oflags; /* page VPO_* flags (O) */
- volatile uint8_t queue; /* page queue index (Q) */
+ uint8_t queue; /* page queue index (Q) */
int8_t psind; /* pagesizes[] index (O) */
int8_t segind; /* vm_phys segment index (C) */
uint8_t order; /* index of the buddy queue (F) */
@@ -539,7 +539,6 @@ void vm_page_deactivate(vm_page_t);
void vm_page_deactivate_noreuse(vm_page_t);
void vm_page_dequeue(vm_page_t m);
void vm_page_dequeue_deferred(vm_page_t m);
-void vm_page_dequeue_locked(vm_page_t m);
void vm_page_drain_pqbatch(void);
vm_page_t vm_page_find_least(vm_object_t, vm_pindex_t);
bool vm_page_free_prep(vm_page_t m);
@@ -565,7 +564,6 @@ int vm_page_rename (vm_page_t, vm_object_t, vm_pindex_t);
vm_page_t vm_page_replace(vm_page_t mnew, vm_object_t object,
vm_pindex_t pindex);
void vm_page_requeue(vm_page_t m);
-void vm_page_requeue_locked(vm_page_t m);
int vm_page_sbusied(vm_page_t m);
vm_page_t vm_page_scan_contig(u_long npages, vm_page_t m_start,
vm_page_t m_end, u_long alignment, vm_paddr_t boundary, int options);