* 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:
Michael Lotz 2009-09-07 02:08:09 +00:00
parent 156b8d5d2d
commit 257f000bd2

View File

@ -847,60 +847,55 @@ page_scrubber(void *unused)
for (;;) {
snooze(100000); // 100ms
if (sFreePageQueue.count > 0) {
vm_page *page[SCRUB_SIZE];
int32 i, scrubCount;
if (sFreePageQueue.count == 0)
continue;
// 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,
// 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.
scrubCount = SCRUB_SIZE;
uint32 freeCount = free_page_queue_count();
if (freeCount < sReservedPages)
scrubCount = 0;
else if ((uint32)scrubCount > freeCount - sReservedPages)
scrubCount = freeCount - sReservedPages;
if ((uint32)scrubCount > freeCount - sReservedPages)
scrubCount = freeCount - sReservedPages;
for (i = 0; i < scrubCount; i++) {
page[i] = dequeue_page(&sFreePageQueue);
if (page[i] == NULL)
break;
page[i]->state = PAGE_STATE_BUSY;
// get some pages from the free queue
vm_page *page[SCRUB_SIZE];
for (int32 i = 0; i < scrubCount; i++) {
page[i] = dequeue_page(&sFreePageQueue);
if (page[i] == NULL) {
scrubCount = i;
break;
}
scrubCount = i;
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));
}
page[i]->state = PAGE_STATE_BUSY;
}
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;
@ -1443,9 +1438,9 @@ steal_pages(vm_page **pages, size_t count, bool reserve)
page->state = PAGE_STATE_FREE;
T(StolenPage());
} else if (stolen < maxCount) {
} else if (stolen < maxCount)
pages[stolen] = page;
}
stolen++;
count--;
} else
@ -1870,6 +1865,7 @@ vm_page_reserve_pages(uint32 count)
if (sReservedPages <= freePages)
return;
count = sReservedPages - freePages;
locker.Unlock();
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);
#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
page = dequeue_page(otherQueue);
}
@ -2005,8 +2001,7 @@ vm_page_allocate_page_run(int pageState, addr_t base, addr_t length)
InterruptsSpinLocker locker(sPageLock);
if (sFreePageQueue.count + sClearPageQueue.count - sReservedPages
< length) {
if (free_page_queue_count() - sReservedPages < length) {
// TODO: add more tries, ie. free some inactive, ...
// no free space
return NULL;
@ -2183,7 +2178,12 @@ vm_page_num_free_pages(void)
size_t
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;
}