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:
parent
6877edf850
commit
951c43ff21
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user