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:
parent
7a4d60459e
commit
7ebd7cfc40
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user