From 5036d66c8f19ca9bc555358f5e72cab37b27c171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 28 Sep 2007 21:20:57 +0000 Subject: [PATCH] vm_cache_resize() did not care about busy pages - now it does. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22353 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/vm/vm_cache.cpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/system/kernel/vm/vm_cache.cpp b/src/system/kernel/vm/vm_cache.cpp index 9117083d81..de93b7f502 100644 --- a/src/system/kernel/vm/vm_cache.cpp +++ b/src/system/kernel/vm/vm_cache.cpp @@ -482,6 +482,9 @@ vm_cache_set_minimal_commitment_locked(vm_cache *cache, off_t commitment) The cache lock must be held when you call it. Since removed pages don't belong to the cache any longer, they are not written back before they will be removed. + + Note, this function way temporarily release the cache lock in case it + has to wait for busy pages. */ status_t vm_cache_resize(vm_cache *cache, off_t newSize) @@ -499,17 +502,33 @@ vm_cache_resize(vm_cache *cache, off_t newSize) newPageCount = (uint32)((newSize + B_PAGE_SIZE - 1) >> PAGE_SHIFT); if (newPageCount < oldPageCount) { - // we need to remove all pages in the cache outside of the new virtual size - vm_page *page, *next; + // we need to remove all pages in the cache outside of the new virtual + // size + vm_page *page = cache->page_list, *next; - for (page = cache->page_list; page; page = next) { + while (page != NULL) { next = page->cache_next; if (page->cache_offset >= newPageCount) { + if (page->state == PAGE_STATE_BUSY) { + // wait for page to become unbusy + ConditionVariableEntry entry; + entry.Add(page); + mutex_unlock(&cache->lock); + entry.Wait(); + mutex_lock(&cache->lock); + + // restart from the start of the list + page = cache->page_list; + continue; + } + // remove the page and put it into the free queue vm_cache_remove_page(cache, page); vm_page_set_state(page, PAGE_STATE_FREE); } + + page = next; } }