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

View File

@ -1,5 +1,5 @@
/*
* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*
@ -15,6 +15,7 @@
#include <KernelExport.h>
#include <heap.h>
#include <slab/Slab.h>
#include <thread.h>
#include <vm/vm.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)
:
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
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
size_t size = fEndAddress - fBase + 1;
fFreeListCount = ld(size) - PAGE_SHIFT + 1;
@ -90,7 +103,8 @@ VMKernelAddressSpace::InitObject()
if (fFreeLists == NULL)
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)
return B_NO_MEMORY;
@ -130,7 +144,7 @@ VMKernelAddressSpace::CreateArea(const char* name, uint32 wiring,
uint32 protection, uint32 allocationFlags)
{
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);
VMKernelArea* area = static_cast<VMKernelArea*>(_area);
area->~VMKernelArea();
free_etc(area, allocationFlags);
object_cache_delete(fAreaObjectCache, area);
}
@ -261,7 +274,7 @@ VMKernelAddressSpace::ResizeArea(VMArea* _area, size_t newSize,
} else {
// no free range following -- we need to allocate a new one and
// insert it
nextRange = new(malloc_flags(allocationFlags)) Range(
nextRange = new(fRangesObjectCache, allocationFlags) Range(
range->base + newSize, range->size - newSize,
Range::RANGE_FREE);
if (nextRange == NULL)
@ -283,7 +296,7 @@ VMKernelAddressSpace::ResizeArea(VMArea* _area, size_t newSize,
if (sizeDiff == nextRange->size) {
// The next range is completely covered -- remove and delete it.
_RemoveRange(nextRange);
free_etc(nextRange, allocationFlags);
object_cache_delete(fRangesObjectCache, nextRange, allocationFlags);
} else {
// The next range is only partially covered -- shrink it.
if (nextRange->type == Range::RANGE_FREE)
@ -333,8 +346,8 @@ VMKernelAddressSpace::ShrinkAreaHead(VMArea* _area, size_t newSize,
} else {
// no free range before -- we need to allocate a new one and
// insert it
previousRange = new(malloc_flags(allocationFlags)) Range(range->base,
sizeDiff, Range::RANGE_FREE);
previousRange = new(fRangesObjectCache, allocationFlags) Range(
range->base, sizeDiff, Range::RANGE_FREE);
if (previousRange == NULL)
return B_NO_MEMORY;
range->base += sizeDiff;
@ -605,8 +618,8 @@ VMKernelAddressSpace::_AllocateRange(
// allocation at the beginning of the range
if (range->size > size) {
// only partial -- split the range
Range* leftOverRange = new(malloc_flags(allocationFlags)) Range(
address + size, range->size - size, range);
Range* leftOverRange = new(fRangesObjectCache, allocationFlags)
Range(address + size, range->size - size, range);
if (leftOverRange == NULL)
return B_NO_MEMORY;
@ -615,7 +628,7 @@ VMKernelAddressSpace::_AllocateRange(
}
} else if (address + size == range->base + range->size) {
// 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);
if (leftOverRange == NULL)
return B_NO_MEMORY;
@ -625,14 +638,15 @@ VMKernelAddressSpace::_AllocateRange(
_InsertRange(leftOverRange);
} else {
// 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);
if (leftOverRange1 == NULL)
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);
if (leftOverRange2 == NULL) {
free_etc(leftOverRange1, allocationFlags);
object_cache_delete(fRangesObjectCache, leftOverRange1,
allocationFlags);
return B_NO_MEMORY;
}
@ -792,15 +806,15 @@ VMKernelAddressSpace::_FreeRange(Range* range, uint32 allocationFlags)
_RemoveRange(range);
_RemoveRange(nextRange);
previousRange->size += range->size + nextRange->size;
free_etc(range, allocationFlags);
free_etc(nextRange, allocationFlags);
object_cache_delete(fRangesObjectCache, range, allocationFlags);
object_cache_delete(fRangesObjectCache, nextRange, allocationFlags);
_FreeListInsertRange(previousRange, previousRange->size);
} else {
// join with the previous range only, delete the supplied one
_FreeListRemoveRange(previousRange, previousRange->size);
_RemoveRange(range);
previousRange->size += range->size;
free_etc(range, allocationFlags);
object_cache_delete(fRangesObjectCache, range, allocationFlags);
_FreeListInsertRange(previousRange, previousRange->size);
}
} else {
@ -808,7 +822,7 @@ VMKernelAddressSpace::_FreeRange(Range* range, uint32 allocationFlags)
// join with the next range and delete it
_RemoveRange(nextRange);
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

View File

@ -1,5 +1,5 @@
/*
* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef VM_KERNEL_ADDRESS_SPACE_H
@ -11,6 +11,9 @@
#include "VMKernelArea.h"
struct ObjectCache;
struct VMKernelAddressSpace : VMAddressSpace {
public:
VMKernelAddressSpace(team_id id, addr_t base,
@ -89,6 +92,8 @@ private:
RangeList fRangeList;
RangeFreeList* fFreeLists;
int fFreeListCount;
ObjectCache* fAreaObjectCache;
ObjectCache* fRangesObjectCache;
};

View File

@ -1,5 +1,5 @@
/*
* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the NewOS License.
*/
@ -7,6 +7,7 @@
#include "VMKernelArea.h"
#include <heap.h>
#include <slab/Slab.h>
#include <vm/vm_priv.h>
@ -25,16 +26,16 @@ VMKernelArea::~VMKernelArea()
/*static*/ VMKernelArea*
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);
if (area == NULL)
return NULL;
if (area->Init(name, allocationFlags) != B_OK) {
area->~VMKernelArea();
free_etc(area, allocationFlags);
object_cache_delete(objectCache, area);
return NULL;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the NewOS License.
*/
#ifndef VM_KERNEL_AREA_H
@ -11,6 +11,7 @@
#include <vm/VMArea.h>
struct ObjectCache;
struct VMKernelAddressSpace;
struct VMKernelArea;
@ -115,7 +116,8 @@ struct VMKernelArea : VMArea, AVLTreeNode {
static VMKernelArea* Create(VMAddressSpace* addressSpace,
const char* name, uint32 wiring,
uint32 protection, uint32 allocationFlags);
uint32 protection, ObjectCache* objectCache,
uint32 allocationFlags);
VMKernelAddressRange* Range() const
{ return fRange; }