Author: bonefish Date: 2010-06-21 15:32:33 +0200 (Mon, 21 Jun 2010) New Revision: 37187 Changeset: http://dev.haiku-os.org/changeset/37187/haiku Modified: haiku/trunk/headers/private/kernel/vm/VMTranslationMap.h haiku/trunk/src/system/kernel/arch/ppc/arch_vm_translation_map.cpp haiku/trunk/src/system/kernel/arch/x86/paging/32bit/X86VMTranslationMap32Bit.cpp haiku/trunk/src/system/kernel/vm/VMTranslationMap.cpp Log: Moved duplicate code from the VMTranslationMap subclasses' UnmapPage() and ClearAccessedAndModified() implementations into helper methods PageUnmapped() and UnaccessedPageUnmapped() in the base class. Modified: haiku/trunk/headers/private/kernel/vm/VMTranslationMap.h =================================================================== --- haiku/trunk/headers/private/kernel/vm/VMTranslationMap.h 2010-06-21 10:58:26 UTC (rev 37186) +++ haiku/trunk/headers/private/kernel/vm/VMTranslationMap.h 2010-06-21 13:32:33 UTC (rev 37187) @@ -70,6 +70,13 @@ 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; }; Modified: haiku/trunk/src/system/kernel/arch/ppc/arch_vm_translation_map.cpp =================================================================== --- haiku/trunk/src/system/kernel/arch/ppc/arch_vm_translation_map.cpp 2010-06-21 10:58:26 UTC (rev 37186) +++ haiku/trunk/src/system/kernel/arch/ppc/arch_vm_translation_map.cpp 2010-06-21 13:32:33 UTC (rev 37187) @@ -489,52 +489,11 @@ 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; + PageUnmapped(area, pageNumber, accessed, modified, updatePageQueue); - // 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)); - } - return B_OK; } Modified: haiku/trunk/src/system/kernel/arch/x86/paging/32bit/X86VMTranslationMap32Bit.cpp =================================================================== --- haiku/trunk/src/system/kernel/arch/x86/paging/32bit/X86VMTranslationMap32Bit.cpp 2010-06-21 10:58:26 UTC (rev 37186) +++ haiku/trunk/src/system/kernel/arch/x86/paging/32bit/X86VMTranslationMap32Bit.cpp 2010-06-21 13:32:33 UTC (rev 37187) @@ -328,59 +328,13 @@ // (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); + PageUnmapped(area, (oldEntry & X86_PTE_ADDRESS_MASK) / B_PAGE_SIZE, + (oldEntry & X86_PTE_ACCESSED) != 0, (oldEntry & X86_PTE_DIRTY) != 0, + updatePageQueue); - // 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)); - } - return B_OK; } @@ -897,42 +851,12 @@ 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; } Modified: haiku/trunk/src/system/kernel/vm/VMTranslationMap.cpp =================================================================== --- haiku/trunk/src/system/kernel/vm/VMTranslationMap.cpp 2010-06-21 10:58:26 UTC (rev 37186) +++ haiku/trunk/src/system/kernel/vm/VMTranslationMap.cpp 2010-06-21 13:32:33 UTC (rev 37187) @@ -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 @@ } +/*! 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