This commit is contained in:
Michael Ball 2025-01-20 20:42:38 +01:00 committed by GitHub
commit 80eda6ce54
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 104 additions and 3 deletions

View File

@ -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.

View File

@ -3,6 +3,7 @@ extern "C"
#include <3ds/types.h>
#include <3ds/allocator/linear.h>
#include <3ds/util/rbtree.h>
#include <string.h> // for memcpy
}
#include "mem_pool.h"
@ -58,8 +59,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 + 1));
if (ret)
{
memcpy(ret, mem, minSize);
linearFree(mem);
return ret;
}
return nullptr;
}
return mem;
}
size_t linearGetSize(void* mem)

View File

@ -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;

View File

@ -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()