diff options
author | 2015-07-10 11:52:59 +0000 | |
---|---|---|
committer | 2015-07-10 11:52:59 +0000 | |
commit | 2bead5cb479e45c8398ee3e33fe8b3fec5e8d300 (patch) | |
tree | 9b7ad2dc0f2b24bd04f40633f5848462340ad305 | |
parent | Avoid calling pool_put(9) while holding a mutex here as well to prevent lock (diff) | |
download | wireguard-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.c | 12 |
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; } |