summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2015-07-10 11:52:59 +0000
committerkettenis <kettenis@openbsd.org>2015-07-10 11:52:59 +0000
commit2bead5cb479e45c8398ee3e33fe8b3fec5e8d300 (patch)
tree9b7ad2dc0f2b24bd04f40633f5848462340ad305
parentAvoid calling pool_put(9) while holding a mutex here as well to prevent lock (diff)
downloadwireguard-openbsd-2bead5cb479e45c8398ee3e33fe8b3fec5e8d300.tar.xz
wireguard-openbsd-2bead5cb479e45c8398ee3e33fe8b3fec5e8d300.zip
Don't call pool_put(9) while holding a mutex. Instead collect pv entries in
a list and put them back into the pool after releasing the mutex. This prevents a lock ordering problem between the per-pmap mutexes and the kernel lock that arises because pool_put(9) may grab the kernel lock when it decides to free a pool page. This seems to make the i386 pmap mpsafe enough to run the reaper without holding the kernel lock. ok sthen@ (who helped me a lot debugging this)
-rw-r--r--sys/arch/i386/i386/pmapae.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/sys/arch/i386/i386/pmapae.c b/sys/arch/i386/i386/pmapae.c
index 4e88ee16ae5..cb98bd18d57 100644
--- a/sys/arch/i386/i386/pmapae.c
+++ b/sys/arch/i386/i386/pmapae.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmapae.c,v 1.38 2015/07/09 08:33:05 kettenis Exp $ */
+/* $OpenBSD: pmapae.c,v 1.39 2015/07/10 11:52:59 kettenis Exp $ */
/*
* Copyright (c) 2006-2008 Michael Shalayeff
@@ -1024,7 +1024,7 @@ vaddr_t startva, vaddr_t endva, int flags)
pmap_sync_flags_pte_pae(pg, opte);
pve = pmap_remove_pv(pg, pmap, startva);
if (pve)
- pmap_free_pv(NULL, pve);
+ pool_put(&pmap_pv_pool, pve);
/* end of "for" loop: time for next pte */
}
@@ -1197,7 +1197,7 @@ pmap_page_remove_pae(struct vm_page *pg)
pmap_unmap_ptes_pae(pve->pv_pmap); /* unlocks pmap */
pmap_destroy(pve->pv_pmap);
- pmap_free_pv(NULL, pve);
+ pool_put(&pmap_pv_pool, pve);
mtx_enter(&pg->mdpage.pv_mtx);
}
mtx_leave(&pg->mdpage.pv_mtx);
@@ -1496,7 +1496,7 @@ pmap_enter_pae(struct pmap *pmap, vaddr_t va, paddr_t pa, vm_prot_t prot,
#endif
if (pmap_initialized)
- pve = pmap_alloc_pv(pmap, ALLOCPV_NEED);
+ pve = pool_get(&pmap_pv_pool, PR_NOWAIT);
else
pve = NULL;
wired_count = resident_count = ptp_count = 0;
@@ -1674,9 +1674,9 @@ enter_now:
out:
if (pve)
- pmap_free_pv(pmap, pve);
+ pool_put(&pmap_pv_pool, pve);
if (opve)
- pmap_free_pv(pmap, opve);
+ pool_put(&pmap_pv_pool, opve);
return error;
}