Module Name:    src
Committed By:   riastradh
Date:           Sat Mar 21 13:11:14 UTC 2015

Modified Files:
        src/sys/uvm: uvm_page.h

Log Message:
Elaborate on locking scheme and vm_page states.


To generate a diff of this commit:
cvs rdiff -u -r1.76 -r1.77 src/sys/uvm/uvm_page.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/uvm/uvm_page.h
diff -u src/sys/uvm/uvm_page.h:1.76 src/sys/uvm/uvm_page.h:1.77
--- src/sys/uvm/uvm_page.h:1.76	Fri Oct 25 14:30:21 2013
+++ src/sys/uvm/uvm_page.h	Sat Mar 21 13:11:14 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_page.h,v 1.76 2013/10/25 14:30:21 martin Exp $	*/
+/*	$NetBSD: uvm_page.h,v 1.77 2015/03/21 13:11:14 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -98,36 +98,71 @@
  *
  * Field markings and the corresponding locks:
  *
- * o:	page owner's lock (UVM object or amap/anon)
- * p:	lock on the page queues
- * o|p:	either lock can be acquired
- * o&p:	both locks are required
+ * f:	free page queue lock, uvm_fpageqlock
+ * o:	page owner (uvm_object::vmobjlock, vm_amap::am_lock, vm_anon::an_lock)
+ * p:	page queue lock, uvm_pageqlock
+ * o,p:	o|p for read, o&p for write
+ * w:	wired page queue or uvm_pglistalloc:
+ *	  => wired page queue: o&p to change, stable from wire to unwire
+ *		XXX What about concurrent or nested wire?
+ *	  => uvm_pglistalloc: owned by caller
  * ?:	locked by pmap or assumed page owner's lock
  *
  * UVM and pmap(9) may use uvm_page_locked_p() to assert whether the
  * page owner's lock is acquired.
+ *
+ * A page can be in one of four life states:
+ *
+ * o free
+ *   => pageq.list is entry on global free page queue
+ *   => listq.list is entry on per-CPU free page queue
+ *   => uanon is unused (or (void *)0xdeadbeef for DEBUG)
+ *   => uobject is unused (or (void *)0xdeadbeef for DEBUG)
+ *   => PQ_FREE is set in pqflags
+ * o owned by a uvm_object
+ *   => pageq.queue is entry on wired page queue, if any
+ *   => listq.queue is entry on list of pages in object
+ *   => uanon is NULL
+ *   => uobject is owner
+ * o owned by a vm_anon
+ *   => pageq is unused (XXX correct?)
+ *   => listq is unused (XXX correct?)
+ *   => uanon is owner
+ *   => uobject is NULL
+ *   => PQ_ANON is set in pqflags
+ * o allocated by uvm_pglistalloc
+ *   => pageq.queue is entry on resulting pglist, owned by caller
+ *   => listq is unused (XXX correct?)
+ *   => uanon is unused
+ *   => uobject is unused
+ *
+ * The following transitions are allowed:
+ *
+ * - uvm_pagealloc: free -> owned by a uvm_object/vm_anon
+ * - uvm_pagefree: owned by a uvm_object/vm_anon -> free
+ * - uvm_pglistalloc: free -> allocated by uvm_pglistalloc
+ * - uvm_pglistfree: allocated by uvm_pglistalloc -> free
  */
 
 struct vm_page {
 	struct rb_node		rb_node;	/* o: tree of pages in obj */
 
 	union {
-		TAILQ_ENTRY(vm_page) queue;
-		LIST_ENTRY(vm_page) list;
-	} pageq;				/* p: queue info for FIFO
-						 * queue or free list */
+		TAILQ_ENTRY(vm_page) queue;	/* w: wired page queue
+						 * or uvm_pglistalloc output */
+		LIST_ENTRY(vm_page) list;	/* f: global free page queue */
+	} pageq;
+
 	union {
-		TAILQ_ENTRY(vm_page) queue;
-		LIST_ENTRY(vm_page) list;
-	} listq;				/* o: pages in same object */
+		TAILQ_ENTRY(vm_page) queue;	/* o: pages in same object */
+		LIST_ENTRY(vm_page) list;	/* f: CPU free page queue */
+	} listq;
 
 	struct vm_anon		*uanon;		/* o,p: anon */
 	struct uvm_object	*uobject;	/* o,p: object */
 	voff_t			offset;		/* o,p: offset into object */
 	uint16_t		flags;		/* o: object flags */
-	uint16_t		loan_count;	/* number of active loans
-						 * o|p: for reading
-						 * o&p: for modification */
+	uint16_t		loan_count;	/* o,p: num. active loans */
 	uint16_t		wire_count;	/* p: wired down map refs */
 	uint16_t		pqflags;	/* p: page queue flags */
 	paddr_t			phys_addr;	/* physical address of page */
@@ -149,9 +184,9 @@ struct vm_page {
  *
  * Locking notes:
  *
- * PG_, struct vm_page::flags	=> locked by the owner
- * PQ_, struct vm_page::pqflags	=> locked by the page-queue lock
- * PQ_FREE			=> additionally locked by free-queue lock
+ * PG_, struct vm_page::flags	=> locked by owner
+ * PQ_, struct vm_page::pqflags	=> locked by uvm_pageqlock
+ * PQ_FREE			=> additionally locked by uvm_fpageqlock
  *
  * Flag descriptions:
  *

Reply via email to