Merge 6003fc9d0c
into 1b1762f872
This commit is contained in:
commit
80eda6ce54
@ -23,7 +23,6 @@ void* linearMemAlign(size_t size, size_t alignment);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reallocates a buffer.
|
* @brief Reallocates a buffer.
|
||||||
* Note: Not implemented yet.
|
|
||||||
* @param mem Buffer to reallocate.
|
* @param mem Buffer to reallocate.
|
||||||
* @param size Size of the buffer to allocate.
|
* @param size Size of the buffer to allocate.
|
||||||
* @return The reallocated buffer.
|
* @return The reallocated buffer.
|
||||||
|
@ -3,6 +3,7 @@ extern "C"
|
|||||||
#include <3ds/types.h>
|
#include <3ds/types.h>
|
||||||
#include <3ds/allocator/linear.h>
|
#include <3ds/allocator/linear.h>
|
||||||
#include <3ds/util/rbtree.h>
|
#include <3ds/util/rbtree.h>
|
||||||
|
#include <string.h> // for memcpy
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "mem_pool.h"
|
#include "mem_pool.h"
|
||||||
@ -58,8 +59,22 @@ void* linearAlloc(size_t size)
|
|||||||
|
|
||||||
void* linearRealloc(void* mem, size_t size)
|
void* linearRealloc(void* mem, size_t size)
|
||||||
{
|
{
|
||||||
// TODO
|
auto node = getNode(mem);
|
||||||
return NULL;
|
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)
|
size_t linearGetSize(void* mem)
|
||||||
|
@ -67,6 +67,7 @@ bool MemPool::Allocate(MemChunk& chunk, u32 size, int align)
|
|||||||
// Found space!
|
// Found space!
|
||||||
chunk.addr = addr;
|
chunk.addr = addr;
|
||||||
chunk.size = size;
|
chunk.size = size;
|
||||||
|
chunk.alignMask = alignMask;
|
||||||
|
|
||||||
// Resize the block
|
// Resize the block
|
||||||
if (!begWaste)
|
if (!begWaste)
|
||||||
@ -94,6 +95,90 @@ bool MemPool::Allocate(MemChunk& chunk, u32 size, int align)
|
|||||||
return false;
|
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)
|
void MemPool::Deallocate(const MemChunk& chunk)
|
||||||
{
|
{
|
||||||
u8* cAddr = chunk.addr;
|
u8* cAddr = chunk.addr;
|
||||||
|
@ -15,6 +15,7 @@ struct MemChunk
|
|||||||
{
|
{
|
||||||
u8* addr;
|
u8* addr;
|
||||||
u32 size;
|
u32 size;
|
||||||
|
u32 alignMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MemBlock
|
struct MemBlock
|
||||||
@ -80,6 +81,7 @@ struct MemPool
|
|||||||
void CoalesceRight(MemBlock* b);
|
void CoalesceRight(MemBlock* b);
|
||||||
|
|
||||||
bool Allocate(MemChunk& chunk, u32 size, int align);
|
bool Allocate(MemChunk& chunk, u32 size, int align);
|
||||||
|
bool Reallocate(MemChunk& chunk, u32 size);
|
||||||
void Deallocate(const MemChunk& chunk);
|
void Deallocate(const MemChunk& chunk);
|
||||||
|
|
||||||
void Destroy()
|
void Destroy()
|
||||||
|
Loading…
Reference in New Issue
Block a user