libctru/libctru/source/allocator/linear.cpp

96 lines
1.6 KiB
C++
Raw Normal View History

2014-12-13 20:05:48 +01:00
extern "C"
{
#include <3ds/types.h>
2015-11-11 05:33:37 +01:00
#include <3ds/allocator/linear.h>
2014-12-13 20:05:48 +01:00
#include <3ds/util/rbtree.h>
}
2014-09-17 00:22:30 +02:00
#include "mem_pool.h"
2014-12-14 17:47:34 +01:00
#include "addrmap.h"
2014-09-17 00:22:30 +02:00
extern u32 __ctru_linear_heap;
extern u32 __ctru_linear_heap_size;
2014-09-17 00:22:30 +02:00
static MemPool sLinearPool;
static bool linearInit()
{
auto blk = MemBlock::Create((u8*)__ctru_linear_heap, __ctru_linear_heap_size);
2014-09-17 00:22:30 +02:00
if (blk)
{
sLinearPool.AddBlock(blk);
rbtree_init(&sAddrMap, addrMapNodeComparator);
2014-09-17 00:22:30 +02:00
return true;
}
return false;
}
void* linearMemAlign(size_t size, size_t alignment)
2014-09-17 00:22:30 +02:00
{
// Enforce minimum alignment
if (alignment < 16)
alignment = 16;
// Convert alignment to shift amount
int shift;
for (shift = 4; shift < 32; shift ++)
{
if ((1U<<shift) == alignment)
break;
}
if (shift == 32) // Invalid alignment
return nullptr;
2014-09-17 00:22:30 +02:00
// Initialize the pool if it is not ready
if (!sLinearPool.Ready() && !linearInit())
return nullptr;
// Allocate the chunk
MemChunk chunk;
if (!sLinearPool.Allocate(chunk, size, shift))
2014-09-17 00:22:30 +02:00
return nullptr;
auto node = newNode(chunk);
if (!node)
{
sLinearPool.Deallocate(chunk);
return nullptr;
}
if (rbtree_insert(&sAddrMap, &node->node));
return chunk.addr;
}
void* linearAlloc(size_t size)
{
return linearMemAlign(size, 0x80);
2014-09-17 00:22:30 +02:00
}
void* linearRealloc(void* mem, size_t size)
{
// TODO
return NULL;
}
size_t linearGetSize(void* mem)
{
auto node = getNode(mem);
return node ? node->chunk.size : 0;
}
2014-09-17 00:22:30 +02:00
void linearFree(void* mem)
{
auto node = getNode(mem);
if (!node) return;
// Free the chunk
sLinearPool.Deallocate(node->chunk);
// Free the node
delNode(node);
2014-09-17 00:22:30 +02:00
}
u32 linearSpaceFree()
{
return sLinearPool.GetFreeSpace();
}