Add a vm_page_allocate_page_run_no_base. It bases its search on the pages found

in the free and/or clear queue. This performs better in the case where only few
pages are free/clear but performs worse in the case where there are a lot of
usable pages. It's not used anywhere but it might come in handy one time.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33527 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2009-10-11 16:55:21 +00:00
parent 7a4d60459e
commit 7ebd7cfc40
2 changed files with 80 additions and 0 deletions

View File

@ -54,6 +54,7 @@ status_t vm_page_allocate_pages(int pageState, struct vm_page **pages,
uint32 numPages);
struct vm_page *vm_page_allocate_page_run(int state, addr_t base,
addr_t length);
struct vm_page *vm_page_allocate_page_run_no_base(int state, addr_t count);
struct vm_page *vm_page_at_index(int32 index);
struct vm_page *vm_lookup_page(addr_t pageNumber);

View File

@ -2263,6 +2263,85 @@ vm_page_allocate_page_run(int pageState, addr_t base, addr_t length)
}
vm_page *
vm_page_allocate_page_run_no_base(int pageState, addr_t count)
{
InterruptsSpinLocker locker(sPageLock);
if (free_page_queue_count() - sReservedPages < count) {
// TODO: add more tries, ie. free some inactive, ...
// no free space
return NULL;
}
page_queue *queue;
page_queue *otherQueue;
switch (pageState) {
case PAGE_STATE_FREE:
queue = &sFreePageQueue;
otherQueue = &sClearPageQueue;
break;
case PAGE_STATE_CLEAR:
queue = &sClearPageQueue;
otherQueue = &sFreePageQueue;
break;
default:
return NULL; // invalid
}
vm_page *firstPage = NULL;
for (uint32 twice = 0; twice < 2; twice++) {
vm_page *page = queue->head;
for (; page != NULL; page = page->queue_next) {
vm_page *current = page;
if (current >= &sPages[sNumPages - count])
continue;
bool foundRun = true;
for (uint32 i = 0; i < count; i++, current++) {
if (current->state != PAGE_STATE_FREE
&& current->state != PAGE_STATE_CLEAR) {
foundRun = false;
break;
}
}
if (foundRun) {
// pull the pages out of the appropriate queues
current = page;
for (uint32 i = 0; i < count; i++, current++) {
current->is_cleared = current->state == PAGE_STATE_CLEAR;
set_page_state_nolock(current, PAGE_STATE_BUSY);
current->usage_count = 2;
}
firstPage = page;
break;
}
}
if (firstPage != NULL)
break;
queue = otherQueue;
}
T(AllocatePageRun(count));
locker.Unlock();
if (firstPage != NULL && pageState == PAGE_STATE_CLEAR) {
vm_page *current = firstPage;
for (uint32 i = 0; i < count; i++, current++) {
if (!current->is_cleared)
clear_page(current);
}
}
return firstPage;
}
vm_page *
vm_page_at_index(int32 index)
{