From: kettenis Date: Sat, 24 Jul 2010 15:40:39 +0000 (+0000) Subject: Don't sleep while holding the uvm_psel_lck mutex. Should fix "locking against X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=cf70c43b1a1e4e3bd82336e4b0f233c4b81aa264;p=openbsd 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@ --- 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); @@ -141,25 +140,6 @@ uvm_pseg_init(struct uvm_pseg *pseg) pseg->start = uvm_km_valloc_try(kernel_map, MAX_PAGER_SEGS * MAXBSIZE); } -/* - * 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. * @@ -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); } /*