summaryrefslogtreecommitdiff
path: root/sys/uvm
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2010-07-24 15:40:40 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2010-07-24 15:40:40 +0000
commitc40dee760bf4df2778d8083fdcc66acdbeab3a5d (patch)
tree69dd5c906b8d7b2701d20041487ea97dc99e7ca4 /sys/uvm
parentd26d482cf7ff4722439913763a5d968c2bde63ca (diff)
Don't sleep while holding the uvm_psel_lck mutex. Should fix "locking against
myself" panics that some people have seen over the last year-and-a-half. Cherry picked from a more complex (and therefore scarier) diff from oga@. ok tedu@, oga@
Diffstat (limited to 'sys/uvm')
-rw-r--r--sys/uvm/uvm_pager.c32
1 files changed, 9 insertions, 23 deletions
diff --git a/sys/uvm/uvm_pager.c b/sys/uvm/uvm_pager.c
index 2e307afedcd..f634caecc96 100644
--- a/sys/uvm/uvm_pager.c
+++ b/sys/uvm/uvm_pager.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_pager.c,v 1.56 2010/06/27 20:53:31 oga Exp $ */
+/* $OpenBSD: uvm_pager.c,v 1.57 2010/07/24 15:40:39 kettenis Exp $ */
/* $NetBSD: uvm_pager.c,v 1.36 2000/11/27 18:26:41 chs Exp $ */
/*
@@ -88,7 +88,6 @@ struct uvm_pseg psegs[PSEG_NUMSEGS];
#define UVM_PSEG_INUSE(pseg,id) (((pseg)->use & (1 << (id))) != 0)
void uvm_pseg_init(struct uvm_pseg *);
-void uvm_pseg_destroy(struct uvm_pseg *);
vaddr_t uvm_pseg_get(int);
void uvm_pseg_release(vaddr_t);
@@ -142,25 +141,6 @@ uvm_pseg_init(struct uvm_pseg *pseg)
}
/*
- * Destroy a uvm_pseg.
- *
- * Never fails.
- *
- * Requires that seg != &psegs[0]
- *
- * Caller locks uvm_pseg_lck.
- */
-void
-uvm_pseg_destroy(struct uvm_pseg *pseg)
-{
- KASSERT(pseg != &psegs[0]);
- KASSERT(pseg->start != 0);
- KASSERT(pseg->use == 0);
- uvm_km_free(kernel_map, pseg->start, MAX_PAGER_SEGS * MAXBSIZE);
- pseg->start = 0;
-}
-
-/*
* Acquire a pager map segment.
*
* Returns a vaddr for paging. 0 on failure.
@@ -225,6 +205,7 @@ uvm_pseg_release(vaddr_t segaddr)
{
int id;
struct uvm_pseg *pseg;
+ vaddr_t va = 0;
for (pseg = &psegs[0]; pseg != &psegs[PSEG_NUMSEGS]; pseg++) {
if (pseg->start <= segaddr &&
@@ -246,10 +227,15 @@ uvm_pseg_release(vaddr_t segaddr)
pseg->use &= ~(1 << id);
wakeup(&psegs);
- if (pseg != &psegs[0] && UVM_PSEG_EMPTY(pseg))
- uvm_pseg_destroy(pseg);
+ if (pseg != &psegs[0] && UVM_PSEG_EMPTY(pseg)) {
+ va = pseg->start;
+ pseg->start = 0;
+ }
mtx_leave(&uvm_pseg_lck);
+
+ if (va)
+ uvm_km_free(kernel_map, va, MAX_PAGER_SEGS * MAXBSIZE);
}
/*