Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement linearRealloc #541

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion libctru/include/3ds/allocator/linear.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
19 changes: 17 additions & 2 deletions libctru/source/allocator/linear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down
85 changes: 85 additions & 0 deletions libctru/source/allocator/mem_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions libctru/source/allocator/mem_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ struct MemChunk
{
u8* addr;
u32 size;
u32 alignMask;
};

struct MemBlock
Expand Down Expand Up @@ -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()
Expand Down