Optimized freeing client memory if it spans the whole area.
* If a block of client memory spans the whole chunk, there is no need to walk the free list for adjacent blocks to join. * Minor cleanup.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006-2012, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -19,15 +19,18 @@
|
|||||||
area might be temporarily unavailable or might be relocated at any time.
|
area might be temporarily unavailable or might be relocated at any time.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// TODO: right now, areas will always stay static until they are deleted;
|
// TODO: right now, areas will always stay static until they are deleted;
|
||||||
// locking is not yet done or enforced!
|
// locking is not yet done or enforced!
|
||||||
|
|
||||||
|
|
||||||
#include "ClientMemoryAllocator.h"
|
#include "ClientMemoryAllocator.h"
|
||||||
#include "ServerApp.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "ServerApp.h"
|
||||||
|
|
||||||
|
|
||||||
typedef block_list::Iterator block_iterator;
|
typedef block_list::Iterator block_iterator;
|
||||||
typedef chunk_list::Iterator chunk_iterator;
|
typedef chunk_list::Iterator chunk_iterator;
|
||||||
@@ -126,46 +129,51 @@ ClientMemoryAllocator::Free(block* freeBlock)
|
|||||||
block_iterator iterator = fFreeBlocks.GetIterator();
|
block_iterator iterator = fFreeBlocks.GetIterator();
|
||||||
struct block* before = NULL;
|
struct block* before = NULL;
|
||||||
struct block* after = NULL;
|
struct block* after = NULL;
|
||||||
|
bool inFreeList = true;
|
||||||
|
|
||||||
// TODO: this could be done better if free blocks are sorted,
|
if (freeBlock->size != freeBlock->chunk->size) {
|
||||||
// and if we had one free blocks list per chunk!
|
// TODO: this could be done better if free blocks are sorted,
|
||||||
// IOW this is a bit slow...
|
// and if we had one free blocks list per chunk!
|
||||||
|
// IOW this is a bit slow...
|
||||||
|
|
||||||
while (struct block* block = iterator.Next()) {
|
while (struct block* block = iterator.Next()) {
|
||||||
if (block->chunk != freeBlock->chunk)
|
if (block->chunk != freeBlock->chunk)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (block->base + block->size == freeBlock->base)
|
if (block->base + block->size == freeBlock->base)
|
||||||
before = block;
|
before = block;
|
||||||
|
|
||||||
if (block->base == freeBlock->base + freeBlock->size)
|
if (block->base == freeBlock->base + freeBlock->size)
|
||||||
after = block;
|
after = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (before != NULL && after != NULL) {
|
if (before != NULL && after != NULL) {
|
||||||
// merge with adjacent blocks
|
// merge with adjacent blocks
|
||||||
before->size += after->size + freeBlock->size;
|
before->size += after->size + freeBlock->size;
|
||||||
fFreeBlocks.Remove(after);
|
fFreeBlocks.Remove(after);
|
||||||
free(after);
|
free(after);
|
||||||
free(freeBlock);
|
free(freeBlock);
|
||||||
freeBlock = before;
|
freeBlock = before;
|
||||||
} else if (before != NULL) {
|
} else if (before != NULL) {
|
||||||
before->size += freeBlock->size;
|
before->size += freeBlock->size;
|
||||||
free(freeBlock);
|
free(freeBlock);
|
||||||
freeBlock = before;
|
freeBlock = before;
|
||||||
} else if (after != NULL) {
|
} else if (after != NULL) {
|
||||||
after->base -= freeBlock->size;
|
after->base -= freeBlock->size;
|
||||||
after->size += freeBlock->size;
|
after->size += freeBlock->size;
|
||||||
free(freeBlock);
|
free(freeBlock);
|
||||||
freeBlock = after;
|
freeBlock = after;
|
||||||
|
} else
|
||||||
|
fFreeBlocks.Add(freeBlock);
|
||||||
} else
|
} else
|
||||||
fFreeBlocks.Add(freeBlock);
|
inFreeList = false;
|
||||||
|
|
||||||
if (freeBlock->size == freeBlock->chunk->size) {
|
if (freeBlock->size == freeBlock->chunk->size) {
|
||||||
// We can delete the chunk now
|
// We can delete the chunk now
|
||||||
struct chunk* chunk = freeBlock->chunk;
|
struct chunk* chunk = freeBlock->chunk;
|
||||||
|
|
||||||
fFreeBlocks.Remove(freeBlock);
|
if (inFreeList)
|
||||||
|
fFreeBlocks.Remove(freeBlock);
|
||||||
free(freeBlock);
|
free(freeBlock);
|
||||||
|
|
||||||
fChunks.Remove(chunk);
|
fChunks.Remove(chunk);
|
||||||
@@ -284,6 +292,9 @@ ClientMemoryAllocator::_AllocateChunk(size_t size, bool& newArea)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
ClientMemory::ClientMemory()
|
ClientMemory::ClientMemory()
|
||||||
:
|
:
|
||||||
fBlock(NULL)
|
fBlock(NULL)
|
||||||
@@ -334,6 +345,9 @@ ClientMemory::AreaOffset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
ClonedAreaMemory::ClonedAreaMemory()
|
ClonedAreaMemory::ClonedAreaMemory()
|
||||||
:
|
:
|
||||||
fClonedArea(-1),
|
fClonedArea(-1),
|
||||||
|
|||||||
Reference in New Issue
Block a user