diff options
-rw-r--r-- | sys/uvm/uvm_amap.c | 18 | ||||
-rw-r--r-- | sys/uvm/uvm_amap.h | 6 | ||||
-rw-r--r-- | sys/uvm/uvm_anon.c | 15 | ||||
-rw-r--r-- | sys/uvm/uvm_anon.h | 3 | ||||
-rw-r--r-- | sys/uvm/uvm_fault.c | 62 | ||||
-rw-r--r-- | sys/uvm/uvm_stat.c | 8 | ||||
-rw-r--r-- | sys/uvm/uvmexp.h | 3 |
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 */ |