Allocate VMKernelAddressRange and VMKernelArea in their own object

caches to reduce slab area fragmentation.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@43136 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2011-11-02 22:04:37 +00:00
parent 6877edf850
commit 951c43ff21
4 changed files with 50 additions and 28 deletions
+34 -20
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2009-2010, Ingo Weinhold, [email protected]. * Copyright 2009-2011, Ingo Weinhold, [email protected].
* Copyright 2002-2009, Axel Dörfler, [email protected]. * Copyright 2002-2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
@@ -15,6 +15,7 @@
#include <KernelExport.h> #include <KernelExport.h>
#include <heap.h> #include <heap.h>
#include <slab/Slab.h>
#include <thread.h> #include <thread.h>
#include <vm/vm.h> #include <vm/vm.h>
#include <vm/VMArea.h> #include <vm/VMArea.h>
@@ -69,7 +70,9 @@ is_valid_spot(addr_t base, addr_t alignedBase, addr_t size, addr_t limit)
VMKernelAddressSpace::VMKernelAddressSpace(team_id id, addr_t base, size_t size) VMKernelAddressSpace::VMKernelAddressSpace(team_id id, addr_t base, size_t size)
: :
VMAddressSpace(id, base, size, "kernel address space") VMAddressSpace(id, base, size, "kernel address space"),
fAreaObjectCache(NULL),
fRangesObjectCache(NULL)
{ {
} }
@@ -83,6 +86,16 @@ VMKernelAddressSpace::~VMKernelAddressSpace()
status_t status_t
VMKernelAddressSpace::InitObject() VMKernelAddressSpace::InitObject()
{ {
fAreaObjectCache = create_object_cache("kernel areas",
sizeof(VMKernelArea), 0, NULL, NULL, NULL);
if (fAreaObjectCache == NULL)
return B_NO_MEMORY;
fRangesObjectCache = create_object_cache("kernel address ranges",
sizeof(Range), 0, NULL, NULL, NULL);
if (fRangesObjectCache == NULL)
return B_NO_MEMORY;
// create the free lists // create the free lists
size_t size = fEndAddress - fBase + 1; size_t size = fEndAddress - fBase + 1;
fFreeListCount = ld(size) - PAGE_SHIFT + 1; fFreeListCount = ld(size) - PAGE_SHIFT + 1;
@@ -90,7 +103,8 @@ VMKernelAddressSpace::InitObject()
if (fFreeLists == NULL) if (fFreeLists == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
Range* range = new(std::nothrow) Range(fBase, size, Range::RANGE_FREE); Range* range = new(fRangesObjectCache, 0) Range(fBase, size,
Range::RANGE_FREE);
if (range == NULL) if (range == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -130,7 +144,7 @@ VMKernelAddressSpace::CreateArea(const char* name, uint32 wiring,
uint32 protection, uint32 allocationFlags) uint32 protection, uint32 allocationFlags)
{ {
return VMKernelArea::Create(this, name, wiring, protection, return VMKernelArea::Create(this, name, wiring, protection,
allocationFlags); fAreaObjectCache, allocationFlags);
} }
@@ -140,8 +154,7 @@ VMKernelAddressSpace::DeleteArea(VMArea* _area, uint32 allocationFlags)
TRACE("VMKernelAddressSpace::DeleteArea(%p)\n", area); TRACE("VMKernelAddressSpace::DeleteArea(%p)\n", area);
VMKernelArea* area = static_cast<VMKernelArea*>(_area); VMKernelArea* area = static_cast<VMKernelArea*>(_area);
area->~VMKernelArea(); object_cache_delete(fAreaObjectCache, area);
free_etc(area, allocationFlags);
} }
@@ -261,7 +274,7 @@ VMKernelAddressSpace::ResizeArea(VMArea* _area, size_t newSize,
} else { } else {
// no free range following -- we need to allocate a new one and // no free range following -- we need to allocate a new one and
// insert it // insert it
nextRange = new(malloc_flags(allocationFlags)) Range( nextRange = new(fRangesObjectCache, allocationFlags) Range(
range->base + newSize, range->size - newSize, range->base + newSize, range->size - newSize,
Range::RANGE_FREE); Range::RANGE_FREE);
if (nextRange == NULL) if (nextRange == NULL)
@@ -283,7 +296,7 @@ VMKernelAddressSpace::ResizeArea(VMArea* _area, size_t newSize,
if (sizeDiff == nextRange->size) { if (sizeDiff == nextRange->size) {
// The next range is completely covered -- remove and delete it. // The next range is completely covered -- remove and delete it.
_RemoveRange(nextRange); _RemoveRange(nextRange);
free_etc(nextRange, allocationFlags); object_cache_delete(fRangesObjectCache, nextRange, allocationFlags);
} else { } else {
// The next range is only partially covered -- shrink it. // The next range is only partially covered -- shrink it.
if (nextRange->type == Range::RANGE_FREE) if (nextRange->type == Range::RANGE_FREE)
@@ -333,8 +346,8 @@ VMKernelAddressSpace::ShrinkAreaHead(VMArea* _area, size_t newSize,
} else { } else {
// no free range before -- we need to allocate a new one and // no free range before -- we need to allocate a new one and
// insert it // insert it
previousRange = new(malloc_flags(allocationFlags)) Range(range->base, previousRange = new(fRangesObjectCache, allocationFlags) Range(
sizeDiff, Range::RANGE_FREE); range->base, sizeDiff, Range::RANGE_FREE);
if (previousRange == NULL) if (previousRange == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
range->base += sizeDiff; range->base += sizeDiff;
@@ -605,8 +618,8 @@ VMKernelAddressSpace::_AllocateRange(
// allocation at the beginning of the range // allocation at the beginning of the range
if (range->size > size) { if (range->size > size) {
// only partial -- split the range // only partial -- split the range
Range* leftOverRange = new(malloc_flags(allocationFlags)) Range( Range* leftOverRange = new(fRangesObjectCache, allocationFlags)
address + size, range->size - size, range); Range(address + size, range->size - size, range);
if (leftOverRange == NULL) if (leftOverRange == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -615,7 +628,7 @@ VMKernelAddressSpace::_AllocateRange(
} }
} else if (address + size == range->base + range->size) { } else if (address + size == range->base + range->size) {
// allocation at the end of the range -- split the range // allocation at the end of the range -- split the range
Range* leftOverRange = new(malloc_flags(allocationFlags)) Range( Range* leftOverRange = new(fRangesObjectCache, allocationFlags) Range(
range->base, range->size - size, range); range->base, range->size - size, range);
if (leftOverRange == NULL) if (leftOverRange == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -625,14 +638,15 @@ VMKernelAddressSpace::_AllocateRange(
_InsertRange(leftOverRange); _InsertRange(leftOverRange);
} else { } else {
// allocation in the middle of the range -- split the range in three // allocation in the middle of the range -- split the range in three
Range* leftOverRange1 = new(malloc_flags(allocationFlags)) Range( Range* leftOverRange1 = new(fRangesObjectCache, allocationFlags) Range(
range->base, address - range->base, range); range->base, address - range->base, range);
if (leftOverRange1 == NULL) if (leftOverRange1 == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
Range* leftOverRange2 = new(malloc_flags(allocationFlags)) Range( Range* leftOverRange2 = new(fRangesObjectCache, allocationFlags) Range(
address + size, range->size - size - leftOverRange1->size, range); address + size, range->size - size - leftOverRange1->size, range);
if (leftOverRange2 == NULL) { if (leftOverRange2 == NULL) {
free_etc(leftOverRange1, allocationFlags); object_cache_delete(fRangesObjectCache, leftOverRange1,
allocationFlags);
return B_NO_MEMORY; return B_NO_MEMORY;
} }
@@ -792,15 +806,15 @@ VMKernelAddressSpace::_FreeRange(Range* range, uint32 allocationFlags)
_RemoveRange(range); _RemoveRange(range);
_RemoveRange(nextRange); _RemoveRange(nextRange);
previousRange->size += range->size + nextRange->size; previousRange->size += range->size + nextRange->size;
free_etc(range, allocationFlags); object_cache_delete(fRangesObjectCache, range, allocationFlags);
free_etc(nextRange, allocationFlags); object_cache_delete(fRangesObjectCache, nextRange, allocationFlags);
_FreeListInsertRange(previousRange, previousRange->size); _FreeListInsertRange(previousRange, previousRange->size);
} else { } else {
// join with the previous range only, delete the supplied one // join with the previous range only, delete the supplied one
_FreeListRemoveRange(previousRange, previousRange->size); _FreeListRemoveRange(previousRange, previousRange->size);
_RemoveRange(range); _RemoveRange(range);
previousRange->size += range->size; previousRange->size += range->size;
free_etc(range, allocationFlags); object_cache_delete(fRangesObjectCache, range, allocationFlags);
_FreeListInsertRange(previousRange, previousRange->size); _FreeListInsertRange(previousRange, previousRange->size);
} }
} else { } else {
@@ -808,7 +822,7 @@ VMKernelAddressSpace::_FreeRange(Range* range, uint32 allocationFlags)
// join with the next range and delete it // join with the next range and delete it
_RemoveRange(nextRange); _RemoveRange(nextRange);
range->size += nextRange->size; range->size += nextRange->size;
free_etc(nextRange, allocationFlags); object_cache_delete(fRangesObjectCache, nextRange, allocationFlags);
} }
// mark the range free and add it to the respective free list // mark the range free and add it to the respective free list
+6 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2009-2010, Ingo Weinhold, [email protected]. * Copyright 2009-2011, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef VM_KERNEL_ADDRESS_SPACE_H #ifndef VM_KERNEL_ADDRESS_SPACE_H
@@ -11,6 +11,9 @@
#include "VMKernelArea.h" #include "VMKernelArea.h"
struct ObjectCache;
struct VMKernelAddressSpace : VMAddressSpace { struct VMKernelAddressSpace : VMAddressSpace {
public: public:
VMKernelAddressSpace(team_id id, addr_t base, VMKernelAddressSpace(team_id id, addr_t base,
@@ -89,6 +92,8 @@ private:
RangeList fRangeList; RangeList fRangeList;
RangeFreeList* fFreeLists; RangeFreeList* fFreeLists;
int fFreeListCount; int fFreeListCount;
ObjectCache* fAreaObjectCache;
ObjectCache* fRangesObjectCache;
}; };
+6 -5
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2009-2010, Ingo Weinhold, [email protected]. * Copyright 2009-2011, Ingo Weinhold, [email protected].
* Distributed under the terms of the NewOS License. * Distributed under the terms of the NewOS License.
*/ */
@@ -7,6 +7,7 @@
#include "VMKernelArea.h" #include "VMKernelArea.h"
#include <heap.h> #include <heap.h>
#include <slab/Slab.h>
#include <vm/vm_priv.h> #include <vm/vm_priv.h>
@@ -25,16 +26,16 @@ VMKernelArea::~VMKernelArea()
/*static*/ VMKernelArea* /*static*/ VMKernelArea*
VMKernelArea::Create(VMAddressSpace* addressSpace, const char* name, VMKernelArea::Create(VMAddressSpace* addressSpace, const char* name,
uint32 wiring, uint32 protection, uint32 allocationFlags) uint32 wiring, uint32 protection, ObjectCache* objectCache,
uint32 allocationFlags)
{ {
VMKernelArea* area = new(malloc_flags(allocationFlags)) VMKernelArea( VMKernelArea* area = new(objectCache, allocationFlags) VMKernelArea(
addressSpace, wiring, protection); addressSpace, wiring, protection);
if (area == NULL) if (area == NULL)
return NULL; return NULL;
if (area->Init(name, allocationFlags) != B_OK) { if (area->Init(name, allocationFlags) != B_OK) {
area->~VMKernelArea(); object_cache_delete(objectCache, area);
free_etc(area, allocationFlags);
return NULL; return NULL;
} }
+4 -2
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2009-2010, Ingo Weinhold, [email protected]. * Copyright 2009-2011, Ingo Weinhold, [email protected].
* Distributed under the terms of the NewOS License. * Distributed under the terms of the NewOS License.
*/ */
#ifndef VM_KERNEL_AREA_H #ifndef VM_KERNEL_AREA_H
@@ -11,6 +11,7 @@
#include <vm/VMArea.h> #include <vm/VMArea.h>
struct ObjectCache;
struct VMKernelAddressSpace; struct VMKernelAddressSpace;
struct VMKernelArea; struct VMKernelArea;
@@ -115,7 +116,8 @@ struct VMKernelArea : VMArea, AVLTreeNode {
static VMKernelArea* Create(VMAddressSpace* addressSpace, static VMKernelArea* Create(VMAddressSpace* addressSpace,
const char* name, uint32 wiring, const char* name, uint32 wiring,
uint32 protection, uint32 allocationFlags); uint32 protection, ObjectCache* objectCache,
uint32 allocationFlags);
VMKernelAddressRange* Range() const VMKernelAddressRange* Range() const
{ return fRange; } { return fRange; }