Moved duplicate code from the VMTranslationMap subclasses' UnmapPage() and
ClearAccessedAndModified() implementations into helper methods PageUnmapped() and UnaccessedPageUnmapped() in the base class. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37187 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -69,6 +69,13 @@ struct VMTranslationMap {
|
||||
|
||||
virtual void Flush() = 0;
|
||||
|
||||
protected:
|
||||
void PageUnmapped(VMArea* area,
|
||||
page_num_t pageNumber, bool accessed,
|
||||
bool modified, bool updatePageQueue);
|
||||
void UnaccessedPageUnmapped(VMArea* area,
|
||||
page_num_t pageNumber);
|
||||
|
||||
protected:
|
||||
recursive_lock fLock;
|
||||
int32 fMapCount;
|
||||
|
||||
@@ -489,51 +489,10 @@ PPCVMTranslationMap::UnmapPage(VMArea* area, addr_t address,
|
||||
|
||||
fMapCount--;
|
||||
|
||||
// get the page
|
||||
vm_page* page = vm_lookup_page(pageNumber);
|
||||
ASSERT(page != NULL);
|
||||
locker.Detach();
|
||||
// PageUnmapped() will unlock for us
|
||||
|
||||
// transfer the accessed/dirty flags to the page
|
||||
page->accessed |= accessed;
|
||||
page->modified |= modified;
|
||||
|
||||
// remove the mapping object/decrement the wired_count of the page
|
||||
vm_page_mapping* mapping = NULL;
|
||||
if (area->wiring == B_NO_LOCK) {
|
||||
vm_page_mappings::Iterator iterator = page->mappings.GetIterator();
|
||||
while ((mapping = iterator.Next()) != NULL) {
|
||||
if (mapping->area == area) {
|
||||
area->mappings.Remove(mapping);
|
||||
page->mappings.Remove(mapping);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(mapping != NULL);
|
||||
} else
|
||||
page->wired_count--;
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
if (page->wired_count == 0 && page->mappings.IsEmpty()) {
|
||||
atomic_add(&gMappedPagesCount, -1);
|
||||
|
||||
if (updatePageQueue) {
|
||||
if (page->Cache()->temporary)
|
||||
vm_page_set_state(page, PAGE_STATE_INACTIVE);
|
||||
else if (page->modified)
|
||||
vm_page_set_state(page, PAGE_STATE_MODIFIED);
|
||||
else
|
||||
vm_page_set_state(page, PAGE_STATE_CACHED);
|
||||
}
|
||||
}
|
||||
|
||||
if (mapping != NULL) {
|
||||
bool isKernelSpace = area->address_space == VMAddressSpace::Kernel();
|
||||
object_cache_free(gPageMappingsObjectCache, mapping,
|
||||
CACHE_DONT_WAIT_FOR_MEMORY
|
||||
| (isKernelSpace ? CACHE_DONT_LOCK_KERNEL_SPACE : 0));
|
||||
}
|
||||
PageUnmapped(area, pageNumber, accessed, modified, updatePageQueue);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -328,58 +328,12 @@ X86VMTranslationMap32Bit::UnmapPage(VMArea* area, addr_t address,
|
||||
// (cf. pmap_remove_all()), unless I've missed something.
|
||||
}
|
||||
|
||||
if (area->cache_type == CACHE_TYPE_DEVICE)
|
||||
return B_OK;
|
||||
locker.Detach();
|
||||
// PageUnmapped() will unlock for us
|
||||
|
||||
// get the page
|
||||
vm_page* page = vm_lookup_page(
|
||||
(oldEntry & X86_PTE_ADDRESS_MASK) / B_PAGE_SIZE);
|
||||
ASSERT_PRINT(page != NULL, "page: %p, pte: %#" B_PRIx32, page, oldEntry);
|
||||
|
||||
// transfer the accessed/dirty flags to the page
|
||||
if ((oldEntry & X86_PTE_ACCESSED) != 0)
|
||||
page->accessed = true;
|
||||
if ((oldEntry & X86_PTE_DIRTY) != 0)
|
||||
page->modified = true;
|
||||
|
||||
// remove the mapping object/decrement the wired_count of the page
|
||||
vm_page_mapping* mapping = NULL;
|
||||
if (area->wiring == B_NO_LOCK) {
|
||||
vm_page_mappings::Iterator iterator = page->mappings.GetIterator();
|
||||
while ((mapping = iterator.Next()) != NULL) {
|
||||
if (mapping->area == area) {
|
||||
area->mappings.Remove(mapping);
|
||||
page->mappings.Remove(mapping);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_PRINT(mapping != NULL, "page: %p, pte: %#" B_PRIx32, page,
|
||||
oldEntry);
|
||||
} else
|
||||
page->wired_count--;
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
if (page->wired_count == 0 && page->mappings.IsEmpty()) {
|
||||
atomic_add(&gMappedPagesCount, -1);
|
||||
|
||||
if (updatePageQueue) {
|
||||
if (page->Cache()->temporary)
|
||||
vm_page_set_state(page, PAGE_STATE_INACTIVE);
|
||||
else if (page->modified)
|
||||
vm_page_set_state(page, PAGE_STATE_MODIFIED);
|
||||
else
|
||||
vm_page_set_state(page, PAGE_STATE_CACHED);
|
||||
}
|
||||
}
|
||||
|
||||
if (mapping != NULL) {
|
||||
bool isKernelSpace = area->address_space == VMAddressSpace::Kernel();
|
||||
object_cache_free(gPageMappingsObjectCache, mapping,
|
||||
CACHE_DONT_WAIT_FOR_MEMORY
|
||||
| (isKernelSpace ? CACHE_DONT_LOCK_KERNEL_SPACE : 0));
|
||||
}
|
||||
PageUnmapped(area, (oldEntry & X86_PTE_ADDRESS_MASK) / B_PAGE_SIZE,
|
||||
(oldEntry & X86_PTE_ACCESSED) != 0, (oldEntry & X86_PTE_DIRTY) != 0,
|
||||
updatePageQueue);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -897,41 +851,11 @@ X86VMTranslationMap32Bit::ClearAccessedAndModified(VMArea* area, addr_t address,
|
||||
|
||||
fMapCount--;
|
||||
|
||||
if (area->cache_type == CACHE_TYPE_DEVICE)
|
||||
return false;
|
||||
locker.Detach();
|
||||
// UnaccessedPageUnmapped() will unlock for us
|
||||
|
||||
// get the page
|
||||
vm_page* page = vm_lookup_page(
|
||||
UnaccessedPageUnmapped(area,
|
||||
(oldEntry & X86_PTE_ADDRESS_MASK) / B_PAGE_SIZE);
|
||||
ASSERT(page != NULL);
|
||||
|
||||
// remove the mapping object/decrement the wired_count of the page
|
||||
vm_page_mapping* mapping = NULL;
|
||||
if (area->wiring == B_NO_LOCK) {
|
||||
vm_page_mappings::Iterator iterator = page->mappings.GetIterator();
|
||||
while ((mapping = iterator.Next()) != NULL) {
|
||||
if (mapping->area == area) {
|
||||
area->mappings.Remove(mapping);
|
||||
page->mappings.Remove(mapping);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(mapping != NULL);
|
||||
} else
|
||||
page->wired_count--;
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
if (page->wired_count == 0 && page->mappings.IsEmpty())
|
||||
atomic_add(&gMappedPagesCount, -1);
|
||||
|
||||
if (mapping != NULL) {
|
||||
object_cache_free(gPageMappingsObjectCache, mapping,
|
||||
CACHE_DONT_WAIT_FOR_MEMORY | CACHE_DONT_LOCK_KERNEL_SPACE);
|
||||
// Since this is called by the page daemon, we never want to lock
|
||||
// the kernel address space.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,12 @@
|
||||
|
||||
#include <vm/VMTranslationMap.h>
|
||||
|
||||
#include <slab/Slab.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_priv.h>
|
||||
#include <vm/VMAddressSpace.h>
|
||||
#include <vm/VMArea.h>
|
||||
#include <vm/VMCache.h>
|
||||
|
||||
|
||||
// #pragma mark - VMTranslationMap
|
||||
@@ -105,6 +108,117 @@ VMTranslationMap::UnmapArea(VMArea* area, bool deletingAddressSpace,
|
||||
}
|
||||
|
||||
|
||||
/*! Called by UnmapPage() after performing the architecture specific part.
|
||||
Looks up the page, updates its flags, removes the page-area mapping, and
|
||||
requeues the page, if necessary.
|
||||
*/
|
||||
void
|
||||
VMTranslationMap::PageUnmapped(VMArea* area, page_num_t pageNumber,
|
||||
bool accessed, bool modified, bool updatePageQueue)
|
||||
{
|
||||
if (area->cache_type == CACHE_TYPE_DEVICE) {
|
||||
recursive_lock_unlock(&fLock);
|
||||
return;
|
||||
}
|
||||
|
||||
// get the page
|
||||
vm_page* page = vm_lookup_page(pageNumber);
|
||||
ASSERT_PRINT(page != NULL, "page number: %#" B_PRIxPHYSADDR
|
||||
", accessed: %d, modified: %d", pageNumber, accessed, modified);
|
||||
|
||||
// transfer the accessed/dirty flags to the page
|
||||
page->accessed |= accessed;
|
||||
page->modified |= modified;
|
||||
|
||||
// remove the mapping object/decrement the wired_count of the page
|
||||
vm_page_mapping* mapping = NULL;
|
||||
if (area->wiring == B_NO_LOCK) {
|
||||
vm_page_mappings::Iterator iterator = page->mappings.GetIterator();
|
||||
while ((mapping = iterator.Next()) != NULL) {
|
||||
if (mapping->area == area) {
|
||||
area->mappings.Remove(mapping);
|
||||
page->mappings.Remove(mapping);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_PRINT(mapping != NULL, "page: %p, page number: %#"
|
||||
B_PRIxPHYSADDR ", accessed: %d, modified: %d", page,
|
||||
pageNumber, accessed, modified);
|
||||
} else
|
||||
page->wired_count--;
|
||||
|
||||
recursive_lock_unlock(&fLock);
|
||||
|
||||
if (page->wired_count == 0 && page->mappings.IsEmpty()) {
|
||||
atomic_add(&gMappedPagesCount, -1);
|
||||
|
||||
if (updatePageQueue) {
|
||||
if (page->Cache()->temporary)
|
||||
vm_page_set_state(page, PAGE_STATE_INACTIVE);
|
||||
else if (page->modified)
|
||||
vm_page_set_state(page, PAGE_STATE_MODIFIED);
|
||||
else
|
||||
vm_page_set_state(page, PAGE_STATE_CACHED);
|
||||
}
|
||||
}
|
||||
|
||||
if (mapping != NULL) {
|
||||
bool isKernelSpace = area->address_space == VMAddressSpace::Kernel();
|
||||
object_cache_free(gPageMappingsObjectCache, mapping,
|
||||
CACHE_DONT_WAIT_FOR_MEMORY
|
||||
| (isKernelSpace ? CACHE_DONT_LOCK_KERNEL_SPACE : 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! Called by ClearAccessedAndModified() after performing the architecture
|
||||
specific part.
|
||||
Looks up the page and removes the page-area mapping.
|
||||
*/
|
||||
void
|
||||
VMTranslationMap::UnaccessedPageUnmapped(VMArea* area, page_num_t pageNumber)
|
||||
{
|
||||
if (area->cache_type == CACHE_TYPE_DEVICE) {
|
||||
recursive_lock_unlock(&fLock);
|
||||
return;
|
||||
}
|
||||
|
||||
// get the page
|
||||
vm_page* page = vm_lookup_page(pageNumber);
|
||||
ASSERT_PRINT(page != NULL, "page number: %#" B_PRIxPHYSADDR, pageNumber);
|
||||
|
||||
// remove the mapping object/decrement the wired_count of the page
|
||||
vm_page_mapping* mapping = NULL;
|
||||
if (area->wiring == B_NO_LOCK) {
|
||||
vm_page_mappings::Iterator iterator = page->mappings.GetIterator();
|
||||
while ((mapping = iterator.Next()) != NULL) {
|
||||
if (mapping->area == area) {
|
||||
area->mappings.Remove(mapping);
|
||||
page->mappings.Remove(mapping);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_PRINT(mapping != NULL, "page: %p, page number: %#"
|
||||
B_PRIxPHYSADDR, page, pageNumber);
|
||||
} else
|
||||
page->wired_count--;
|
||||
|
||||
recursive_lock_unlock(&fLock);
|
||||
|
||||
if (page->wired_count == 0 && page->mappings.IsEmpty())
|
||||
atomic_add(&gMappedPagesCount, -1);
|
||||
|
||||
if (mapping != NULL) {
|
||||
object_cache_free(gPageMappingsObjectCache, mapping,
|
||||
CACHE_DONT_WAIT_FOR_MEMORY | CACHE_DONT_LOCK_KERNEL_SPACE);
|
||||
// Since this is called by the page daemon, we never want to lock
|
||||
// the kernel address space.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - VMPhysicalPageMapper
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user