kernel/vm: Make the page_scrubber wait on a condition.
On an idle system with 1GB RAM and the 100ms timeout, it takes multiple minutes for all the pages in the system to get cleared after boot, but once they do, the page scrubber will then remain idle for seconds to even minutes at a time, so this is clearly worth it. The "free pages condition" was unused before this commit, so I have repurposed it (and unpublished it.) Change-Id: I7034677a1e51c97c2baf11b772db3a31c0e1adfa Reviewed-on: https://review.haiku-os.org/c/haiku/+/1699 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
0786d50332
commit
be1cc9c890
@@ -63,7 +63,7 @@
|
||||
#define PAGE_ASSERT(page, condition) \
|
||||
ASSERT_PRINT((condition), "page: %p", (page))
|
||||
|
||||
#define SCRUB_SIZE 16
|
||||
#define SCRUB_SIZE 32
|
||||
// this many pages will be cleared at once in the page scrubber thread
|
||||
|
||||
#define MAX_PAGE_WRITER_IO_PRIORITY B_URGENT_DISPLAY_PRIORITY
|
||||
@@ -1521,6 +1521,7 @@ free_page(vm_page* page, bool clear)
|
||||
} else {
|
||||
page->SetState(PAGE_STATE_FREE);
|
||||
sFreePageQueue.PrependUnlocked(page);
|
||||
sFreePageCondition.NotifyAll();
|
||||
}
|
||||
|
||||
locker.Unlock();
|
||||
@@ -1726,7 +1727,7 @@ mark_page_range_in_use(page_num_t startPage, page_num_t length, bool wired)
|
||||
|
||||
|
||||
/*!
|
||||
This is a background thread that wakes up every now and then (every 100ms)
|
||||
This is a background thread that wakes up when its condition is notified
|
||||
and moves some pages from the free queue over to the clear queue.
|
||||
Given enough time, it will clear out all pages from the free queue - we
|
||||
could probably slow it down after having reached a certain threshold.
|
||||
@@ -1738,13 +1739,13 @@ page_scrubber(void *unused)
|
||||
|
||||
TRACE(("page_scrubber starting...\n"));
|
||||
|
||||
ConditionVariableEntry entry;
|
||||
for (;;) {
|
||||
snooze(100000); // 100ms
|
||||
|
||||
if (sFreePageQueue.Count() == 0
|
||||
while (sFreePageQueue.Count() == 0
|
||||
|| atomic_get(&sUnreservedFreePages)
|
||||
< (int32)sFreePagesTarget) {
|
||||
continue;
|
||||
sFreePageCondition.Add(&entry);
|
||||
entry.Wait();
|
||||
}
|
||||
|
||||
// Since we temporarily remove pages from the free pages reserve,
|
||||
@@ -1802,6 +1803,9 @@ page_scrubber(void *unused)
|
||||
unreserve_pages(reserved);
|
||||
|
||||
TA(ScrubbedPages(scrubCount));
|
||||
|
||||
// wait at least 100ms between runs
|
||||
snooze(100 * 1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2584,6 +2588,8 @@ free_cached_pages(uint32 pagesToFree, bool dontWait)
|
||||
|
||||
remove_page_marker(marker);
|
||||
|
||||
sFreePageCondition.NotifyAll();
|
||||
|
||||
return pagesFreed;
|
||||
}
|
||||
|
||||
@@ -3401,7 +3407,6 @@ status_t
|
||||
vm_page_init_post_thread(kernel_args *args)
|
||||
{
|
||||
new (&sFreePageCondition) ConditionVariable;
|
||||
sFreePageCondition.Publish(&sFreePageQueue, "free page");
|
||||
|
||||
// create a kernel thread to clear out pages
|
||||
|
||||
@@ -3603,6 +3608,8 @@ allocate_page_run_cleanup(VMPageQueue::PageList& freePages,
|
||||
DEBUG_PAGE_ACCESS_END(page);
|
||||
sClearPageQueue.PrependUnlocked(page);
|
||||
}
|
||||
|
||||
sFreePageCondition.NotifyAll();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user