vm_page no longer points directly to its containing cache, but rather to a

VMCacheRef object which points to the cache. This allows to optimize
VMCache::MoveAllPages(), since it no longer needs to iterate over all pages
to adjust their cache pointer. It can simple swap the cache refs of the two
caches instead.

Reduces the total -j8 Haiku image build time only marginally. The kernel time
drops almost 10%, though.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35155 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2010-01-19 08:34:14 +00:00
parent 2416d6ae42
commit 6379e53e2d
8 changed files with 114 additions and 58 deletions
+3
View File
@@ -61,6 +61,7 @@ struct VMCachePagesTreeDefinition {
typedef IteratableSplayTree<VMCachePagesTreeDefinition> VMCachePagesTree; typedef IteratableSplayTree<VMCachePagesTreeDefinition> VMCachePagesTree;
struct VMCache { struct VMCache {
public: public:
VMCache(); VMCache();
@@ -171,6 +172,7 @@ public:
private: private:
struct PageEventWaiter; struct PageEventWaiter;
friend struct VMCacheRef;
private: private:
void _NotifyPageEvents(vm_page* page, uint32 events); void _NotifyPageEvents(vm_page* page, uint32 events);
@@ -185,6 +187,7 @@ private:
mutex fLock; mutex fLock;
PageEventWaiter* fPageEventWaiters; PageEventWaiter* fPageEventWaiters;
void* fUserData; void* fUserData;
VMCacheRef* fCacheRef;
}; };
+20 -1
View File
@@ -26,6 +26,7 @@
class AsyncIOCallback; class AsyncIOCallback;
struct vm_page_mapping; struct vm_page_mapping;
struct VMCache; struct VMCache;
struct VMCacheRef;
typedef DoublyLinkedListLink<vm_page_mapping> vm_page_mapping_link; typedef DoublyLinkedListLink<vm_page_mapping> vm_page_mapping_link;
@@ -71,12 +72,23 @@ typedef class DoublyLinkedQueue<vm_page_mapping, DoublyLinkedAreaLink>
typedef uint32 page_num_t; typedef uint32 page_num_t;
struct VMCacheRef {
VMCache* cache;
int32 ref_count;
VMCacheRef(VMCache* cache);
};
struct vm_page { struct vm_page {
DoublyLinkedListLink<vm_page> queue_link; DoublyLinkedListLink<vm_page> queue_link;
addr_t physical_page_number; addr_t physical_page_number;
VMCache* cache; private:
VMCacheRef* cache_ref;
public:
page_num_t cache_offset; page_num_t cache_offset;
// in page size units // in page size units
@@ -103,6 +115,13 @@ struct vm_page {
int8 usage_count; int8 usage_count;
uint16 wired_count; uint16 wired_count;
VMCacheRef* CacheRef() const { return cache_ref; }
void SetCacheRef(VMCacheRef* cacheRef) { this->cache_ref = cacheRef; }
VMCache* Cache() const
{ return cache_ref != NULL ? cache_ref->cache : NULL; }
}; };
@@ -768,7 +768,7 @@ X86VMTranslationMap::UnmapArea(VMArea* area, bool deletingAddressSpace,
if (page->wired_count == 0 && page->mappings.IsEmpty()) if (page->wired_count == 0 && page->mappings.IsEmpty())
atomic_add(&gMappedPagesCount, -1); atomic_add(&gMappedPagesCount, -1);
if (unmapPages || page->cache != area->cache) { if (unmapPages || page->Cache() != area->cache) {
addr_t address = area->Base() addr_t address = area->Base()
+ ((page->cache_offset * B_PAGE_SIZE) - area->cache_offset); + ((page->cache_offset * B_PAGE_SIZE) - area->cache_offset);
+1 -1
View File
@@ -1286,7 +1286,7 @@ swap_init_post_modules()
bool bool
swap_free_page_swap_space(vm_page* page) swap_free_page_swap_space(vm_page* page)
{ {
VMAnonymousCache* cache = dynamic_cast<VMAnonymousCache*>(page->cache); VMAnonymousCache* cache = dynamic_cast<VMAnonymousCache*>(page->Cache());
if (cache == NULL) if (cache == NULL)
return false; return false;
+53 -20
View File
@@ -491,15 +491,21 @@ vm_cache_acquire_locked_page_cache(vm_page* page, bool dontWait)
mutex_lock(&sCacheListLock); mutex_lock(&sCacheListLock);
while (dontWait) { while (dontWait) {
VMCache* cache = page->cache; VMCacheRef* cacheRef = page->CacheRef();
if (cache == NULL || !cache->TryLock()) { if (cacheRef == NULL) {
mutex_unlock(&sCacheListLock); mutex_unlock(&sCacheListLock);
return NULL; return NULL;
} }
if (cache == page->cache) { VMCache* cache = cacheRef->cache;
cache->AcquireRefLocked(); if (!cache->TryLock()) {
mutex_unlock(&sCacheListLock); mutex_unlock(&sCacheListLock);
return NULL;
}
if (cacheRef == page->CacheRef()) {
mutex_unlock(&sCacheListLock);
cache->AcquireRefLocked();
return cache; return cache;
} }
@@ -508,26 +514,28 @@ vm_cache_acquire_locked_page_cache(vm_page* page, bool dontWait)
} }
while (true) { while (true) {
VMCache* cache = page->cache; VMCacheRef* cacheRef = page->CacheRef();
if (cache == NULL) { if (cacheRef == NULL) {
mutex_unlock(&sCacheListLock); mutex_unlock(&sCacheListLock);
return NULL; return NULL;
} }
VMCache* cache = cacheRef->cache;
if (!cache->SwitchLock(&sCacheListLock)) { if (!cache->SwitchLock(&sCacheListLock)) {
// cache has been deleted // cache has been deleted
mutex_lock(&sCacheListLock); mutex_lock(&sCacheListLock);
continue; continue;
} }
if (cache == page->cache) { mutex_lock(&sCacheListLock);
if (cache == page->Cache()) {
mutex_unlock(&sCacheListLock);
cache->AcquireRefLocked(); cache->AcquireRefLocked();
return cache; return cache;
} }
// the cache changed in the meantime // the cache changed in the meantime
cache->Unlock(); cache->Unlock();
mutex_lock(&sCacheListLock);
} }
} }
@@ -535,6 +543,17 @@ vm_cache_acquire_locked_page_cache(vm_page* page, bool dontWait)
// #pragma mark - VMCache // #pragma mark - VMCache
VMCacheRef::VMCacheRef(VMCache* cache)
:
cache(cache),
ref_count(1)
{
}
// #pragma mark - VMCache
bool bool
VMCache::_IsMergeable() const VMCache::_IsMergeable() const
{ {
@@ -545,12 +564,15 @@ VMCache::_IsMergeable() const
VMCache::VMCache() VMCache::VMCache()
:
fCacheRef(NULL)
{ {
} }
VMCache::~VMCache() VMCache::~VMCache()
{ {
delete fCacheRef;
} }
@@ -572,6 +594,10 @@ VMCache::Init(uint32 cacheType)
type = cacheType; type = cacheType;
fPageEventWaiters = NULL; fPageEventWaiters = NULL;
fCacheRef = new(nogrow) VMCacheRef(this);
if (fCacheRef == NULL)
return B_NO_MEMORY;
#if DEBUG_CACHE_LIST #if DEBUG_CACHE_LIST
mutex_lock(&sCacheListLock); mutex_lock(&sCacheListLock);
@@ -607,8 +633,7 @@ VMCache::Delete()
// remove it // remove it
pages.Remove(page); pages.Remove(page);
page->cache = NULL; page->SetCacheRef(NULL);
// TODO: we also need to remove all of the page's mappings!
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));
@@ -689,7 +714,7 @@ VMCache::LookupPage(off_t offset)
vm_page* page = pages.Lookup((page_num_t)(offset >> PAGE_SHIFT)); vm_page* page = pages.Lookup((page_num_t)(offset >> PAGE_SHIFT));
#if KDEBUG #if KDEBUG
if (page != NULL && page->cache != this) if (page != NULL && page->Cache() != this)
panic("page %p not in cache %p\n", page, this); panic("page %p not in cache %p\n", page, this);
#endif #endif
@@ -704,9 +729,9 @@ VMCache::InsertPage(vm_page* page, off_t offset)
this, page, offset)); this, page, offset));
AssertLocked(); AssertLocked();
if (page->cache != NULL) { if (page->CacheRef() != NULL) {
panic("insert page %p into cache %p: page cache is set to %p\n", panic("insert page %p into cache %p: page cache is set to %p\n",
page, this, page->cache); page, this, page->Cache());
} }
T2(InsertPage(this, page, offset)); T2(InsertPage(this, page, offset));
@@ -714,7 +739,7 @@ VMCache::InsertPage(vm_page* page, off_t offset)
page->cache_offset = (page_num_t)(offset >> PAGE_SHIFT); page->cache_offset = (page_num_t)(offset >> PAGE_SHIFT);
page_count++; page_count++;
page->usage_count = 2; page->usage_count = 2;
page->cache = this; page->SetCacheRef(fCacheRef);
#if KDEBUG #if KDEBUG
vm_page* otherPage = pages.Lookup(page->cache_offset); vm_page* otherPage = pages.Lookup(page->cache_offset);
@@ -739,16 +764,16 @@ VMCache::RemovePage(vm_page* page)
TRACE(("VMCache::RemovePage(): cache %p, page %p\n", this, page)); TRACE(("VMCache::RemovePage(): cache %p, page %p\n", this, page));
AssertLocked(); AssertLocked();
if (page->cache != this) { if (page->Cache() != this) {
panic("remove page %p from cache %p: page cache is set to %p\n", page, panic("remove page %p from cache %p: page cache is set to %p\n", page,
this, page->cache); this, page->Cache());
} }
T2(RemovePage(this, page)); T2(RemovePage(this, page));
pages.Remove(page); pages.Remove(page);
page->cache = NULL;
page_count--; page_count--;
page->SetCacheRef(NULL);
} }
@@ -758,7 +783,7 @@ VMCache::RemovePage(vm_page* page)
void void
VMCache::MovePage(vm_page* page) VMCache::MovePage(vm_page* page)
{ {
VMCache* oldCache = page->cache; VMCache* oldCache = page->Cache();
AssertLocked(); AssertLocked();
oldCache->AssertLocked(); oldCache->AssertLocked();
@@ -771,7 +796,7 @@ VMCache::MovePage(vm_page* page)
// insert here // insert here
pages.Insert(page); pages.Insert(page);
page_count++; page_count++;
page->cache = this; page->SetCacheRef(fCacheRef);
T2(InsertPage(this, page, page->cache_offset << PAGE_SHIFT)); T2(InsertPage(this, page, page->cache_offset << PAGE_SHIFT));
} }
@@ -790,12 +815,20 @@ VMCache::MoveAllPages(VMCache* fromCache)
page_count = fromCache->page_count; page_count = fromCache->page_count;
fromCache->page_count = 0; fromCache->page_count = 0;
// swap the VMCacheRefs
mutex_lock(&sCacheListLock);
std::swap(fCacheRef, fromCache->fCacheRef);
fCacheRef->cache = this;
fromCache->fCacheRef->cache = fromCache;
mutex_unlock(&sCacheListLock);
#if VM_CACHE_TRACING >= 2
for (VMCachePagesTree::Iterator it = pages.GetIterator(); for (VMCachePagesTree::Iterator it = pages.GetIterator();
vm_page* page = it.Next();) { vm_page* page = it.Next();) {
page->cache = this;
T2(RemovePage(fromCache, page)); T2(RemovePage(fromCache, page));
T2(InsertPage(this, page, page->cache_offset << PAGE_SHIFT)); T2(InsertPage(this, page, page->cache_offset << PAGE_SHIFT));
} }
#endif
} }
+4 -4
View File
@@ -3686,7 +3686,7 @@ fault_get_page(PageFaultContext& context)
// insert the new page into our cache // insert the new page into our cache
cache->InsertPage(page, context.cacheOffset); cache->InsertPage(page, context.cacheOffset);
} else if (page->cache != context.topCache && context.isWrite) { } else if (page->Cache() != context.topCache && context.isWrite) {
// We have a page that has the data we want, but in the wrong cache // We have a page that has the data we want, but in the wrong cache
// object so we need to copy it and stick it into the top cache. // object so we need to copy it and stick it into the top cache.
vm_page* sourcePage = page; vm_page* sourcePage = page;
@@ -3709,7 +3709,7 @@ fault_get_page(PageFaultContext& context)
context.cacheChainLocker.RelockCaches(true); context.cacheChainLocker.RelockCaches(true);
sourcePage->state = sourcePageState; sourcePage->state = sourcePageState;
sourcePage->cache->NotifyPageEvents(sourcePage, PAGE_EVENT_NOT_BUSY); sourcePage->Cache()->NotifyPageEvents(sourcePage, PAGE_EVENT_NOT_BUSY);
// insert the new page into our cache // insert the new page into our cache
context.topCache->InsertPage(page, context.cacheOffset); context.topCache->InsertPage(page, context.cacheOffset);
@@ -3824,7 +3824,7 @@ vm_soft_fault(VMAddressSpace* addressSpace, addr_t originalAddress,
// it's mapped in read-only, so that we cannot overwrite someone else's // it's mapped in read-only, so that we cannot overwrite someone else's
// data (copy-on-write) // data (copy-on-write)
uint32 newProtection = protection; uint32 newProtection = protection;
if (context.page->cache != context.topCache && !isWrite) if (context.page->Cache() != context.topCache && !isWrite)
newProtection &= ~(B_WRITE_AREA | B_KERNEL_WRITE_AREA); newProtection &= ~(B_WRITE_AREA | B_KERNEL_WRITE_AREA);
bool unmapPage = false; bool unmapPage = false;
@@ -5210,7 +5210,7 @@ _user_set_memory_protection(void* _address, size_t size, int protection)
// If the page is not in the topmost cache and write access is // If the page is not in the topmost cache and write access is
// requested, we have to unmap it. Otherwise we can re-map it with // requested, we have to unmap it. Otherwise we can re-map it with
// the new protection. // the new protection.
bool unmapPage = page->cache != topCache bool unmapPage = page->Cache() != topCache
&& (protection & B_WRITE_AREA) != 0; && (protection & B_WRITE_AREA) != 0;
if (!unmapPage) { if (!unmapPage) {
+5 -5
View File
@@ -67,8 +67,7 @@ PageCacheLocker::_IgnorePage(vm_page* page)
{ {
if (page->state == PAGE_STATE_WIRED || page->state == PAGE_STATE_BUSY if (page->state == PAGE_STATE_WIRED || page->state == PAGE_STATE_BUSY
|| page->state == PAGE_STATE_FREE || page->state == PAGE_STATE_CLEAR || page->state == PAGE_STATE_FREE || page->state == PAGE_STATE_CLEAR
|| page->state == PAGE_STATE_UNUSED || page->wired_count > 0 || page->state == PAGE_STATE_UNUSED || page->wired_count > 0)
|| page->cache == NULL)
return true; return true;
return false; return false;
@@ -102,7 +101,7 @@ PageCacheLocker::Unlock()
if (fPage == NULL) if (fPage == NULL)
return; return;
fPage->cache->ReleaseRefAndUnlock(); fPage->Cache()->ReleaseRefAndUnlock();
fPage = NULL; fPage = NULL;
} }
@@ -342,8 +341,9 @@ free_page_swap_space(int32 index)
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
if (page->cache->temporary && page->wired_count == 0 VMCache* cache = page->Cache();
&& page->cache->HasPage(page->cache_offset << PAGE_SHIFT) if (cache->temporary && page->wired_count == 0
&& cache->HasPage(page->cache_offset << PAGE_SHIFT)
&& page->usage_count > 0) { && page->usage_count > 0) {
// TODO: how to judge a page is highly active? // TODO: how to judge a page is highly active?
if (swap_free_page_swap_space(page)) { if (swap_free_page_swap_space(page)) {
+27 -26
View File
@@ -240,7 +240,7 @@ class WritePage : public AbstractTraceEntry {
public: public:
WritePage(vm_page* page) WritePage(vm_page* page)
: :
fCache(page->cache), fCache(page->Cache()),
fPage(page) fPage(page)
{ {
Initialized(); Initialized();
@@ -404,7 +404,7 @@ dump_page(int argc, char **argv)
kprintf("queue_next,prev: %p, %p\n", page->queue_link.next, kprintf("queue_next,prev: %p, %p\n", page->queue_link.next,
page->queue_link.previous); page->queue_link.previous);
kprintf("physical_number: %#lx\n", page->physical_page_number); kprintf("physical_number: %#lx\n", page->physical_page_number);
kprintf("cache: %p\n", page->cache); kprintf("cache: %p\n", page->Cache());
kprintf("cache_offset: %ld\n", page->cache_offset); kprintf("cache_offset: %ld\n", page->cache_offset);
kprintf("cache_next: %p\n", page->cache_next); kprintf("cache_next: %p\n", page->cache_next);
kprintf("is dummy: %d\n", page->is_dummy); kprintf("is dummy: %d\n", page->is_dummy);
@@ -496,8 +496,8 @@ dump_page_queue(int argc, char **argv)
const char *type = "none"; const char *type = "none";
int i; int i;
if (page->cache != NULL) { if (page->Cache() != NULL) {
switch (page->cache->type) { switch (page->Cache()->type) {
case CACHE_TYPE_RAM: case CACHE_TYPE_RAM:
type = "RAM"; type = "RAM";
break; break;
@@ -518,7 +518,7 @@ dump_page_queue(int argc, char **argv)
kprintf("page cache type state wired usage\n"); kprintf("page cache type state wired usage\n");
for (i = 0; page; i++, page = queue->Next(page)) { for (i = 0; page; i++, page = queue->Next(page)) {
kprintf("%p %p %-7s %8s %5d %5d\n", page, page->cache, kprintf("%p %p %-7s %8s %5d %5d\n", page, page->Cache(),
type, page_state_to_string(page->state), type, page_state_to_string(page->state),
page->wired_count, page->usage_count); page->wired_count, page->usage_count);
} }
@@ -543,8 +543,8 @@ dump_page_stats(int argc, char **argv)
counter[sPages[i].state]++; counter[sPages[i].state]++;
if (sPages[i].state == PAGE_STATE_MODIFIED && sPages[i].cache != NULL if (sPages[i].state == PAGE_STATE_MODIFIED && sPages[i].Cache() != NULL
&& sPages[i].cache->temporary && sPages[i].wired_count == 0) { && sPages[i].Cache()->temporary && sPages[i].wired_count == 0) {
swappableModified++; swappableModified++;
if (sPages[i].usage_count < 0) if (sPages[i].usage_count < 0)
swappableModifiedInactive++; swappableModifiedInactive++;
@@ -610,7 +610,7 @@ free_page(vm_page* page, bool clear)
return; return;
} }
if (page->cache != NULL) if (page->CacheRef() != NULL)
panic("to be freed page %p has cache", page); panic("to be freed page %p has cache", page);
if (!page->mappings.IsEmpty() || page->wired_count > 0) if (!page->mappings.IsEmpty() || page->wired_count > 0)
panic("to be freed page %p has mappings", page); panic("to be freed page %p has mappings", page);
@@ -715,7 +715,8 @@ set_page_state(vm_page *page, int pageState)
sFreePageCondition.NotifyOne(); sFreePageCondition.NotifyOne();
} }
if (page->cache != NULL && page->cache->temporary) { VMCache* cache = page->Cache();
if (cache != NULL && cache->temporary) {
if (pageState == PAGE_STATE_MODIFIED) if (pageState == PAGE_STATE_MODIFIED)
atomic_add(&sModifiedTemporaryPages, 1); atomic_add(&sModifiedTemporaryPages, 1);
else if (page->state == PAGE_STATE_MODIFIED) else if (page->state == PAGE_STATE_MODIFIED)
@@ -730,8 +731,8 @@ set_page_state(vm_page *page, int pageState)
// page states and active pages have a cache that must be locked at // page states and active pages have a cache that must be locked at
// this point. So we rely on the fact that everyone must lock the cache // this point. So we rely on the fact that everyone must lock the cache
// before trying to change/interpret the page state. // before trying to change/interpret the page state.
ASSERT(page->cache != NULL); ASSERT(cache != NULL);
page->cache->AssertLocked(); cache->AssertLocked();
page->state = pageState; page->state = pageState;
} else { } else {
if (fromQueue != NULL) if (fromQueue != NULL)
@@ -767,7 +768,7 @@ move_page_to_active_or_inactive_queue(vm_page *page, bool dequeued)
VMPageQueue& queue = state == PAGE_STATE_ACTIVE VMPageQueue& queue = state == PAGE_STATE_ACTIVE
? sActivePageQueue : sInactivePageQueue; ? sActivePageQueue : sInactivePageQueue;
queue.AppendUnlocked(page); queue.AppendUnlocked(page);
if (page->cache->temporary) if (page->Cache()->temporary)
atomic_add(&sModifiedTemporaryPages, -1); atomic_add(&sModifiedTemporaryPages, -1);
} else } else
set_page_state(page, state); set_page_state(page, state);
@@ -1026,7 +1027,7 @@ PageWriteWrapper::SetTo(vm_page* page, bool dequeuedPage)
panic("re-setting page write wrapper that isn't completed"); panic("re-setting page write wrapper that isn't completed");
fPage = page; fPage = page;
fCache = page->cache; fCache = page->Cache();
fDequeuedPage = dequeuedPage; fDequeuedPage = dequeuedPage;
fIsActive = true; fIsActive = true;
@@ -1125,7 +1126,7 @@ void
PageWriteTransfer::SetTo(PageWriterRun* run, vm_page* page, int32 maxPages) PageWriteTransfer::SetTo(PageWriterRun* run, vm_page* page, int32 maxPages)
{ {
fRun = run; fRun = run;
fCache = page->cache; fCache = page->Cache();
fOffset = page->cache_offset; fOffset = page->cache_offset;
fPageCount = 1; fPageCount = 1;
fMaxPages = maxPages; fMaxPages = maxPages;
@@ -1142,7 +1143,7 @@ PageWriteTransfer::SetTo(PageWriterRun* run, vm_page* page, int32 maxPages)
bool bool
PageWriteTransfer::AddPage(vm_page* page) PageWriteTransfer::AddPage(vm_page* page)
{ {
if (page->cache != fCache if (page->Cache() != fCache
|| (fMaxPages >= 0 && fPageCount >= (uint32)fMaxPages)) || (fMaxPages >= 0 && fPageCount >= (uint32)fMaxPages))
return false; return false;
@@ -1271,7 +1272,7 @@ PageWriterRun::AddPage(vm_page* page)
if (fTransferCount == 0 || !fTransfers[fTransferCount - 1].AddPage(page)) { if (fTransferCount == 0 || !fTransfers[fTransferCount - 1].AddPage(page)) {
fTransfers[fTransferCount++].SetTo(this, page, fTransfers[fTransferCount++].SetTo(this, page,
page->cache->MaxPagesPerAsyncWrite()); page->Cache()->MaxPagesPerAsyncWrite());
} }
} }
@@ -1360,7 +1361,7 @@ page_writer(void* /*unused*/)
vm_page marker; vm_page marker;
marker.is_dummy = true; marker.is_dummy = true;
marker.cache = NULL; marker.SetCacheRef(NULL);
marker.state = PAGE_STATE_UNUSED; marker.state = PAGE_STATE_UNUSED;
#if DEBUG_PAGE_QUEUE #if DEBUG_PAGE_QUEUE
marker.queue = NULL; marker.queue = NULL;
@@ -1425,7 +1426,7 @@ page_writer(void* /*unused*/)
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
VMCache *cache = page->cache; VMCache *cache = page->Cache();
// Don't write back wired (locked) pages and don't write RAM pages // Don't write back wired (locked) pages and don't write RAM pages
// until we're low on pages. Also avoid writing temporary pages that // until we're low on pages. Also avoid writing temporary pages that
@@ -1544,9 +1545,10 @@ steal_page(vm_page *page)
// try to lock the page's cache // try to lock the page's cache
if (vm_cache_acquire_locked_page_cache(page, false) == NULL) if (vm_cache_acquire_locked_page_cache(page, false) == NULL)
return false; return false;
VMCache* cache = page->Cache();
AutoLocker<VMCache> cacheLocker(page->cache, true); AutoLocker<VMCache> cacheLocker(cache, true);
MethodDeleter<VMCache> _2(page->cache, &VMCache::ReleaseRefLocked); MethodDeleter<VMCache> _2(cache, &VMCache::ReleaseRefLocked);
// check again if that page is still a candidate // check again if that page is still a candidate
if (page->state != PAGE_STATE_INACTIVE) if (page->state != PAGE_STATE_INACTIVE)
@@ -1574,7 +1576,7 @@ steal_page(vm_page *page)
//dprintf(" steal page %p from cache %p%s\n", page, page->cache, //dprintf(" steal page %p from cache %p%s\n", page, page->cache,
// page->state == PAGE_STATE_INACTIVE ? "" : " (ACTIVE)"); // page->state == PAGE_STATE_INACTIVE ? "" : " (ACTIVE)");
page->cache->RemovePage(page); cache->RemovePage(page);
sInactivePageQueue.RemoveUnlocked(page); sInactivePageQueue.RemoveUnlocked(page);
return true; return true;
@@ -1587,7 +1589,7 @@ steal_pages(vm_page **pages, size_t count)
while (true) { while (true) {
vm_page marker; vm_page marker;
marker.is_dummy = true; marker.is_dummy = true;
marker.cache = NULL; marker.SetCacheRef(NULL);
marker.state = PAGE_STATE_UNUSED; marker.state = PAGE_STATE_UNUSED;
#if DEBUG_PAGE_QUEUE #if DEBUG_PAGE_QUEUE
marker.queue = NULL; marker.queue = NULL;
@@ -1890,7 +1892,7 @@ vm_page_init(kernel_args *args)
sPages[i].wired_count = 0; sPages[i].wired_count = 0;
sPages[i].usage_count = 0; sPages[i].usage_count = 0;
sPages[i].busy_writing = false; sPages[i].busy_writing = false;
sPages[i].cache = NULL; sPages[i].SetCacheRef(NULL);
#if DEBUG_PAGE_QUEUE #if DEBUG_PAGE_QUEUE
sPages[i].queue = NULL; sPages[i].queue = NULL;
#endif #endif
@@ -2160,7 +2162,7 @@ vm_page_allocate_page(int pageState)
} }
} }
if (page->cache != NULL) if (page->CacheRef() != NULL)
panic("supposed to be free page %p has cache\n", page); panic("supposed to be free page %p has cache\n", page);
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
@@ -2383,8 +2385,7 @@ vm_page_set_state(vm_page *page, int pageState)
void void
vm_page_requeue(struct vm_page *page, bool tail) vm_page_requeue(struct vm_page *page, bool tail)
{ {
ASSERT(page->cache != NULL); ASSERT(page->Cache() != NULL);
page->cache->AssertLocked();
DEBUG_PAGE_ACCESS_CHECK(page); DEBUG_PAGE_ACCESS_CHECK(page);
VMPageQueue *queue = NULL; VMPageQueue *queue = NULL;