svn commit: r195301 - user/kmacy/releng_7_2_fcs/sys/amd64/amd64
Kip Macy
kmacy at FreeBSD.org
Fri Jul 3 02:51:15 UTC 2009
Author: kmacy
Date: Fri Jul 3 02:51:14 2009
New Revision: 195301
URL: http://svn.freebsd.org/changeset/base/195301
Log:
acquire page lock *before* calling pmap_remove_pte for managed pages to avoid race
when dropping pmap lock
Modified:
user/kmacy/releng_7_2_fcs/sys/amd64/amd64/pmap.c
Modified: user/kmacy/releng_7_2_fcs/sys/amd64/amd64/pmap.c
==============================================================================
--- user/kmacy/releng_7_2_fcs/sys/amd64/amd64/pmap.c Thu Jul 2 23:33:34 2009 (r195300)
+++ user/kmacy/releng_7_2_fcs/sys/amd64/amd64/pmap.c Fri Jul 3 02:51:14 2009 (r195301)
@@ -2500,21 +2500,14 @@ pmap_remove_pte(pmap_t pmap, pt_entry_t
ret = PMAP_REMOVE_LAST;
if (oldpte & PG_MANAGED) {
m = PHYS_TO_VM_PAGE(oldpte & PG_FRAME);
+ vm_page_lock_assert(m, MA_OWNED);
KASSERT((m->flags & PG_UNMANAGED) == 0,
("page not managed"));
- if (vm_page_trylock(m) == 0) {
- PMAP_UNLOCK(pmap);
- vm_page_lock(m);
- PMAP_LOCK(pmap);
- KASSERT((m->flags & PG_UNMANAGED) == 0,
- ("page not managed"));
- }
if ((oldpte & (PG_M | PG_RW)) == (PG_M | PG_RW))
vm_page_dirty(m);
if (oldpte & PG_A)
vm_page_flag_set(m, PG_REFERENCED);
pmap_remove_entry(pmap, m, va, free);
- vm_page_unlock(m);
}
return (ret);
}
@@ -2526,6 +2519,7 @@ static void
pmap_remove_page(pmap_t pmap, vm_offset_t va, pd_entry_t *pde, vm_page_t *free)
{
pt_entry_t *pte;
+ vm_page_t m;
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
if ((*pde & PG_V) == 0)
@@ -2533,7 +2527,18 @@ pmap_remove_page(pmap_t pmap, vm_offset_
pte = pmap_pde_to_pte(pde, va);
if ((*pte & PG_V) == 0)
return;
+
+ if (*pte & PG_MANAGED) {
+ m = PHYS_TO_VM_PAGE(*pte & PG_FRAME);
+ if (vm_page_trylock(m) == 0) {
+ PMAP_UNLOCK(pmap);
+ vm_page_lock(m);
+ PMAP_LOCK(pmap);
+ }
+ }
pmap_remove_pte(pmap, pte, va, *pde, free);
+ if (m != NULL)
+ vm_page_unlock(m);
pmap_invalidate_page(pmap, va);
}
@@ -2660,9 +2665,23 @@ restart:
for (pte = pmap_pde_to_pte(pde, sva); sva != va_next; pte++,
sva += PAGE_SIZE) {
int ret;
+ vm_page_t m = NULL;
+
if (*pte == 0)
continue;
+ if (*pte & PG_MANAGED) {
+ m = PHYS_TO_VM_PAGE(*pte & PG_FRAME);
+ if (vm_page_trylock(m) == 0) {
+ PMAP_UNLOCK(pmap);
+ vm_page_lock(m);
+ PMAP_LOCK(pmap);
+ }
+ if (*pte != *pmap_pde_to_pte(pde, sva)) {
+ vm_page_unlock(m);
+ goto restart;
+ }
+ }
/*
* The TLB entry for a PG_G mapping is invalidated
* by pmap_remove_pte().
@@ -2670,6 +2689,8 @@ restart:
if ((*pte & PG_G) == 0)
anyvalid = 1;
ret = pmap_remove_pte(pmap, pte, sva, ptpaddr, &free);
+ if (m != NULL)
+ vm_page_unlock(m);
if (ret & PMAP_REMOVE_LAST)
break;
if (ret & PMAP_REMOVE_UNLOCKED) {
More information about the svn-src-user
mailing list