From 0d5ab7a14d2b2d10ce462eba9896d7a7bd01d827 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 21 Jun 2010 13:32:33 +0000 Subject: [PATCH] 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 --- headers/private/kernel/vm/VMTranslationMap.h | 7 ++ .../arch/ppc/arch_vm_translation_map.cpp | 47 +------- .../paging/32bit/X86VMTranslationMap32Bit.cpp | 92 ++------------ src/system/kernel/vm/VMTranslationMap.cpp | 114 ++++++++++++++++++ 4 files changed, 132 insertions(+), 128 deletions(-) diff --git a/headers/private/kernel/vm/VMTranslationMap.h b/headers/private/kernel/vm/VMTranslationMap.h index e078e6cab0..3d50def12c 100644 --- a/headers/private/kernel/vm/VMTranslationMap.h +++ b/headers/private/kernel/vm/VMTranslationMap.h @@ -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; diff --git a/src/system/kernel/arch/ppc/arch_vm_translation_map.cpp b/src/system/kernel/arch/ppc/arch_vm_translation_map.cpp index 7b42772173..e62d0e3ce4 100644 --- a/src/system/kernel/arch/ppc/arch_vm_translation_map.cpp +++ b/src/system/kernel/arch/ppc/arch_vm_translation_map.cpp @@ -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; } diff --git a/src/system/kernel/arch/x86/paging/32bit/X86VMTranslationMap32Bit.cpp b/src/system/kernel/arch/x86/paging/32bit/X86VMTranslationMap32Bit.cpp index 482086b368..bbb36c53ce 100644 --- a/src/system/kernel/arch/x86/paging/32bit/X86VMTranslationMap32Bit.cpp +++ b/src/system/kernel/arch/x86/paging/32bit/X86VMTranslationMap32Bit.cpp @@ -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; } diff --git a/src/system/kernel/vm/VMTranslationMap.cpp b/src/system/kernel/vm/VMTranslationMap.cpp index d450d50fd6..98fbf17e6a 100644 --- a/src/system/kernel/vm/VMTranslationMap.cpp +++ b/src/system/kernel/vm/VMTranslationMap.cpp @@ -6,9 +6,12 @@ #include +#include #include #include +#include #include +#include // #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