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:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|||||||
Reference in New Issue
Block a user