Revamp mappableAlloc
This commit is contained in:
parent
c9326f6bce
commit
69483a473a
@ -4,27 +4,24 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <3ds/types.h>
|
||||
|
||||
/**
|
||||
* @brief Reserves a mappable memory area.
|
||||
* @param size Size of the area to reserve.
|
||||
* @brief Initializes the mappable allocator.
|
||||
* @param addrMin Minimum address.
|
||||
* @param addrMax Maxium address.
|
||||
*/
|
||||
void mappableInit(u32 addrMin, u32 addrMax);
|
||||
|
||||
/**
|
||||
* @brief Finds a mappable memory area.
|
||||
* @param size Size of the area to find.
|
||||
* @return The mappable area.
|
||||
*/
|
||||
void* mappableAlloc(size_t size);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the allocated size of a mappable area.
|
||||
* @return The size of the mappable area.
|
||||
*/
|
||||
size_t mappableGetSize(void* mem);
|
||||
|
||||
/**
|
||||
* @brief Frees a mappable area.
|
||||
* @brief Frees a mappable area (stubbed).
|
||||
* @param mem Mappable area to free.
|
||||
*/
|
||||
void mappableFree(void* mem);
|
||||
|
||||
/**
|
||||
* @brief Gets the current mappable free space.
|
||||
* @return The current mappable free space.
|
||||
*/
|
||||
u32 mappableSpaceFree(void);
|
||||
|
59
libctru/source/allocator/mappable.c
Normal file
59
libctru/source/allocator/mappable.c
Normal file
@ -0,0 +1,59 @@
|
||||
#include <3ds/allocator/mappable.h>
|
||||
#include <3ds/svc.h>
|
||||
#include <3ds/result.h>
|
||||
|
||||
static u32 minAddr, maxAddr, currentAddr;
|
||||
|
||||
void mappableInit(u32 addrMin, u32 addrMax)
|
||||
{
|
||||
minAddr = addrMin;
|
||||
maxAddr = addrMax;
|
||||
currentAddr = minAddr;
|
||||
}
|
||||
|
||||
static u32 mappableFindAddressWithin(u32 start, u32 end, u32 size)
|
||||
{
|
||||
MemInfo info;
|
||||
PageInfo pgInfo;
|
||||
|
||||
u32 addr = start;
|
||||
while (addr >= start && (addr + size) < end && (addr + size) >= addr)
|
||||
{
|
||||
if (R_FAILED(svcQueryMemory(&info, &pgInfo, addr)))
|
||||
return 0;
|
||||
|
||||
if (info.state == MEMSTATE_FREE)
|
||||
{
|
||||
u32 sz = info.size - (addr - info.base_addr); // a free block might cover all the memory, etc.
|
||||
if (sz >= size)
|
||||
return addr;
|
||||
}
|
||||
|
||||
addr = info.base_addr + info.size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* mappableAlloc(size_t size)
|
||||
{
|
||||
// Round up, can only allocate in page units
|
||||
size = (size + 0xFFF) & ~0xFFF;
|
||||
|
||||
u32 addr = mappableFindAddressWithin(currentAddr, maxAddr, size);
|
||||
if (addr == 0)
|
||||
{
|
||||
// Need to rollover (maybe)
|
||||
addr = mappableFindAddressWithin(minAddr, currentAddr, size);
|
||||
if (addr == 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
currentAddr = addr + size >= maxAddr ? minAddr : addr + size;
|
||||
return (void *)addr;
|
||||
}
|
||||
|
||||
void mappableFree(void* mem)
|
||||
{
|
||||
(void)mem;
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
extern "C"
|
||||
{
|
||||
#include <3ds/types.h>
|
||||
#include <3ds/allocator/mappable.h>
|
||||
#include <3ds/util/rbtree.h>
|
||||
}
|
||||
|
||||
#include "mem_pool.h"
|
||||
#include "addrmap.h"
|
||||
|
||||
static MemPool sMappablePool;
|
||||
|
||||
static bool mappableInit()
|
||||
{
|
||||
auto blk = MemBlock::Create((u8*)0x10000000, 0x04000000);
|
||||
if (blk)
|
||||
{
|
||||
sMappablePool.AddBlock(blk);
|
||||
rbtree_init(&sAddrMap, addrMapNodeComparator);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void* mappableAlloc(size_t size)
|
||||
{
|
||||
// Initialize the pool if it is not ready
|
||||
if (!sMappablePool.Ready() && !mappableInit())
|
||||
return nullptr;
|
||||
|
||||
// Allocate the chunk
|
||||
MemChunk chunk;
|
||||
if (!sMappablePool.Allocate(chunk, size, 12))
|
||||
return nullptr;
|
||||
|
||||
auto node = newNode(chunk);
|
||||
if (!node)
|
||||
{
|
||||
sMappablePool.Deallocate(chunk);
|
||||
return nullptr;
|
||||
}
|
||||
if (rbtree_insert(&sAddrMap, &node->node));
|
||||
return chunk.addr;
|
||||
}
|
||||
|
||||
size_t mappableGetSize(void* mem)
|
||||
{
|
||||
auto node = getNode(mem);
|
||||
return node ? node->chunk.size : 0;
|
||||
}
|
||||
|
||||
void mappableFree(void* mem)
|
||||
{
|
||||
auto node = getNode(mem);
|
||||
if (!node) return;
|
||||
|
||||
// Free the chunk
|
||||
sMappablePool.Deallocate(node->chunk);
|
||||
|
||||
// Free the node
|
||||
delNode(node);
|
||||
}
|
||||
|
||||
u32 mappableSpaceFree()
|
||||
{
|
||||
return sMappablePool.GetFreeSpace();
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#include <3ds/types.h>
|
||||
#include <3ds/svc.h>
|
||||
#include <3ds/allocator/mappable.h>
|
||||
#include <3ds/env.h>
|
||||
#include <3ds/os.h>
|
||||
|
||||
@ -39,6 +39,9 @@ void __attribute__((weak)) __system_allocateHeaps(void) {
|
||||
// Allocate the linear heap
|
||||
svcControlMemory(&__ctru_linear_heap, 0x0, 0x0, __ctru_linear_heap_size, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
|
||||
|
||||
// Mappable allocator init
|
||||
mappableInit(0x10000000, 0x14000000);
|
||||
|
||||
// Set up newlib heap
|
||||
fake_heap_start = (char*)__ctru_heap;
|
||||
fake_heap_end = fake_heap_start + __ctru_heap_size;
|
||||
|
Loading…
Reference in New Issue
Block a user