summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/uvm/uvm_amap.c18
-rw-r--r--sys/uvm/uvm_amap.h6
-rw-r--r--sys/uvm/uvm_anon.c15
-rw-r--r--sys/uvm/uvm_anon.h3
-rw-r--r--sys/uvm/uvm_fault.c62
-rw-r--r--sys/uvm/uvm_stat.c8
-rw-r--r--sys/uvm/uvmexp.h3
7 files changed, 85 insertions, 30 deletions
diff --git a/sys/uvm/uvm_amap.c b/sys/uvm/uvm_amap.c
index 004cc7dbc86..c31a1b4a187 100644
--- a/sys/uvm/uvm_amap.c
+++ b/sys/uvm/uvm_amap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_amap.c,v 1.66 2016/04/16 18:39:31 stefan Exp $ */
+/* $OpenBSD: uvm_amap.c,v 1.67 2016/05/08 11:52:32 stefan Exp $ */
/* $NetBSD: uvm_amap.c,v 1.27 2000/11/25 06:27:59 chs Exp $ */
/*
@@ -803,11 +803,21 @@ amap_lookups(struct vm_aref *aref, vaddr_t offset,
}
/*
+ * amap_populate: ensure that the amap can store an anon for the page at
+ * offset. This function can sleep until memory to store the anon is
+ * available.
+ */
+void
+amap_populate(struct vm_aref *aref, vaddr_t offset)
+{
+}
+
+/*
* amap_add: add (or replace) a page to an amap
*
- * => returns an "offset" which is meaningful to amap_unadd().
+ * => returns 0 if adding the page was successful or 1 when not.
*/
-void
+int
amap_add(struct vm_aref *aref, vaddr_t offset, struct vm_anon *anon,
boolean_t replace)
{
@@ -840,6 +850,8 @@ amap_add(struct vm_aref *aref, vaddr_t offset, struct vm_anon *anon,
amap->am_nused++;
}
amap->am_anon[slot] = anon;
+
+ return 0;
}
/*
diff --git a/sys/uvm/uvm_amap.h b/sys/uvm/uvm_amap.h
index c602d0088a8..e76dead3f28 100644
--- a/sys/uvm/uvm_amap.h
+++ b/sys/uvm/uvm_amap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_amap.h,v 1.24 2016/04/16 18:39:31 stefan Exp $ */
+/* $OpenBSD: uvm_amap.h,v 1.25 2016/05/08 11:52:32 stefan Exp $ */
/* $NetBSD: uvm_amap.h,v 1.14 2001/02/18 21:19:08 chs Exp $ */
/*
@@ -62,8 +62,10 @@ struct vm_amap;
* prototypes for the amap interface
*/
+ /* ensure amap can store anon */
+void amap_populate(struct vm_aref *, vaddr_t);
/* add an anon to an amap */
-void amap_add(struct vm_aref *, vaddr_t, struct vm_anon *,
+int amap_add(struct vm_aref *, vaddr_t, struct vm_anon *,
boolean_t);
/* allocate a new amap */
struct vm_amap *amap_alloc(vaddr_t, int);
diff --git a/sys/uvm/uvm_anon.c b/sys/uvm/uvm_anon.c
index e245ecf623c..d2738cad2ac 100644
--- a/sys/uvm/uvm_anon.c
+++ b/sys/uvm/uvm_anon.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_anon.c,v 1.45 2016/03/29 12:04:26 chl Exp $ */
+/* $OpenBSD: uvm_anon.c,v 1.46 2016/05/08 11:52:32 stefan Exp $ */
/* $NetBSD: uvm_anon.c,v 1.10 2000/11/25 06:27:59 chs Exp $ */
/*
@@ -125,6 +125,19 @@ uvm_anfree(struct vm_anon *anon)
}
/*
+ * uvm_anwait: wait for memory to become available to allocate an anon.
+ */
+void
+uvm_anwait(void)
+{
+ struct vm_anon *anon;
+
+ /* XXX: Want something like pool_wait()? */
+ anon = pool_get(&uvm_anon_pool, PR_WAITOK);
+ pool_put(&uvm_anon_pool, anon);
+}
+
+/*
* uvm_anon_dropswap: release any swap resources from this anon.
*/
void
diff --git a/sys/uvm/uvm_anon.h b/sys/uvm/uvm_anon.h
index 894f5031dec..2f8c259d663 100644
--- a/sys/uvm/uvm_anon.h
+++ b/sys/uvm/uvm_anon.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_anon.h,v 1.19 2015/08/21 16:04:35 visa Exp $ */
+/* $OpenBSD: uvm_anon.h,v 1.20 2016/05/08 11:52:32 stefan Exp $ */
/* $NetBSD: uvm_anon.h,v 1.13 2000/12/27 09:17:04 chs Exp $ */
/*
@@ -79,6 +79,7 @@ struct vm_aref {
#ifdef _KERNEL
struct vm_anon *uvm_analloc(void);
void uvm_anfree(struct vm_anon *);
+void uvm_anwait(void);
void uvm_anon_init(void);
void uvm_anon_dropswap(struct vm_anon *);
boolean_t uvm_anon_pagein(struct vm_anon *);
diff --git a/sys/uvm/uvm_fault.c b/sys/uvm/uvm_fault.c
index a6858c3e157..e00b0b9d5ea 100644
--- a/sys/uvm/uvm_fault.c
+++ b/sys/uvm/uvm_fault.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_fault.c,v 1.89 2016/03/29 12:04:26 chl Exp $ */
+/* $OpenBSD: uvm_fault.c,v 1.90 2016/05/08 11:52:32 stefan Exp $ */
/* $NetBSD: uvm_fault.c,v 1.51 2000/08/06 00:22:53 thorpej Exp $ */
/*
@@ -493,7 +493,7 @@ uvm_fault(vm_map_t orig_map, vaddr_t vaddr, vm_fault_t fault_type,
struct uvm_faultinfo ufi;
vm_prot_t enter_prot;
boolean_t wired, narrow, promote, locked, shadowed;
- int npages, nback, nforw, centeridx, result, lcv, gotpages;
+ int npages, nback, nforw, centeridx, result, lcv, gotpages, ret;
vaddr_t startva, currva;
voff_t uoff;
paddr_t pa;
@@ -870,7 +870,7 @@ ReFault:
* in the (hopefully very rare) case that we are out of RAM we
* will wait for more RAM, and refault.
*
- * if we are out of anon VM we kill the process (XXX: could wait?).
+ * if we are out of anon VM we wait for RAM to become available.
*/
if ((access_type & PROT_WRITE) != 0 && anon->an_ref > 1) {
@@ -883,17 +883,23 @@ ReFault:
/* check for out of RAM */
if (anon == NULL || pg == NULL) {
- if (anon)
- uvm_anfree(anon);
uvmfault_unlockall(&ufi, amap, NULL, oanon);
KASSERT(uvmexp.swpgonly <= uvmexp.swpages);
- if (anon == NULL || uvmexp.swpgonly == uvmexp.swpages) {
+ if (anon == NULL)
uvmexp.fltnoanon++;
- return (ENOMEM);
+ else {
+ uvm_anfree(anon);
+ uvmexp.fltnoram++;
}
- uvmexp.fltnoram++;
- uvm_wait("flt_noram3"); /* out of RAM, wait for more */
+ if (uvmexp.swpgonly == uvmexp.swpages)
+ return (ENOMEM);
+
+ /* out of RAM, wait for more */
+ if (anon == NULL)
+ uvm_anwait();
+ else
+ uvm_wait("flt_noram3");
goto ReFault;
}
@@ -902,8 +908,9 @@ ReFault:
/* un-busy! new page */
atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_FAKE);
UVM_PAGE_OWN(pg, NULL);
- amap_add(&ufi.entry->aref, ufi.orig_rvaddr - ufi.entry->start,
- anon, 1);
+ ret = amap_add(&ufi.entry->aref,
+ ufi.orig_rvaddr - ufi.entry->start, anon, 1);
+ KASSERT(ret == 0);
/* deref: can not drop to zero here by defn! */
oanon->an_ref--;
@@ -1132,14 +1139,21 @@ Case2:
/* unlock and fail ... */
uvmfault_unlockall(&ufi, amap, uobj, NULL);
KASSERT(uvmexp.swpgonly <= uvmexp.swpages);
- if (anon == NULL || uvmexp.swpgonly == uvmexp.swpages) {
+ if (anon == NULL)
uvmexp.fltnoanon++;
- return (ENOMEM);
+ else {
+ uvm_anfree(anon);
+ uvmexp.fltnoram++;
}
- uvm_anfree(anon);
- uvmexp.fltnoram++;
- uvm_wait("flt_noram5");
+ if (uvmexp.swpgonly == uvmexp.swpages)
+ return (ENOMEM);
+
+ /* out of RAM, wait for more */
+ if (anon == NULL)
+ uvm_anwait();
+ else
+ uvm_wait("flt_noram5");
goto ReFault;
}
@@ -1175,8 +1189,20 @@ Case2:
*/
}
- amap_add(&ufi.entry->aref, ufi.orig_rvaddr - ufi.entry->start,
- anon, 0);
+ if (amap_add(&ufi.entry->aref,
+ ufi.orig_rvaddr - ufi.entry->start, anon, 0)) {
+ uvmfault_unlockall(&ufi, amap, NULL, oanon);
+ KASSERT(uvmexp.swpgonly <= uvmexp.swpages);
+ uvm_anfree(anon);
+ uvmexp.fltnoamap++;
+
+ if (uvmexp.swpgonly == uvmexp.swpages)
+ return (ENOMEM);
+
+ amap_populate(&ufi.entry->aref,
+ ufi.orig_rvaddr - ufi.entry->start);
+ goto ReFault;
+ }
}
/* note: pg is either the uobjpage or the new page in the new anon */
diff --git a/sys/uvm/uvm_stat.c b/sys/uvm/uvm_stat.c
index 97173f25a8a..b88b3fb30cd 100644
--- a/sys/uvm/uvm_stat.c
+++ b/sys/uvm/uvm_stat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_stat.c,v 1.28 2014/10/25 12:54:16 miod Exp $ */
+/* $OpenBSD: uvm_stat.c,v 1.29 2016/05/08 11:52:32 stefan Exp $ */
/* $NetBSD: uvm_stat.c,v 1.18 2001/03/09 01:02:13 chs Exp $ */
/*
@@ -69,9 +69,9 @@ uvmexp_print(int (*pr)(const char *, ...))
uvmexp.softs, uvmexp.syscalls, uvmexp.kmapent);
(*pr)(" fault counts:\n");
- (*pr)(" noram=%d, noanon=%d, pgwait=%d, pgrele=%d\n",
- uvmexp.fltnoram, uvmexp.fltnoanon, uvmexp.fltpgwait,
- uvmexp.fltpgrele);
+ (*pr)(" noram=%d, noanon=%d, noamap=%d, pgwait=%d, pgrele=%d\n",
+ uvmexp.fltnoram, uvmexp.fltnoanon, uvmexp.fltnoamap,
+ uvmexp.fltpgwait, uvmexp.fltpgrele);
(*pr)(" ok relocks(total)=%d(%d), anget(retries)=%d(%d), "
"amapcopy=%d\n", uvmexp.fltrelckok, uvmexp.fltrelck,
uvmexp.fltanget, uvmexp.fltanretry, uvmexp.fltamcopy);
diff --git a/sys/uvm/uvmexp.h b/sys/uvm/uvmexp.h
index cae4458d756..63fe6b077c6 100644
--- a/sys/uvm/uvmexp.h
+++ b/sys/uvm/uvmexp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvmexp.h,v 1.1 2014/07/08 17:19:26 deraadt Exp $ */
+/* $OpenBSD: uvmexp.h,v 1.2 2016/05/08 11:52:32 stefan Exp $ */
#ifndef _UVM_UVMEXP_
#define _UVM_UVMEXP_
@@ -107,6 +107,7 @@ struct uvmexp {
/* fault subcounters */
int fltnoram; /* number of times fault was out of ram */
int fltnoanon; /* number of times fault was out of anons */
+ int fltnoamap; /* number of times fault was out of amap chunks */
int fltpgwait; /* number of times fault had to wait on a page */
int fltpgrele; /* number of times fault found a released page */
int fltrelck; /* number of times fault relock called */