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:
Augustin Cavalier
2020-06-20 21:18:57 +00:00
committed by waddlesplash
parent 0786d50332
commit be1cc9c890
+14 -7
View File
@@ -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();
}