mmlr (distracted) + bonefish:

* Turn VMCache::consumers C list into a DoublyLinkedList.
* Use object caches for the different VMCache types and the VMCacheRefs.
  The purpose is to reduce slab area fragmentation.
* Requires the introduction of a pure virtual VMCache::DeleteObject()
  method, implemented in the derived classes.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@43133 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2011-11-02 21:14:11 +00:00
parent ef9d9a1720
commit f8154d172d
14 changed files with 158 additions and 62 deletions
+18 -4
View File
@@ -12,7 +12,7 @@
#include <debug.h> #include <debug.h>
#include <kernel.h> #include <kernel.h>
#include <util/list.h> #include <util/DoublyLinkedList.h>
#include <vm/vm.h> #include <vm/vm.h>
#include <vm/vm_types.h> #include <vm/vm_types.h>
@@ -20,6 +20,7 @@
struct kernel_args; struct kernel_args;
class ObjectCache;
enum { enum {
@@ -34,6 +35,14 @@ enum {
}; };
extern ObjectCache* gCacheRefObjectCache;
extern ObjectCache* gAnonymousCacheObjectCache;
extern ObjectCache* gAnonymousNoSwapCacheObjectCache;
extern ObjectCache* gVnodeCacheObjectCache;
extern ObjectCache* gDeviceCacheObjectCache;
extern ObjectCache* gNullCacheObjectCache;
struct VMCachePagesTreeDefinition { struct VMCachePagesTreeDefinition {
typedef page_num_t KeyType; typedef page_num_t KeyType;
typedef vm_page NodeType; typedef vm_page NodeType;
@@ -63,7 +72,10 @@ struct VMCachePagesTreeDefinition {
typedef IteratableSplayTree<VMCachePagesTreeDefinition> VMCachePagesTree; typedef IteratableSplayTree<VMCachePagesTreeDefinition> VMCachePagesTree;
struct VMCache { struct VMCache : public DoublyLinkedListLinkImpl<VMCache> {
public:
typedef DoublyLinkedList<VMCache> ConsumerList;
public: public:
VMCache(); VMCache();
virtual ~VMCache(); virtual ~VMCache();
@@ -163,10 +175,12 @@ public:
virtual void Dump(bool showPages) const; virtual void Dump(bool showPages) const;
protected:
virtual void DeleteObject() = 0;
public: public:
VMArea* areas; VMArea* areas;
list_link consumer_link; ConsumerList consumers;
list consumers;
// list of caches that use this cache as a source // list of caches that use this cache as a source
VMCachePagesTree pages; VMCachePagesTree pages;
VMCache* source; VMCache* source;
+1 -1
View File
@@ -290,7 +290,7 @@ reserve_pages(file_cache_ref* ref, vm_page_reservation* reservation,
VMCache* cache = ref->cache; VMCache* cache = ref->cache;
cache->Lock(); cache->Lock();
if (list_is_empty(&cache->consumers) && cache->areas == NULL if (cache->consumers.IsEmpty() && cache->areas == NULL
&& access_is_sequential(ref)) { && access_is_sequential(ref)) {
// we are not mapped, and we're accessed sequentially // we are not mapped, and we're accessed sequentially
+9 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -10,6 +10,7 @@
#include <string.h> #include <string.h>
#include <file_cache.h> #include <file_cache.h>
#include <slab/Slab.h>
#include <vfs.h> #include <vfs.h>
#include <vm/vm.h> #include <vm/vm.h>
@@ -164,3 +165,10 @@ VMVnodeCache::Dump(bool showPages) const
kprintf(" vnode: %p <%" B_PRIdDEV ", %" B_PRIdINO ">\n", fVnode, kprintf(" vnode: %p <%" B_PRIdDEV ", %" B_PRIdINO ">\n", fVnode,
fDevice, fInode); fDevice, fInode);
} }
void
VMVnodeCache::DeleteObject()
{
object_cache_delete(gVnodeCacheObjectCache, this);
}
+4 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -48,6 +48,9 @@ public:
void VnodeDeleted() { fVnodeDeleted = true; } void VnodeDeleted() { fVnodeDeleted = true; }
protected:
virtual void DeleteObject();
private: private:
struct vnode* fVnode; struct vnode* fVnode;
file_cache_ref* fFileCacheRef; file_cache_ref* fFileCacheRef;
+8 -1
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright 2008, Zhao Shuai, upczhsh@163.com. * Copyright 2008, Zhao Shuai, upczhsh@163.com.
* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
@@ -846,6 +846,13 @@ VMAnonymousCache::Merge(VMCache* _source)
} }
void
VMAnonymousCache::DeleteObject()
{
object_cache_delete(gAnonymousCacheObjectCache, this);
}
void void
VMAnonymousCache::_SwapBlockBuild(off_t startPageIndex, VMAnonymousCache::_SwapBlockBuild(off_t startPageIndex,
swap_addr_t startSlotIndex, uint32 count) swap_addr_t startSlotIndex, uint32 count)
+4 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
@@ -64,6 +64,9 @@ public:
virtual void Merge(VMCache* source); virtual void Merge(VMCache* source);
protected:
virtual void DeleteObject();
private: private:
class WriteCallback; class WriteCallback;
friend class WriteCallback; friend class WriteCallback;
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
@@ -14,6 +14,7 @@
#include <arch_config.h> #include <arch_config.h>
#include <heap.h> #include <heap.h>
#include <KernelExport.h> #include <KernelExport.h>
#include <slab/Slab.h>
#include <vm/vm_priv.h> #include <vm/vm_priv.h>
#include <vm/VMAddressSpace.h> #include <vm/VMAddressSpace.h>
@@ -183,3 +184,10 @@ VMAnonymousNoSwapCache::MergeStore(VMCache* _source)
committed_size = actualSize; committed_size = actualSize;
} }
} }
void
VMAnonymousNoSwapCache::DeleteObject()
{
object_cache_delete(gAnonymousNoSwapCacheObjectCache, this);
}
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
@@ -37,6 +37,9 @@ public:
virtual void MergeStore(VMCache* source); virtual void MergeStore(VMCache* source);
protected:
virtual void DeleteObject();
private: private:
bool fCanOvercommit; bool fCanOvercommit;
bool fHasPrecommitted; bool fHasPrecommitted;
+63 -35
View File
@@ -20,6 +20,7 @@
#include <heap.h> #include <heap.h>
#include <int.h> #include <int.h>
#include <kernel.h> #include <kernel.h>
#include <slab/Slab.h>
#include <smp.h> #include <smp.h>
#include <tracing.h> #include <tracing.h>
#include <util/khash.h> #include <util/khash.h>
@@ -32,6 +33,13 @@
#include <vm/VMAddressSpace.h> #include <vm/VMAddressSpace.h>
#include <vm/VMArea.h> #include <vm/VMArea.h>
// needed for the factory only
#include "VMAnonymousCache.h"
#include "VMAnonymousNoSwapCache.h"
#include "VMDeviceCache.h"
#include "VMNullCache.h"
#include "../cache/vnode_store.h"
//#define TRACE_VM_CACHE //#define TRACE_VM_CACHE
#ifdef TRACE_VM_CACHE #ifdef TRACE_VM_CACHE
@@ -47,6 +55,13 @@ VMCache* gDebugCacheList;
static mutex sCacheListLock = MUTEX_INITIALIZER("global VMCache list"); static mutex sCacheListLock = MUTEX_INITIALIZER("global VMCache list");
// The lock is also needed when the debug feature is disabled. // The lock is also needed when the debug feature is disabled.
ObjectCache* gCacheRefObjectCache;
ObjectCache* gAnonymousCacheObjectCache;
ObjectCache* gAnonymousNoSwapCacheObjectCache;
ObjectCache* gVnodeCacheObjectCache;
ObjectCache* gDeviceCacheObjectCache;
ObjectCache* gNullCacheObjectCache;
struct VMCache::PageEventWaiter { struct VMCache::PageEventWaiter {
Thread* thread; Thread* thread;
@@ -465,6 +480,30 @@ command_cache_stack(int argc, char** argv)
status_t status_t
vm_cache_init(kernel_args* args) vm_cache_init(kernel_args* args)
{ {
// Create object caches for the structures we allocate here.
gCacheRefObjectCache = create_object_cache("cache refs", sizeof(VMCacheRef),
0, NULL, NULL, NULL);
gAnonymousCacheObjectCache = create_object_cache("anon caches",
sizeof(VMAnonymousCache), 0, NULL, NULL, NULL);
gAnonymousNoSwapCacheObjectCache = create_object_cache(
"anon no-swap caches", sizeof(VMAnonymousNoSwapCache), 0, NULL, NULL,
NULL);
gVnodeCacheObjectCache = create_object_cache("vnode caches",
sizeof(VMVnodeCache), 0, NULL, NULL, NULL);
gDeviceCacheObjectCache = create_object_cache("device caches",
sizeof(VMDeviceCache), 0, NULL, NULL, NULL);
gNullCacheObjectCache = create_object_cache("null caches",
sizeof(VMNullCache), 0, NULL, NULL, NULL);
if (gCacheRefObjectCache == NULL || gAnonymousCacheObjectCache == NULL
|| gAnonymousNoSwapCacheObjectCache == NULL
|| gVnodeCacheObjectCache == NULL
|| gDeviceCacheObjectCache == NULL
|| gNullCacheObjectCache == NULL) {
panic("vm_cache_init(): Failed to create object caches!");
return B_NO_MEMORY;
}
return B_OK; return B_OK;
} }
@@ -558,9 +597,8 @@ VMCacheRef::VMCacheRef(VMCache* cache)
bool bool
VMCache::_IsMergeable() const VMCache::_IsMergeable() const
{ {
return (areas == NULL && temporary return areas == NULL && temporary && !consumers.IsEmpty()
&& !list_is_empty(const_cast<list*>(&consumers)) && consumers.Head() == consumers.Tail();
&& consumers.link.next == consumers.link.prev);
} }
@@ -573,7 +611,7 @@ VMCache::VMCache()
VMCache::~VMCache() VMCache::~VMCache()
{ {
delete fCacheRef; object_cache_delete(gCacheRefObjectCache, fCacheRef);
} }
@@ -582,10 +620,6 @@ VMCache::Init(uint32 cacheType, uint32 allocationFlags)
{ {
mutex_init(&fLock, "VMCache"); mutex_init(&fLock, "VMCache");
VMCache dummyCache;
list_init_etc(&consumers, offset_of_member(dummyCache, consumer_link));
// TODO: This is disgusting! Use DoublyLinkedList!
areas = NULL; areas = NULL;
fRefCount = 1; fRefCount = 1;
source = NULL; source = NULL;
@@ -604,7 +638,7 @@ VMCache::Init(uint32 cacheType, uint32 allocationFlags)
// initialize in case the following fails // initialize in case the following fails
#endif #endif
fCacheRef = new(malloc_flags(allocationFlags)) VMCacheRef(this); fCacheRef = new(gCacheRefObjectCache, allocationFlags) VMCacheRef(this);
if (fCacheRef == NULL) if (fCacheRef == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -628,7 +662,7 @@ VMCache::Delete()
{ {
if (areas != NULL) if (areas != NULL)
panic("cache %p to be deleted still has areas", this); panic("cache %p to be deleted still has areas", this);
if (!list_is_empty(&consumers)) if (!consumers.IsEmpty())
panic("cache %p to be deleted still has consumers", this); panic("cache %p to be deleted still has consumers", this);
T(Delete(this)); T(Delete(this));
@@ -672,7 +706,7 @@ VMCache::Delete()
mutex_unlock(&sCacheListLock); mutex_unlock(&sCacheListLock);
delete this; DeleteObject();
} }
@@ -680,7 +714,7 @@ void
VMCache::Unlock(bool consumerLocked) VMCache::Unlock(bool consumerLocked)
{ {
while (fRefCount == 1 && _IsMergeable()) { while (fRefCount == 1 && _IsMergeable()) {
VMCache* consumer = (VMCache*)list_get_first_item(&consumers); VMCache* consumer = consumers.Head();
if (consumerLocked) { if (consumerLocked) {
_MergeWithOnlyConsumer(); _MergeWithOnlyConsumer();
} else if (consumer->TryLock()) { } else if (consumer->TryLock()) {
@@ -698,7 +732,7 @@ VMCache::Unlock(bool consumerLocked)
if (consumerLockedTemp) { if (consumerLockedTemp) {
if (fRefCount == 1 && _IsMergeable() if (fRefCount == 1 && _IsMergeable()
&& consumer == list_get_first_item(&consumers)) { && consumer == consumers.Head()) {
// nothing has changed in the meantime -- merge // nothing has changed in the meantime -- merge
_MergeWithOnlyConsumer(); _MergeWithOnlyConsumer();
} }
@@ -901,7 +935,7 @@ VMCache::AddConsumer(VMCache* consumer)
T(AddConsumer(this, consumer)); T(AddConsumer(this, consumer));
consumer->source = this; consumer->source = this;
list_add_item(&consumers, consumer); consumers.Add(consumer);
AcquireRefLocked(); AcquireRefLocked();
AcquireStoreRef(); AcquireStoreRef();
@@ -1312,9 +1346,8 @@ VMCache::Dump(bool showPages) const
} }
kprintf(" consumers:\n"); kprintf(" consumers:\n");
VMCache* consumer = NULL; for (ConsumerList::ConstIterator it = consumers.GetIterator();
while ((consumer = (VMCache*)list_get_next_item((list*)&consumers, VMCache* consumer = it.Next();) {
consumer)) != NULL) {
kprintf("\t%p\n", consumer); kprintf("\t%p\n", consumer);
} }
@@ -1365,7 +1398,7 @@ VMCache::_NotifyPageEvents(vm_page* page, uint32 events)
void void
VMCache::_MergeWithOnlyConsumer() VMCache::_MergeWithOnlyConsumer()
{ {
VMCache* consumer = (VMCache*)list_remove_head_item(&consumers); VMCache* consumer = consumers.RemoveHead();
TRACE(("merge vm cache %p (ref == %ld) with vm cache %p\n", TRACE(("merge vm cache %p (ref == %ld) with vm cache %p\n",
this, this->fRefCount, consumer)); this, this->fRefCount, consumer));
@@ -1381,8 +1414,8 @@ VMCache::_MergeWithOnlyConsumer()
newSource->Lock(); newSource->Lock();
list_remove_item(&newSource->consumers, this); newSource->consumers.Remove(this);
list_add_item(&newSource->consumers, consumer); newSource->consumers.Add(consumer);
consumer->source = newSource; consumer->source = newSource;
source = NULL; source = NULL;
@@ -1416,7 +1449,7 @@ VMCache::_RemoveConsumer(VMCache* consumer)
// remove the consumer from the cache, but keep its reference until later // remove the consumer from the cache, but keep its reference until later
Lock(); Lock();
list_remove_item(&consumers, consumer); consumers.Remove(consumer);
consumer->source = NULL; consumer->source = NULL;
ReleaseRefAndUnlock(); ReleaseRefAndUnlock();
@@ -1427,15 +1460,6 @@ VMCache::_RemoveConsumer(VMCache* consumer)
// TODO: Move to own source file! // TODO: Move to own source file!
#include <heap.h>
#include "VMAnonymousCache.h"
#include "VMAnonymousNoSwapCache.h"
#include "VMDeviceCache.h"
#include "VMNullCache.h"
#include "../cache/vnode_store.h"
/*static*/ status_t /*static*/ status_t
VMCacheFactory::CreateAnonymousCache(VMCache*& _cache, bool canOvercommit, VMCacheFactory::CreateAnonymousCache(VMCache*& _cache, bool canOvercommit,
int32 numPrecommittedPages, int32 numGuardPages, bool swappable, int32 numPrecommittedPages, int32 numGuardPages, bool swappable,
@@ -1449,7 +1473,7 @@ VMCacheFactory::CreateAnonymousCache(VMCache*& _cache, bool canOvercommit,
#if ENABLE_SWAP_SUPPORT #if ENABLE_SWAP_SUPPORT
if (swappable) { if (swappable) {
VMAnonymousCache* cache VMAnonymousCache* cache
= new(malloc_flags(allocationFlags)) VMAnonymousCache; = new(gAnonymousCacheObjectCache, allocationFlags) VMAnonymousCache;
if (cache == NULL) if (cache == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -1468,7 +1492,8 @@ VMCacheFactory::CreateAnonymousCache(VMCache*& _cache, bool canOvercommit,
#endif #endif
VMAnonymousNoSwapCache* cache VMAnonymousNoSwapCache* cache
= new(malloc_flags(allocationFlags)) VMAnonymousNoSwapCache; = new(gAnonymousNoSwapCacheObjectCache, allocationFlags)
VMAnonymousNoSwapCache;
if (cache == NULL) if (cache == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -1493,7 +1518,8 @@ VMCacheFactory::CreateVnodeCache(VMCache*& _cache, struct vnode* vnode)
| HEAP_DONT_LOCK_KERNEL_SPACE; | HEAP_DONT_LOCK_KERNEL_SPACE;
// Note: Vnode cache creation is never VIP. // Note: Vnode cache creation is never VIP.
VMVnodeCache* cache = new(malloc_flags(allocationFlags)) VMVnodeCache; VMVnodeCache* cache
= new(gVnodeCacheObjectCache, allocationFlags) VMVnodeCache;
if (cache == NULL) if (cache == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -1517,7 +1543,8 @@ VMCacheFactory::CreateDeviceCache(VMCache*& _cache, addr_t baseAddress)
| HEAP_DONT_LOCK_KERNEL_SPACE; | HEAP_DONT_LOCK_KERNEL_SPACE;
// Note: Device cache creation is never VIP. // Note: Device cache creation is never VIP.
VMDeviceCache* cache = new(malloc_flags(allocationFlags)) VMDeviceCache; VMDeviceCache* cache
= new(gDeviceCacheObjectCache, allocationFlags) VMDeviceCache;
if (cache == NULL) if (cache == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -1542,7 +1569,8 @@ VMCacheFactory::CreateNullCache(int priority, VMCache*& _cache)
if (priority >= VM_PRIORITY_VIP) if (priority >= VM_PRIORITY_VIP)
allocationFlags |= HEAP_PRIORITY_VIP; allocationFlags |= HEAP_PRIORITY_VIP;
VMNullCache* cache = new(malloc_flags(allocationFlags)) VMNullCache; VMNullCache* cache
= new(gNullCacheObjectCache, allocationFlags) VMNullCache;
if (cache == NULL) if (cache == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
+9
View File
@@ -9,6 +9,8 @@
#include "VMDeviceCache.h" #include "VMDeviceCache.h"
#include <slab/Slab.h>
status_t status_t
VMDeviceCache::Init(addr_t baseAddress, uint32 allocationFlags) VMDeviceCache::Init(addr_t baseAddress, uint32 allocationFlags)
@@ -34,3 +36,10 @@ VMDeviceCache::Write(off_t offset, const iovec* vecs, size_t count,
// no place to write, this will cause the page daemon to skip this store // no place to write, this will cause the page daemon to skip this store
return B_OK; return B_OK;
} }
void
VMDeviceCache::DeleteObject()
{
object_cache_delete(gDeviceCacheObjectCache, this);
}
+4 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de. * Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
@@ -25,6 +25,9 @@ public:
size_t count, uint32 flags, size_t count, uint32 flags,
size_t* _numBytes); size_t* _numBytes);
protected:
virtual void DeleteObject();
private: private:
addr_t fBaseAddress; addr_t fBaseAddress;
}; };
+11 -1
View File
@@ -1,14 +1,24 @@
/* /*
* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "VMNullCache.h" #include "VMNullCache.h"
#include <slab/Slab.h>
status_t status_t
VMNullCache::Init(uint32 allocationFlags) VMNullCache::Init(uint32 allocationFlags)
{ {
return VMCache::Init(CACHE_TYPE_NULL, allocationFlags); return VMCache::Init(CACHE_TYPE_NULL, allocationFlags);
} }
void
VMNullCache::DeleteObject()
{
object_cache_delete(gNullCacheObjectCache, this);
}
+4 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de. * Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
@@ -16,6 +16,9 @@
class VMNullCache : public VMCache { class VMNullCache : public VMCache {
public: public:
status_t Init(uint32 allocationFlags); status_t Init(uint32 allocationFlags);
protected:
virtual void DeleteObject();
}; };
+10 -13
View File
@@ -618,7 +618,7 @@ cut_area(VMAddressSpace* addressSpace, VMArea* area, addr_t address,
// If no one else uses the area's cache, we can resize it, too. // If no one else uses the area's cache, we can resize it, too.
if (cache->areas == area && area->cache_next == NULL if (cache->areas == area && area->cache_next == NULL
&& list_is_empty(&cache->consumers) && cache->consumers.IsEmpty()
&& cache->type == CACHE_TYPE_RAM) { && cache->type == CACHE_TYPE_RAM) {
// Since VMCache::Resize() can temporarily drop the lock, we must // Since VMCache::Resize() can temporarily drop the lock, we must
// unlock all lower caches to prevent locking order inversion. // unlock all lower caches to prevent locking order inversion.
@@ -2442,7 +2442,7 @@ vm_set_area_protection(team_id team, area_id areaID, uint32 newProtection,
// Make sure the area (respectively, if we're going to call // Make sure the area (respectively, if we're going to call
// vm_copy_on_write_area(), all areas of the cache) doesn't have any // vm_copy_on_write_area(), all areas of the cache) doesn't have any
// wired ranges. // wired ranges.
if (!isWritable && becomesWritable && !list_is_empty(&cache->consumers)) { if (!isWritable && becomesWritable && !cache->consumers.IsEmpty()) {
for (VMArea* otherArea = cache->areas; otherArea != NULL; for (VMArea* otherArea = cache->areas; otherArea != NULL;
otherArea = otherArea->cache_next) { otherArea = otherArea->cache_next) {
if (wait_if_area_is_wired(otherArea, &locker, &cacheLocker)) { if (wait_if_area_is_wired(otherArea, &locker, &cacheLocker)) {
@@ -2490,7 +2490,7 @@ vm_set_area_protection(team_id team, area_id areaID, uint32 newProtection,
} else if (!isWritable && becomesWritable) { } else if (!isWritable && becomesWritable) {
// !writable -> writable // !writable -> writable
if (!list_is_empty(&cache->consumers)) { if (!cache->consumers.IsEmpty()) {
// There are consumers -- we have to insert a new cache. Fortunately // There are consumers -- we have to insert a new cache. Fortunately
// vm_copy_on_write_area() does everything that's needed. // vm_copy_on_write_area() does everything that's needed.
changePageProtection = false; changePageProtection = false;
@@ -2885,9 +2885,8 @@ dump_cache_tree_recursively(VMCache* cache, int level,
kprintf("%p\n", cache); kprintf("%p\n", cache);
// recursively print its consumers // recursively print its consumers
VMCache* consumer = NULL; for (VMCache::ConsumerList::Iterator it = cache->consumers.GetIterator();
while ((consumer = (VMCache*)list_get_next_item(&cache->consumers, VMCache* consumer = it.Next();) {
consumer)) != NULL) {
dump_cache_tree_recursively(consumer, level + 1, highlightCache); dump_cache_tree_recursively(consumer, level + 1, highlightCache);
} }
} }
@@ -2947,9 +2946,8 @@ update_cache_info_recursively(VMCache* cache, cache_info& info)
info.committed += cache->committed_size; info.committed += cache->committed_size;
// recurse // recurse
VMCache* consumer = NULL; for (VMCache::ConsumerList::Iterator it = cache->consumers.GetIterator();
while ((consumer = (VMCache*)list_get_next_item(&cache->consumers, VMCache* consumer = it.Next();) {
consumer)) != NULL) {
update_cache_info_recursively(consumer, info); update_cache_info_recursively(consumer, info);
} }
} }
@@ -3012,9 +3010,8 @@ dump_caches_recursively(VMCache* cache, cache_info& info, int level)
kputs("\n"); kputs("\n");
// recurse // recurse
VMCache* consumer = NULL; for (VMCache::ConsumerList::Iterator it = cache->consumers.GetIterator();
while ((consumer = (VMCache*)list_get_next_item(&cache->consumers, VMCache* consumer = it.Next();) {
consumer)) != NULL) {
dump_caches_recursively(consumer, info, level + 1); dump_caches_recursively(consumer, info, level + 1);
} }
} }
@@ -3687,7 +3684,7 @@ vm_init(kernel_args* args)
// initialize the free page list and physical page mapper // initialize the free page list and physical page mapper
vm_page_init(args); vm_page_init(args);
// initialize the hash table that stores the pages mapped to caches // initialize the cache allocators
vm_cache_init(args); vm_cache_init(args);
{ {