* My last change to vm_page.cpp made an existing bug much more likely to
appear: when freeing a modified page, it wouldn't have a cache anymore, but set_page_state_nolock() depended on it. * To work around this, I added a vm_page_free() function, which the caches that free modified pages have to call (but others may, too). It will correctly maintain the sModifiedTemporaryPages counter in case the cache has already been removed. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23318 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -26,6 +26,7 @@ status_t vm_page_init_post_thread(struct kernel_args *args);
|
|||||||
|
|
||||||
status_t vm_mark_page_inuse(addr_t page);
|
status_t vm_mark_page_inuse(addr_t page);
|
||||||
status_t vm_mark_page_range_inuse(addr_t startPage, addr_t length);
|
status_t vm_mark_page_range_inuse(addr_t startPage, addr_t length);
|
||||||
|
void vm_page_free(struct vm_cache *cache, struct vm_page *page);
|
||||||
status_t vm_page_set_state(struct vm_page *page, int state);
|
status_t vm_page_set_state(struct vm_page *page, int state);
|
||||||
void vm_page_requeue(struct vm_page *page, bool tail);
|
void vm_page_requeue(struct vm_page *page, bool tail);
|
||||||
|
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ delete_cache(vm_cache *cache)
|
|||||||
|
|
||||||
TRACE(("vm_cache_release_ref: freeing page 0x%lx\n",
|
TRACE(("vm_cache_release_ref: freeing page 0x%lx\n",
|
||||||
oldPage->physical_page_number));
|
oldPage->physical_page_number));
|
||||||
vm_page_set_state(oldPage, PAGE_STATE_FREE);
|
vm_page_free(cache, oldPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the ref to the source
|
// remove the ref to the source
|
||||||
@@ -514,7 +514,7 @@ vm_cache_resize(vm_cache *cache, off_t newSize)
|
|||||||
|
|
||||||
// remove the page and put it into the free queue
|
// remove the page and put it into the free queue
|
||||||
vm_cache_remove_page(cache, page);
|
vm_cache_remove_page(cache, page);
|
||||||
vm_page_set_state(page, PAGE_STATE_FREE);
|
vm_page_free(cache, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
page = next;
|
page = next;
|
||||||
|
|||||||
@@ -656,17 +656,20 @@ set_page_state_nolock(vm_page *page, int pageState)
|
|||||||
panic("vm_page_set_state: invalid target state %d\n", pageState);
|
panic("vm_page_set_state: invalid target state %d\n", pageState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pageState == PAGE_STATE_CLEAR || pageState == PAGE_STATE_FREE || pageState == PAGE_STATE_INACTIVE) {
|
if (pageState == PAGE_STATE_CLEAR || pageState == PAGE_STATE_FREE
|
||||||
|
|| pageState == PAGE_STATE_INACTIVE) {
|
||||||
if (sPageDeficit > 0)
|
if (sPageDeficit > 0)
|
||||||
sFreePageCondition.NotifyOne();
|
sFreePageCondition.NotifyOne();
|
||||||
|
|
||||||
if (pageState != PAGE_STATE_INACTIVE && page->cache != NULL)
|
if (pageState != PAGE_STATE_INACTIVE && page->cache != NULL)
|
||||||
panic("to be freed page %p has cache", page);
|
panic("to be freed page %p has cache", page);
|
||||||
}
|
}
|
||||||
if (pageState == PAGE_STATE_MODIFIED && page->cache->temporary)
|
if (page->cache != NULL) {
|
||||||
sModifiedTemporaryPages++;
|
if (pageState == PAGE_STATE_MODIFIED && page->cache->temporary)
|
||||||
else if (page->state == PAGE_STATE_MODIFIED && page->cache->temporary)
|
sModifiedTemporaryPages++;
|
||||||
sModifiedTemporaryPages--;
|
else if (page->state == PAGE_STATE_MODIFIED && page->cache->temporary)
|
||||||
|
sModifiedTemporaryPages--;
|
||||||
|
}
|
||||||
|
|
||||||
#if TRACK_PAGE_ALLOCATIONS
|
#if TRACK_PAGE_ALLOCATIONS
|
||||||
if ((pageState == PAGE_STATE_CLEAR || pageState == PAGE_STATE_FREE)
|
if ((pageState == PAGE_STATE_CLEAR || pageState == PAGE_STATE_FREE)
|
||||||
@@ -1708,6 +1711,23 @@ vm_lookup_page(addr_t pageNumber)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Free the page that belonged to a certain cache.
|
||||||
|
You can use vm_page_set_state() manually if you prefer, but only
|
||||||
|
if the page does not equal PAGE_STATE_MODIFIED.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
vm_page_free(vm_cache *cache, vm_page *page)
|
||||||
|
{
|
||||||
|
InterruptsSpinLocker _(sPageLock);
|
||||||
|
|
||||||
|
if (page->cache == NULL && page->state == PAGE_STATE_MODIFIED
|
||||||
|
&& cache->temporary)
|
||||||
|
sModifiedTemporaryPages--;
|
||||||
|
|
||||||
|
set_page_state_nolock(page, PAGE_STATE_FREE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
vm_page_set_state(vm_page *page, int pageState)
|
vm_page_set_state(vm_page *page, int pageState)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user