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:
@@ -752,103 +752,10 @@ VMAnonymousCache::Merge(VMCache* _source)
|
|||||||
_Commit(actualSize);
|
_Commit(actualSize);
|
||||||
|
|
||||||
// Move all not shadowed pages from the source to the consumer cache.
|
// Move all not shadowed pages from the source to the consumer cache.
|
||||||
|
|
||||||
_MergePagesSmallerSource(source);
|
_MergePagesSmallerSource(source);
|
||||||
|
|
||||||
// Move all not shadowed swap pages from the source to the consumer cache.
|
// Move all not shadowed swap pages from the source to the consumer cache.
|
||||||
|
_MergeSwapPages(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -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 -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ private:
|
|||||||
VMAnonymousCache* source);
|
VMAnonymousCache* source);
|
||||||
void _MergePagesSmallerConsumer(
|
void _MergePagesSmallerConsumer(
|
||||||
VMAnonymousCache* source);
|
VMAnonymousCache* source);
|
||||||
|
void _MergeSwapPages(VMAnonymousCache* source);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend bool swap_free_page_swap_space(vm_page* page);
|
friend bool swap_free_page_swap_space(vm_page* page);
|
||||||
|
|||||||
Reference in New Issue
Block a user