Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/uvm uvm_fault: Split "neighbor" fault and loan handling ...
details: https://anonhg.NetBSD.org/src/rev/2062fc533ad7
branches: trunk
changeset: 751361:2062fc533ad7
user: uebayasi <uebayasi%NetBSD.org@localhost>
date: Tue Feb 02 04:35:35 2010 +0000
description:
uvm_fault: Split "neighbor" fault and loan handling into functions.
diffstat:
sys/uvm/uvm_fault.c | 146 ++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 113 insertions(+), 33 deletions(-)
diffs (truncated from 318 to 300 lines):
diff -r a8e1510c46e5 -r 2062fc533ad7 sys/uvm/uvm_fault.c
--- a/sys/uvm/uvm_fault.c Tue Feb 02 04:28:55 2010 +0000
+++ b/sys/uvm/uvm_fault.c Tue Feb 02 04:35:35 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_fault.c,v 1.150 2010/02/02 01:54:48 uebayasi Exp $ */
+/* $NetBSD: uvm_fault.c,v 1.151 2010/02/02 04:35:35 uebayasi Exp $ */
/*
*
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_fault.c,v 1.150 2010/02/02 01:54:48 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_fault.c,v 1.151 2010/02/02 04:35:35 uebayasi Exp $");
#include "opt_uvmhist.h"
@@ -1002,6 +1002,15 @@
return 0;
}
+static inline void
+uvm_fault_upper_lookup1(
+ struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+ bool shadowed);
+static void
+uvm_fault_upper_lookup_neighbor(
+ struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+ vaddr_t currva, struct vm_anon *anon);
+
static int
uvm_fault_upper_lookup(
struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
@@ -1024,8 +1033,6 @@
currva = flt->startva;
shadowed = false;
for (lcv = 0 ; lcv < flt->npages ; lcv++, currva += PAGE_SIZE) {
- struct vm_anon *anon;
-
/*
* dont play with VAs that are already mapped
* except for center)
@@ -1051,9 +1058,22 @@
pages[lcv] = PGO_DONTCARE;
if (lcv == flt->centeridx) { /* save center for later! */
shadowed = true;
- continue;
+ } else {
+ uvm_fault_upper_lookup_neighbor(ufi, flt, currva, anons[lcv]);
}
- anon = anons[lcv];
+ }
+
+ uvm_fault_upper_lookup1(ufi, flt, shadowed);
+
+ return 0;
+}
+
+static void
+uvm_fault_upper_lookup_neighbor(
+ struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+ vaddr_t currva, struct vm_anon *anon)
+{
+
mutex_enter(&anon->an_lock);
/* ignore loaned and busy pages */
@@ -1085,7 +1105,19 @@
uvm_fault_upper_lookup_enter_done:
pmap_update(ufi->orig_map->pmap);
mutex_exit(&anon->an_lock);
- }
+}
+
+static inline void
+uvm_fault_upper_lookup1(
+ struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+ bool shadowed)
+{
+#ifdef DIAGNOSTIC
+ struct vm_amap *amap = ufi->entry->aref.ar_amap;
+#endif
+#ifdef UVMHIST
+ struct uvm_object *uobj = ufi->entry->object.uvm_obj;
+#endif
/* locked: maps(read), amap(if there) */
KASSERT(amap == NULL || mutex_owned(&amap->am_l));
@@ -1100,8 +1132,6 @@
* XXX Actually, that is bad; pmap_enter() should just fail in that
* XXX case. --thorpej
*/
-
- return 0;
}
static int
@@ -1152,6 +1182,10 @@
return error;
}
+static void uvm_fault_lower_generic_lookup_neighbor(
+ struct uvm_faultinfo *, struct uvm_faultctx *,
+ vaddr_t, struct vm_page *);
+
static int
uvm_fault_lower_generic(
struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
@@ -1210,7 +1244,6 @@
currva = flt->startva;
for (lcv = 0; lcv < flt->npages; lcv++, currva += PAGE_SIZE) {
struct vm_page *curpg;
- bool readonly;
curpg = pages[lcv];
if (curpg == NULL || curpg == PGO_DONTCARE) {
@@ -1228,8 +1261,20 @@
UVMHIST_LOG(maphist, " got uobjpage "
"(0x%x) with locked get",
curpg, 0,0,0);
- continue;
- }
+ } else
+ uvm_fault_lower_generic_lookup_neighbor(ufi, flt,
+ currva, curpg);
+ }
+ pmap_update(ufi->orig_map->pmap);
+ return 0;
+}
+
+static void
+uvm_fault_lower_generic_lookup_neighbor(
+ struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+ vaddr_t currva, struct vm_page *curpg)
+{
+ bool readonly;
/*
* calling pgo_get with PGO_LOCKED returns us pages which
@@ -1273,9 +1318,6 @@
curpg->flags &= ~(PG_BUSY);
UVM_PAGE_OWN(curpg, NULL);
- }
- pmap_update(ufi->orig_map->pmap);
- return 0;
}
static int
@@ -1420,12 +1462,17 @@
}
static int
+uvm_fault_upper_loan_break(
+ struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+ struct vm_anon *anon, struct uvm_object **ruobj);
+
+static int
uvm_fault_upper_loan(
struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
struct vm_anon *anon, struct uvm_object **ruobj)
{
struct vm_amap * const amap = ufi->entry->aref.ar_amap;
- struct uvm_object *uobj = *ruobj;
+ int error = 0;
if (!flt->cow_now) {
@@ -1452,14 +1499,29 @@
/* >1 case is already ok */
if (anon->an_ref == 1) {
+ error = uvm_fault_upper_loan_break(ufi, flt, anon, ruobj);
+ if (error != 0) {
+ uvmfault_unlockall(ufi, amap, *ruobj, anon);
+ uvm_wait("flt_noram2");
+ return ERESTART;
+ }
+ }
+ }
+ return error;
+}
+
+/* XXXUEBS consider to move this elsewhere */
+static int
+uvm_fault_upper_loan_break(
+ struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+ struct vm_anon *anon, struct uvm_object **ruobj)
+{
struct vm_page *pg;
/* get new un-owned replacement page */
pg = uvm_pagealloc(NULL, 0, NULL, 0);
if (pg == NULL) {
- uvmfault_unlockall(ufi, amap, uobj, anon);
- uvm_wait("flt_noram2");
- return ERESTART;
+ return ENOMEM;
}
/*
@@ -1477,7 +1539,7 @@
/* in case we owned */
anon->an_page->pqflags &= ~PQ_ANON;
- if (uobj) {
+ if (*ruobj) {
/* if we were receiver of loan */
anon->an_page->loan_count--;
} else {
@@ -1488,8 +1550,8 @@
uvm_pagedequeue(anon->an_page);
}
- if (uobj) {
- mutex_exit(&uobj->vmobjlock);
+ if (*ruobj) {
+ mutex_exit(&(*ruobj)->vmobjlock);
*ruobj = NULL;
}
@@ -1505,10 +1567,8 @@
UVM_PAGE_OWN(pg, NULL);
/* done! */
- } /* ref == 1 */
- } /* write fault */
- return 0;
+ return 0;
}
static int
@@ -1691,7 +1751,7 @@
struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
struct vm_page **ruobjpage);
static int
-uvm_fault_lower_generic_uobjpage(
+uvm_fault_lower_generic3(
struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
struct vm_page *uobjpage, bool promote);
static int
@@ -1771,7 +1831,7 @@
if (error != 0)
return error;
}
- return uvm_fault_lower_generic_uobjpage(ufi, flt, uobjpage, promote);
+ return uvm_fault_lower_generic3(ufi, flt, uobjpage, promote);
}
static int
@@ -1897,7 +1957,7 @@
}
int
-uvm_fault_lower_generic_uobjpage(
+uvm_fault_lower_generic3(
struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
struct vm_page *uobjpage, bool promote)
{
@@ -1935,12 +1995,16 @@
return error;
}
+static int
+uvm_fault_lower_generic_direct_loan(
+ struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+ struct vm_page **rpg, struct vm_page **ruobjpage);
+
int
uvm_fault_lower_generic_direct(
struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
struct vm_page *uobjpage)
{
- struct vm_amap * const amap = ufi->entry->aref.ar_amap;
struct uvm_object * const uobj = ufi->entry->object.uvm_obj;
struct vm_page *pg;
@@ -1967,6 +2031,23 @@
*/
if (uobjpage->loan_count) {
+ uvm_fault_lower_generic_direct_loan(ufi, flt, &pg, &uobjpage);
+ }
+ KASSERT(pg == uobjpage);
+
+ return uvm_fault_lower_generic_enter(ufi, flt, uobj, NULL, pg, uobjpage);
+}
+
+static int
+uvm_fault_lower_generic_direct_loan(
+ struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+ struct vm_page **rpg, struct vm_page **ruobjpage)
+{
+ struct vm_amap * const amap = ufi->entry->aref.ar_amap;
+ struct uvm_object * const uobj = ufi->entry->object.uvm_obj;
+ struct vm_page *pg;
+ struct vm_page *uobjpage = *ruobjpage;
+
Home |
Main Index |
Thread Index |
Old Index