* 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:
parent
e3145a8d8d
commit
bcb71f00e8
@ -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_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);
|
||||
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",
|
||||
oldPage->physical_page_number));
|
||||
vm_page_set_state(oldPage, PAGE_STATE_FREE);
|
||||
vm_page_free(cache, oldPage);
|
||||
}
|
||||
|
||||
// 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
|
||||
vm_cache_remove_page(cache, page);
|
||||
vm_page_set_state(page, PAGE_STATE_FREE);
|
||||
vm_page_free(cache, page);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
sFreePageCondition.NotifyOne();
|
||||
|
||||
if (pageState != PAGE_STATE_INACTIVE && page->cache != NULL)
|
||||
panic("to be freed page %p has cache", page);
|
||||
}
|
||||
if (pageState == PAGE_STATE_MODIFIED && page->cache->temporary)
|
||||
sModifiedTemporaryPages++;
|
||||
else if (page->state == PAGE_STATE_MODIFIED && page->cache->temporary)
|
||||
sModifiedTemporaryPages--;
|
||||
if (page->cache != NULL) {
|
||||
if (pageState == PAGE_STATE_MODIFIED && page->cache->temporary)
|
||||
sModifiedTemporaryPages++;
|
||||
else if (page->state == PAGE_STATE_MODIFIED && page->cache->temporary)
|
||||
sModifiedTemporaryPages--;
|
||||
}
|
||||
|
||||
#if TRACK_PAGE_ALLOCATIONS
|
||||
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
|
||||
vm_page_set_state(vm_page *page, int pageState)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user