* When reserving pages and there aren't yet enough free pages, only steal as
many pages as are actually missing, not the full count. * Take into account that free_page_queue_count() can be less than sReservedPages (when some of the reserved pages have been allocated already) in vm_page_num_unused_pages(). Before it could return negative and therefore wrapped numbers. * Simplify the page scrubber loop by continuing early. Also avoids a needless interrupt spin lock acquisition when there's nothing to do. * Some minor coding style cleanup. * Fix a typo. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32980 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -847,60 +847,55 @@ page_scrubber(void *unused)
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
snooze(100000); // 100ms
|
snooze(100000); // 100ms
|
||||||
|
|
||||||
if (sFreePageQueue.count > 0) {
|
if (sFreePageQueue.count == 0)
|
||||||
vm_page *page[SCRUB_SIZE];
|
continue;
|
||||||
int32 i, scrubCount;
|
|
||||||
|
|
||||||
// get some pages from the free queue
|
InterruptsSpinLocker locker(sPageLock);
|
||||||
|
|
||||||
InterruptsSpinLocker locker(sPageLock);
|
// Since we temporarily remove pages from the free pages reserve,
|
||||||
|
// we must make sure we don't cause a violation of the page
|
||||||
|
// reservation warranty. The following is usually stricter than
|
||||||
|
// necessary, because we don't have information on how many of the
|
||||||
|
// reserved pages have already been allocated.
|
||||||
|
int32 scrubCount = SCRUB_SIZE;
|
||||||
|
uint32 freeCount = free_page_queue_count();
|
||||||
|
if (freeCount <= sReservedPages)
|
||||||
|
continue;
|
||||||
|
|
||||||
// Since we temporarily remove pages from the free pages reserve,
|
if ((uint32)scrubCount > freeCount - sReservedPages)
|
||||||
// we must make sure we don't cause a violation of the page
|
scrubCount = freeCount - sReservedPages;
|
||||||
// reservation warranty. The following is usually stricter than
|
|
||||||
// necessary, because we don't have information on how many of the
|
|
||||||
// reserved pages have already been allocated.
|
|
||||||
scrubCount = SCRUB_SIZE;
|
|
||||||
uint32 freeCount = free_page_queue_count();
|
|
||||||
if (freeCount < sReservedPages)
|
|
||||||
scrubCount = 0;
|
|
||||||
else if ((uint32)scrubCount > freeCount - sReservedPages)
|
|
||||||
scrubCount = freeCount - sReservedPages;
|
|
||||||
|
|
||||||
for (i = 0; i < scrubCount; i++) {
|
// get some pages from the free queue
|
||||||
page[i] = dequeue_page(&sFreePageQueue);
|
vm_page *page[SCRUB_SIZE];
|
||||||
if (page[i] == NULL)
|
for (int32 i = 0; i < scrubCount; i++) {
|
||||||
break;
|
page[i] = dequeue_page(&sFreePageQueue);
|
||||||
page[i]->state = PAGE_STATE_BUSY;
|
if (page[i] == NULL) {
|
||||||
|
scrubCount = i;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
scrubCount = i;
|
page[i]->state = PAGE_STATE_BUSY;
|
||||||
|
|
||||||
if (scrubCount > 0) {
|
|
||||||
T(ScrubbingPages(scrubCount));
|
|
||||||
}
|
|
||||||
|
|
||||||
locker.Unlock();
|
|
||||||
|
|
||||||
// clear them
|
|
||||||
|
|
||||||
for (i = 0; i < scrubCount; i++) {
|
|
||||||
clear_page(page[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
locker.Lock();
|
|
||||||
|
|
||||||
// and put them into the clear queue
|
|
||||||
|
|
||||||
for (i = 0; i < scrubCount; i++) {
|
|
||||||
page[i]->state = PAGE_STATE_CLEAR;
|
|
||||||
enqueue_page(&sClearPageQueue, page[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scrubCount > 0) {
|
|
||||||
T(ScrubbedPages(scrubCount));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (scrubCount == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
T(ScrubbingPages(scrubCount));
|
||||||
|
locker.Unlock();
|
||||||
|
|
||||||
|
// clear them
|
||||||
|
for (int32 i = 0; i < scrubCount; i++)
|
||||||
|
clear_page(page[i]);
|
||||||
|
|
||||||
|
locker.Lock();
|
||||||
|
|
||||||
|
// and put them into the clear queue
|
||||||
|
for (int32 i = 0; i < scrubCount; i++) {
|
||||||
|
page[i]->state = PAGE_STATE_CLEAR;
|
||||||
|
enqueue_page(&sClearPageQueue, page[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
T(ScrubbedPages(scrubCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1443,9 +1438,9 @@ steal_pages(vm_page **pages, size_t count, bool reserve)
|
|||||||
page->state = PAGE_STATE_FREE;
|
page->state = PAGE_STATE_FREE;
|
||||||
|
|
||||||
T(StolenPage());
|
T(StolenPage());
|
||||||
} else if (stolen < maxCount) {
|
} else if (stolen < maxCount)
|
||||||
pages[stolen] = page;
|
pages[stolen] = page;
|
||||||
}
|
|
||||||
stolen++;
|
stolen++;
|
||||||
count--;
|
count--;
|
||||||
} else
|
} else
|
||||||
@@ -1870,6 +1865,7 @@ vm_page_reserve_pages(uint32 count)
|
|||||||
if (sReservedPages <= freePages)
|
if (sReservedPages <= freePages)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
count = sReservedPages - freePages;
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
steal_pages(NULL, count + 1, true);
|
steal_pages(NULL, count + 1, true);
|
||||||
@@ -1932,7 +1928,7 @@ vm_page_allocate_page(int pageState, bool reserved)
|
|||||||
panic("queue %p corrupted, count = %d\n", queue, queue->count);
|
panic("queue %p corrupted, count = %d\n", queue, queue->count);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// if the primary queue was empty, grap the page from the
|
// if the primary queue was empty, grab the page from the
|
||||||
// secondary queue
|
// secondary queue
|
||||||
page = dequeue_page(otherQueue);
|
page = dequeue_page(otherQueue);
|
||||||
}
|
}
|
||||||
@@ -2005,8 +2001,7 @@ vm_page_allocate_page_run(int pageState, addr_t base, addr_t length)
|
|||||||
|
|
||||||
InterruptsSpinLocker locker(sPageLock);
|
InterruptsSpinLocker locker(sPageLock);
|
||||||
|
|
||||||
if (sFreePageQueue.count + sClearPageQueue.count - sReservedPages
|
if (free_page_queue_count() - sReservedPages < length) {
|
||||||
< length) {
|
|
||||||
// TODO: add more tries, ie. free some inactive, ...
|
// TODO: add more tries, ie. free some inactive, ...
|
||||||
// no free space
|
// no free space
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -2183,7 +2178,12 @@ vm_page_num_free_pages(void)
|
|||||||
size_t
|
size_t
|
||||||
vm_page_num_unused_pages(void)
|
vm_page_num_unused_pages(void)
|
||||||
{
|
{
|
||||||
return free_page_queue_count() - sReservedPages;
|
size_t reservedPages = sReservedPages;
|
||||||
|
size_t count = free_page_queue_count();
|
||||||
|
if (reservedPages >= count)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return count - reservedPages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user