Author: bonefish Date: 2010-02-16 18:12:42 +0100 (Tue, 16 Feb 2010) New Revision: 35499 Changeset: http://dev.haiku-os.org/changeset/35499/haiku Modified: haiku/trunk/src/system/kernel/vm/vm_page.cpp Log: * Added some more asserts for cached pages. * full_scan_inactive_pages(): Fixed syntactical glitch (missing "else"). Affected only the active paging mode and was relatively harmless. The worst case would be that an inactive page would be moved to the cached queue although its usage_count hadn't dropped to 0 yet, thus freeing it before pages that deserved it more. * move_page_to_active_or_inactive_queue(): - Was ignoring the page's modified flag, thus potentially moving a modified page to the cached queue. That could happen only in rare cases though, like when the page was still mmap()ped while being written and modified and unmapped before being done. - No longer move the page to the inactive queue, even if its usage count is 0. In idle mode the page daemon doesn't look at inactive pages, so the page's stats wouldn't be updated anymore. - Renamed to move_page_to_appropriate_queue(). Modified: haiku/trunk/src/system/kernel/vm/vm_page.cpp =================================================================== --- haiku/trunk/src/system/kernel/vm/vm_page.cpp 2010-02-16 16:54:01 UTC (rev 35498) +++ haiku/trunk/src/system/kernel/vm/vm_page.cpp 2010-02-16 17:12:42 UTC (rev 35499) @@ -1082,6 +1082,7 @@ break; case PAGE_STATE_CACHED: ASSERT(page->wired_count == 0 && page->mappings.IsEmpty()); + ASSERT(!page->modified); toQueue = &sCachedPageQueue; break; case PAGE_STATE_FREE: @@ -1128,23 +1129,22 @@ } -/*! Moves a modified page into either the active or inactive page queue - depending on its usage count and wiring. +/*! Moves a previously modified page into a now appropriate queue. The page queues must not be locked. */ static void -move_page_to_active_or_inactive_queue(vm_page *page) +move_page_to_appropriate_queue(vm_page *page) { DEBUG_PAGE_ACCESS_CHECK(page); - // Note, this logic must be in sync with what the page daemon does + // Note, this logic must be in sync with what the page daemon does. int32 state; - if (page->mappings.IsEmpty() && page->wired_count == 0) - state = PAGE_STATE_CACHED; - else if (page->usage_count > 0) + if (!page->mappings.IsEmpty() || page->wired_count > 0) state = PAGE_STATE_ACTIVE; + else if (page->modified) + state = PAGE_STATE_MODIFIED; else - state = PAGE_STATE_INACTIVE; + state = PAGE_STATE_CACHED; // TODO: If free + cached pages are low, we might directly want to free the // page. @@ -1431,7 +1431,7 @@ if (result == B_OK) { // put it into the active/inactive queue - move_page_to_active_or_inactive_queue(fPage); + move_page_to_appropriate_queue(fPage); fPage->busy_writing = false; DEBUG_PAGE_ACCESS_END(fPage); } else { @@ -1923,6 +1923,10 @@ static bool free_cached_page(vm_page *page, bool dontWait) { + ASSERT(!page->busy); + ASSERT(!page->modified); + ASSERT(page->wired_count == 0 && page->mappings.IsEmpty()); + // try to lock the page's cache if (vm_cache_acquire_locked_page_cache(page, dontWait) == NULL) return false; @@ -2151,7 +2155,7 @@ pagesToActive++; } else vm_page_requeue(page, true); - } if (isMapped) { + } else if (isMapped) { vm_page_requeue(page, true); } else if (!page->modified) { set_page_state(page, PAGE_STATE_CACHED);