diff --git a/src/system/kernel/vm/vm_page.cpp b/src/system/kernel/vm/vm_page.cpp index 45feb38028..2b52b4ac6a 100644 --- a/src/system/kernel/vm/vm_page.cpp +++ b/src/system/kernel/vm/vm_page.cpp @@ -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(); }