Moved merging swap pages from Merge() to a separate method.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34779 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-12-26 21:05:38 +00:00
parent 4566a632c6
commit c2d5972b6a
2 changed files with 100 additions and 94 deletions
+99 -94
View File
@@ -752,103 +752,10 @@ VMAnonymousCache::Merge(VMCache* _source)
_Commit(actualSize);
// Move all not shadowed pages from the source to the consumer cache.
_MergePagesSmallerSource(source);
// Move all not shadowed swap pages from the source to the consumer cache.
for (off_t offset = source->virtual_base
& ~(off_t)(B_PAGE_SIZE * SWAP_BLOCK_PAGES - 1);
offset < source->virtual_end;
offset += B_PAGE_SIZE * SWAP_BLOCK_PAGES) {
WriteLocker locker(sSwapHashLock);
page_num_t swapBlockPageIndex = offset >> PAGE_SHIFT;
swap_hash_key key = { source, swapBlockPageIndex };
swap_block* sourceSwapBlock = sSwapHashTable.Lookup(key);
if (sourceSwapBlock == NULL)
continue;
// remove the source swap block -- we will either take over the swap
// space (and the block) or free it
sSwapHashTable.RemoveUnchecked(sourceSwapBlock);
key.cache = this;
swap_block* swapBlock = sSwapHashTable.Lookup(key);
locker.Unlock();
for (uint32 i = 0; i < SWAP_BLOCK_PAGES; i++) {
off_t pageIndex = swapBlockPageIndex + i;
swap_addr_t sourceSlotIndex = sourceSwapBlock->swap_slots[i];
if (sourceSlotIndex == SWAP_SLOT_NONE)
// this page is not swapped out
continue;
vm_page* page = LookupPage((off_t)pageIndex << PAGE_SHIFT);
bool keepSwapPage = true;
if (page != NULL && !page->merge_swap) {
// The consumer already has a page at this index and it wasn't
// one taken over from the source. So we can simply free the
// swap space.
keepSwapPage = false;
} else {
if (page != NULL) {
// The page was taken over from the source cache. Clear the
// indicator flag. We'll take over the swap page too.
page->merge_swap = false;
} else if (swapBlock != NULL
&& swapBlock->swap_slots[i] != SWAP_SLOT_NONE) {
// There's no page in the consumer cache, but a swap page.
// Free the source swap page.
keepSwapPage = false;
}
}
if (!keepSwapPage) {
swap_slot_dealloc(sourceSlotIndex, 1);
sourceSwapBlock->swap_slots[i] = SWAP_SLOT_NONE;
sourceSwapBlock->used--;
}
// We've either freed the source swap page or are going to move it
// to the consumer. At any rate, the source cache doesn't own it
// anymore.
source->fAllocatedSwapSize -= B_PAGE_SIZE;
}
// All source swap pages that have not been freed yet are taken over by
// the consumer.
fAllocatedSwapSize += B_PAGE_SIZE * (off_t)sourceSwapBlock->used;
if (sourceSwapBlock->used == 0) {
// All swap pages have been freed -- we can discard the source swap
// block.
object_cache_free(sSwapBlockCache, sourceSwapBlock);
} else if (swapBlock == NULL) {
// We need to take over some of the source's swap pages and there's
// no swap block in the consumer cache. Just take over the source
// swap block.
sourceSwapBlock->key.cache = this;
locker.Lock();
sSwapHashTable.InsertUnchecked(sourceSwapBlock);
locker.Unlock();
} else {
// We need to take over some of the source's swap pages and there's
// already swap block in the consumer cache. Copy the respective
// swap addresses and discard the source swap block.
for (uint32 i = 0; i < SWAP_BLOCK_PAGES; i++) {
if (sourceSwapBlock->swap_slots[i] != SWAP_SLOT_NONE)
swapBlock->swap_slots[i] = sourceSwapBlock->swap_slots[i];
}
object_cache_free(sSwapBlockCache, sourceSwapBlock);
}
}
_MergeSwapPages(source);
}
@@ -1044,6 +951,104 @@ VMAnonymousCache::_MergePagesSmallerSource(VMAnonymousCache* source)
}
void
VMAnonymousCache::_MergeSwapPages(VMAnonymousCache* source)
{
for (off_t offset = source->virtual_base
& ~(off_t)(B_PAGE_SIZE * SWAP_BLOCK_PAGES - 1);
offset < source->virtual_end;
offset += B_PAGE_SIZE * SWAP_BLOCK_PAGES) {
WriteLocker locker(sSwapHashLock);
page_num_t swapBlockPageIndex = offset >> PAGE_SHIFT;
swap_hash_key key = { source, swapBlockPageIndex };
swap_block* sourceSwapBlock = sSwapHashTable.Lookup(key);
if (sourceSwapBlock == NULL)
continue;
// remove the source swap block -- we will either take over the swap
// space (and the block) or free it
sSwapHashTable.RemoveUnchecked(sourceSwapBlock);
key.cache = this;
swap_block* swapBlock = sSwapHashTable.Lookup(key);
locker.Unlock();
for (uint32 i = 0; i < SWAP_BLOCK_PAGES; i++) {
off_t pageIndex = swapBlockPageIndex + i;
swap_addr_t sourceSlotIndex = sourceSwapBlock->swap_slots[i];
if (sourceSlotIndex == SWAP_SLOT_NONE)
// this page is not swapped out
continue;
vm_page* page = LookupPage((off_t)pageIndex << PAGE_SHIFT);
bool keepSwapPage = true;
if (page != NULL && !page->merge_swap) {
// The consumer already has a page at this index and it wasn't
// one taken over from the source. So we can simply free the
// swap space.
keepSwapPage = false;
} else {
if (page != NULL) {
// The page was taken over from the source cache. Clear the
// indicator flag. We'll take over the swap page too.
page->merge_swap = false;
} else if (swapBlock != NULL
&& swapBlock->swap_slots[i] != SWAP_SLOT_NONE) {
// There's no page in the consumer cache, but a swap page.
// Free the source swap page.
keepSwapPage = false;
}
}
if (!keepSwapPage) {
swap_slot_dealloc(sourceSlotIndex, 1);
sourceSwapBlock->swap_slots[i] = SWAP_SLOT_NONE;
sourceSwapBlock->used--;
}
// We've either freed the source swap page or are going to move it
// to the consumer. At any rate, the source cache doesn't own it
// anymore.
source->fAllocatedSwapSize -= B_PAGE_SIZE;
}
// All source swap pages that have not been freed yet are taken over by
// the consumer.
fAllocatedSwapSize += B_PAGE_SIZE * (off_t)sourceSwapBlock->used;
if (sourceSwapBlock->used == 0) {
// All swap pages have been freed -- we can discard the source swap
// block.
object_cache_free(sSwapBlockCache, sourceSwapBlock);
} else if (swapBlock == NULL) {
// We need to take over some of the source's swap pages and there's
// no swap block in the consumer cache. Just take over the source
// swap block.
sourceSwapBlock->key.cache = this;
locker.Lock();
sSwapHashTable.InsertUnchecked(sourceSwapBlock);
locker.Unlock();
} else {
// We need to take over some of the source's swap pages and there's
// already swap block in the consumer cache. Copy the respective
// swap addresses and discard the source swap block.
for (uint32 i = 0; i < SWAP_BLOCK_PAGES; i++) {
if (sourceSwapBlock->swap_slots[i] != SWAP_SLOT_NONE)
swapBlock->swap_slots[i] = sourceSwapBlock->swap_slots[i];
}
object_cache_free(sSwapBlockCache, sourceSwapBlock);
}
}
}
// #pragma mark -
+1
View File
@@ -72,6 +72,7 @@ private:
VMAnonymousCache* source);
void _MergePagesSmallerConsumer(
VMAnonymousCache* source);
void _MergeSwapPages(VMAnonymousCache* source);
private:
friend bool swap_free_page_swap_space(vm_page* page);