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-11-28 14:13:34 +01:00
|
|
|
|
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
|
|
|
|
2015-11-15 18:37:04 +01: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()
|
|
|
|
{
|
2015-11-15 18:37:04 +01:00
|
|
|
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);
|
2014-11-21 23:44:57 +01:00
|
|
|
rbtree_init(&sAddrMap, addrMapNodeComparator);
|
2014-09-17 00:22:30 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-11-05 20:58:50 +01:00
|
|
|
void* linearMemAlign(size_t size, size_t alignment)
|
2014-09-17 00:22:30 +02:00
|
|
|
{
|
2014-11-05 20:58:50 +01: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;
|
2014-11-05 20:58:50 +01:00
|
|
|
if (!sLinearPool.Allocate(chunk, size, shift))
|
2014-09-17 00:22:30 +02:00
|
|
|
return nullptr;
|
|
|
|
|
2014-11-21 23:44:57 +01:00
|
|
|
auto node = newNode(chunk);
|
|
|
|
if (!node)
|
|
|
|
{
|
|
|
|
sLinearPool.Deallocate(chunk);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (rbtree_insert(&sAddrMap, &node->node));
|
|
|
|
return chunk.addr;
|
2014-11-05 20:58:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void* linearAlloc(size_t size)
|
|
|
|
{
|
2015-09-07 12:37:55 +02:00
|
|
|
return linearMemAlign(size, 0x80);
|
2014-09-17 00:22:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void* linearRealloc(void* mem, size_t size)
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-02-16 13:44:19 +01:00
|
|
|
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)
|
|
|
|
{
|
2014-11-21 23:44:57 +01:00
|
|
|
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
|
|
|
}
|
2014-11-03 20:20:33 +01:00
|
|
|
|
|
|
|
u32 linearSpaceFree()
|
|
|
|
{
|
|
|
|
return sLinearPool.GetFreeSpace();
|
|
|
|
}
|