-
-
Notifications
You must be signed in to change notification settings - Fork 170
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from smealum/refactor
Refactor
- Loading branch information
Showing
5 changed files
with
264 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#include <3ds.h> | ||
#include "mem_pool.h" | ||
|
||
extern u32 __linear_heap, __linear_heap_size; | ||
|
||
static MemPool sLinearPool; | ||
|
||
static bool linearInit() | ||
{ | ||
auto blk = MemBlock::Create((u8*)__linear_heap, __linear_heap_size); | ||
if (blk) | ||
{ | ||
sLinearPool.AddBlock(blk); | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
void* linearAlloc(size_t size) | ||
{ | ||
// Initialize the pool if it is not ready | ||
if (!sLinearPool.Ready() && !linearInit()) | ||
return nullptr; | ||
|
||
// Reserve memory for MemChunk structure | ||
size += 16; | ||
|
||
// Allocate the chunk | ||
MemChunk chunk; | ||
if (!sLinearPool.Allocate(chunk, size, 4)) // 16-byte alignment | ||
return nullptr; | ||
|
||
// Copy the MemChunk structure and return memory | ||
auto addr = chunk.addr; | ||
*(MemChunk*)addr = chunk; | ||
return addr + 16; | ||
} | ||
|
||
void* linearRealloc(void* mem, size_t size) | ||
{ | ||
// TODO | ||
return NULL; | ||
} | ||
|
||
void linearFree(void* mem) | ||
{ | ||
// Find MemChunk structure and free the chunk | ||
auto pChunk = (MemChunk*)((u8*)mem - 16); | ||
sLinearPool.Deallocate(*pChunk); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
#include "mem_pool.h" | ||
|
||
/* | ||
// This method is currently unused | ||
void MemPool::CoalesceLeft(MemBlock* b) | ||
{ | ||
auto curPtr = b->base; | ||
for (auto p = b->prev; p; p = p->prev) | ||
{ | ||
if ((p->base + p->size) != curPtr) break; | ||
curPtr = p->base; | ||
p->size += b->size; | ||
DelBlock(b); | ||
b = p; | ||
} | ||
} | ||
*/ | ||
|
||
void MemPool::CoalesceRight(MemBlock* b) | ||
{ | ||
auto curPtr = b->base + b->size; | ||
auto next = b->next; | ||
for (auto n = next; n; n = next) | ||
{ | ||
next = n->next; | ||
if (n->base != curPtr) break; | ||
b->size += n->size; | ||
curPtr += n->size; | ||
DelBlock(n); | ||
} | ||
} | ||
|
||
bool MemPool::Allocate(MemChunk& chunk, u32 size, int align) | ||
{ | ||
int alignM = (1 << align) - 1; | ||
size = (size + alignM) &~ alignM; // Round the size | ||
// Find the first suitable block | ||
for (auto b = first; b; b = b->next) | ||
{ | ||
auto addr = b->base; | ||
u32 begWaste = (u32)addr & alignM; | ||
addr += begWaste; | ||
u32 bSize = b->size - begWaste; | ||
if (bSize < size) continue; | ||
|
||
// Found space! | ||
chunk.addr = addr; | ||
chunk.size = size; | ||
|
||
// Resize the block | ||
if (!begWaste) | ||
{ | ||
b->base += size; | ||
b->size -= size; | ||
if (!b->size) | ||
DelBlock(b); | ||
} else | ||
{ | ||
auto nAddr = addr + size; | ||
auto nSize = bSize - size; | ||
b->size = begWaste; | ||
if (nSize) | ||
{ | ||
// We need to add the tail chunk that wasn't used to the list | ||
auto n = MemBlock::Create(nAddr, nSize); | ||
if (n) InsertAfter(b, n); | ||
else chunk.size += nSize; // we have no choice but to waste the space. | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
void MemPool::Deallocate(const MemChunk& chunk) | ||
{ | ||
u8* cAddr = chunk.addr; | ||
auto cSize = chunk.size; | ||
bool done = false; | ||
|
||
// Try to merge the chunk somewhere into the list | ||
for (auto b = first; !done && b; b = b->next) | ||
{ | ||
auto addr = b->base; | ||
if (addr > cAddr) | ||
{ | ||
if ((cAddr + cSize) == addr) | ||
{ | ||
// Merge the chunk to the left of the block | ||
b->base = cAddr; | ||
b->size += cSize; | ||
} else | ||
{ | ||
// We need to insert a new block | ||
auto c = MemBlock::Create(cAddr, cSize); | ||
if (c) InsertBefore(b, c); | ||
} | ||
done = true; | ||
} else if ((b->base + b->size) == cAddr) | ||
{ | ||
// Coalesce to the right | ||
b->size += cSize; | ||
CoalesceRight(b); | ||
done = true; | ||
} | ||
} | ||
|
||
if (!done) | ||
{ | ||
// Either the list is empty or the chunk address is past the end | ||
// address of the last block -- let's add a new block at the end | ||
auto b = MemBlock::Create(cAddr, cSize); | ||
if (b) AddBlock(b); | ||
} | ||
} | ||
|
||
/* | ||
void MemPool::Dump(const char* title) | ||
{ | ||
printf("<%s> VRAM Pool Dump\n", title); | ||
for (auto b = first; b; b = b->next) | ||
printf(" - %p (%u bytes)\n", b->base, b->size); | ||
} | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
#pragma once | ||
#include <3ds.h> | ||
|
||
struct MemChunk | ||
{ | ||
u8* addr; | ||
u32 size; | ||
}; | ||
|
||
struct MemBlock | ||
{ | ||
MemBlock *prev, *next; | ||
u8* base; | ||
u32 size; | ||
|
||
static MemBlock* Create(u8* base, u32 size) | ||
{ | ||
auto b = (MemBlock*)malloc(sizeof(MemBlock)); | ||
if (!b) return nullptr; | ||
b->prev = nullptr; | ||
b->next = nullptr; | ||
b->base = base; | ||
b->size = size; | ||
return b; | ||
} | ||
}; | ||
|
||
struct MemPool | ||
{ | ||
MemBlock *first, *last; | ||
|
||
bool Ready() { return first != nullptr; } | ||
|
||
void AddBlock(MemBlock* blk) | ||
{ | ||
blk->prev = last; | ||
if (last) last->next = blk; | ||
if (!first) first = blk; | ||
last = blk; | ||
} | ||
|
||
void DelBlock(MemBlock* b) | ||
{ | ||
auto prev = b->prev, &pNext = prev ? prev->next : first; | ||
auto next = b->next, &nPrev = next ? next->prev : last; | ||
pNext = next; | ||
nPrev = prev; | ||
free(b); | ||
} | ||
|
||
void InsertBefore(MemBlock* b, MemBlock* p) | ||
{ | ||
auto prev = b->prev, &pNext = prev ? prev->next : first; | ||
b->prev = p; | ||
p->next = b; | ||
p->prev = prev; | ||
pNext = p; | ||
} | ||
|
||
void InsertAfter(MemBlock* b, MemBlock* n) | ||
{ | ||
auto next = b->next, &nPrev = next ? next->prev : last; | ||
b->next = n; | ||
n->prev = b; | ||
n->next = next; | ||
nPrev = n; | ||
} | ||
|
||
//void CoalesceLeft(MemBlock* b); | ||
void CoalesceRight(MemBlock* b); | ||
|
||
bool Allocate(MemChunk& chunk, u32 size, int align); | ||
void Deallocate(const MemChunk& chunk); | ||
|
||
void Destroy() | ||
{ | ||
MemBlock* next = nullptr; | ||
for (auto b = first; b; b = next) | ||
{ | ||
next = b->next; | ||
free(b); | ||
} | ||
first = nullptr; | ||
last = nullptr; | ||
} | ||
|
||
//void Dump(const char* title); | ||
}; |
This file was deleted.
Oops, something went wrong.