Implement linearRealloc
This commit is contained in:
parent
faf5162b60
commit
cd2bb79f4a
@ -23,7 +23,6 @@ void* linearMemAlign(size_t size, size_t alignment);
|
||||
|
||||
/**
|
||||
* @brief Reallocates a buffer.
|
||||
* Note: Not implemented yet.
|
||||
* @param mem Buffer to reallocate.
|
||||
* @param size Size of the buffer to allocate.
|
||||
* @return The reallocated buffer.
|
||||
|
@ -58,8 +58,22 @@ void* linearAlloc(size_t size)
|
||||
|
||||
void* linearRealloc(void* mem, size_t size)
|
||||
{
|
||||
// TODO
|
||||
return NULL;
|
||||
auto node = getNode(mem);
|
||||
if (!node) return nullptr;
|
||||
|
||||
if (!sLinearPool.Reallocate(node->chunk, size))
|
||||
{
|
||||
size_t minSize = (size < node->chunk.size) ? size : node->chunk.size;
|
||||
void* ret = linearMemAlign(size, node->chunk.alignMask);
|
||||
if (ret)
|
||||
{
|
||||
memcpy(ret, mem, minSize);
|
||||
linearFree(mem);
|
||||
return ret;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
size_t linearGetSize(void* mem)
|
||||
|
@ -67,6 +67,7 @@ bool MemPool::Allocate(MemChunk& chunk, u32 size, int align)
|
||||
// Found space!
|
||||
chunk.addr = addr;
|
||||
chunk.size = size;
|
||||
chunk.alignMask = alignMask;
|
||||
|
||||
// Resize the block
|
||||
if (!begWaste)
|
||||
@ -94,6 +95,90 @@ bool MemPool::Allocate(MemChunk& chunk, u32 size, int align)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MemPool::Reallocate(MemChunk& chunk, u32 size)
|
||||
{
|
||||
u8* cAddr = chunk.addr;
|
||||
u32 cSize = chunk.size;
|
||||
|
||||
u32 newSize = (size + chunk.alignMask) &~ chunk.alignMask;
|
||||
|
||||
if (newSize == cSize)
|
||||
return true;
|
||||
|
||||
if (newSize > cSize)
|
||||
{
|
||||
// Try finding the adjacent memory in the linear pool.
|
||||
MemBlock* b;
|
||||
bool memFound = false;
|
||||
for (b = first; b; b = b->next)
|
||||
{
|
||||
auto addr = b->base;
|
||||
if ((cAddr + cSize) == addr)
|
||||
{
|
||||
memFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if adjacent memory is already occupied, or if it isn't large enough.
|
||||
if (!memFound || newSize > cSize + b->size)
|
||||
return false;
|
||||
|
||||
{
|
||||
u32 memAdded = newSize - cSize;
|
||||
b->base += memAdded;
|
||||
b->size -= memAdded;
|
||||
if (!b->size)
|
||||
DelBlock(b);
|
||||
|
||||
chunk.size = newSize;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (newSize < cSize)
|
||||
{
|
||||
u8* memFreeBase = cAddr + newSize;
|
||||
u32 memFreeSize = cSize - newSize;
|
||||
|
||||
bool done = false;
|
||||
for (auto b = first; !done && b; b = b->next)
|
||||
{
|
||||
auto addr = b->base;
|
||||
if (addr > cAddr)
|
||||
{
|
||||
if ((cAddr + cSize) == addr)
|
||||
{
|
||||
// Merge the memory to be freed to the left of the block.
|
||||
b->base = memFreeBase;
|
||||
b->size += memFreeSize;
|
||||
} else
|
||||
{
|
||||
// We need to insert a new block.
|
||||
auto c = MemBlock::Create(memFreeBase, memFreeSize);
|
||||
if (c) InsertBefore(b, c);
|
||||
else return false;
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!done)
|
||||
{
|
||||
// Either the list is empty or the "memFreeBase" address is past the end
|
||||
// address of the last block -- let's add a new block at the end
|
||||
auto b = MemBlock::Create(memFreeBase, memFreeSize);
|
||||
if (b) AddBlock(b);
|
||||
else return false;
|
||||
}
|
||||
|
||||
chunk.size = newSize;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MemPool::Deallocate(const MemChunk& chunk)
|
||||
{
|
||||
u8* cAddr = chunk.addr;
|
||||
|
@ -15,6 +15,7 @@ struct MemChunk
|
||||
{
|
||||
u8* addr;
|
||||
u32 size;
|
||||
u32 alignMask;
|
||||
};
|
||||
|
||||
struct MemBlock
|
||||
@ -80,6 +81,7 @@ struct MemPool
|
||||
void CoalesceRight(MemBlock* b);
|
||||
|
||||
bool Allocate(MemChunk& chunk, u32 size, int align);
|
||||
bool Reallocate(MemChunk& chunk, u32 size);
|
||||
void Deallocate(const MemChunk& chunk);
|
||||
|
||||
void Destroy()
|
||||
|
Loading…
Reference in New Issue
Block a user