diff options
author | PikalaxALT <pikalaxalt@gmail.com> | 2021-08-20 21:00:20 -0400 |
---|---|---|
committer | PikalaxALT <pikalaxalt@gmail.com> | 2021-08-20 21:00:20 -0400 |
commit | cb6f5a1c7ad38e09cb47d402b2b5d78fdd5965cc (patch) | |
tree | b6202c549aa1f981e96e3233b714eb589ce8122a /arm9/lib | |
parent | 36eef8e744976e708abc3652a95f662346ee7072 (diff) |
AllocFromHead, ALlocFromTail
Diffstat (limited to 'arm9/lib')
-rw-r--r-- | arm9/lib/libnns/include/NNS_FND_heapcommon.h | 8 | ||||
-rw-r--r-- | arm9/lib/libnns/src/NNS_FND_expheap.c | 65 |
2 files changed, 73 insertions, 0 deletions
diff --git a/arm9/lib/libnns/include/NNS_FND_heapcommon.h b/arm9/lib/libnns/include/NNS_FND_heapcommon.h index 77473efe..f35bf097 100644 --- a/arm9/lib/libnns/include/NNS_FND_heapcommon.h +++ b/arm9/lib/libnns/include/NNS_FND_heapcommon.h @@ -98,4 +98,12 @@ static inline void FillAllocMemory(NNSiFndHeapHead* pHeapHd, void* address, u32 void NNSi_FndInitHeapHead(NNSiFndHeapHead *pHead, u32 signature, void* heapStart, void* heapEnd, u16 optionFlag); +#define NNSi_FndRoundUp(value, alignment) (((value) + (alignment - 1)) & ~(alignment - 1)) + +#define NNSi_FndRoundUpPtr(ptr, alignment) ((void*)NNSi_FndRoundUp(NNSiGetUIntPtr(ptr), alignment)) + +#define NNSi_FndRoundDown(value, alignment) ((value) & ~(alignment - 1)) + +#define NNSi_FndRoundDownPtr(ptr, alignment) ((void*)NNSi_FndRoundDown(NNSiGetUIntPtr(ptr), alignment)) + #endif //GUARD_NNS_FND_HEAPCOMMON_H diff --git a/arm9/lib/libnns/src/NNS_FND_expheap.c b/arm9/lib/libnns/src/NNS_FND_expheap.c index f5a74dc4..31ea5fbe 100644 --- a/arm9/lib/libnns/src/NNS_FND_expheap.c +++ b/arm9/lib/libnns/src/NNS_FND_expheap.c @@ -36,6 +36,11 @@ static inline void* GetMBlockEndAddr(NNSiFndExpHeapMBlockHead* block) return AddU32ToPtr(GetMemPtrForMBlock(block), block->blockSize);
}
+static inline u16 GetAllocMode(NNSiFndExpHeapHead* pExHeapHd)
+{
+ return NNSi_FndGetBitValue(pExHeapHd->feature, 0, 1);
+}
+
static inline void SetAllocMode(NNSiFndExpHeapHead* pExHeapHd, u16 mode)
{
NNSi_FndSetBitValue(pExHeapHd->feature, 0, 1, mode);
@@ -202,3 +207,63 @@ void* AllocUsedBlockFromFreeBlock(NNSiFndExpHeapHead* pEHHead, NNSiFndExpHeapMBl return mblock;
}
+
+void* AllocFromHead(NNSiFndHeapHead* pHeapHd, u32 size, int alignment)
+{
+ NNSiFndExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead(pHeapHd);
+ const BOOL bAllocFirst = GetAllocMode(pExpHeapHd) == 0;
+ NNSiFndExpHeapMBlockHead* pMBlkHd = NULL;
+ NNSiFndExpHeapMBlockHead* pMBlkHdFound = NULL;
+ u32 foundSize = 0xFFFFFFFF;
+ void* foundMBlock = NULL;
+
+ for (pMBlkHd = pExpHeapHd->mbFreeList.head; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadNext)
+ {
+ void *const mblock = GetMemPtrForMBlock(pMBlkHd);
+ void *const reqMBlock = NNSi_FndRoundUpPtr(mblock, alignment);
+ const u32 offset = GetOffsetFromPtr(mblock, reqMBlock);
+ if (pMBlkHd->blockSize >= size + offset && foundSize > pMBlkHd->blockSize)
+ {
+ pMBlkHdFound = pMBlkHd;
+ foundSize = pMBlkHd->blockSize;
+ foundMBlock = reqMBlock;
+ if (bAllocFirst || foundSize == size)
+ break;
+ }
+ }
+
+ if (!pMBlkHdFound)
+ return NULL;
+
+ return AllocUsedBlockFromFreeBlock(pExpHeapHd, pMBlkHdFound, foundMBlock, size, 0);
+}
+
+void* AllocFromTail(NNSiFndHeapHead* pHeapHd, u32 size, int alignment)
+{
+ NNSiFndExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead(pHeapHd);
+ const BOOL bAllocFirst = GetAllocMode(pExpHeapHd) == 0;
+ NNSiFndExpHeapMBlockHead* pMBlkHd = NULL;
+ NNSiFndExpHeapMBlockHead* pMBlkHdFound = NULL;
+ u32 foundSize = 0xFFFFFFFF;
+ void* foundMBlock = NULL;
+
+ for (pMBlkHd = pExpHeapHd->mbFreeList.tail; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadPrev)
+ {
+ void *const mblock = GetMemPtrForMBlock(pMBlkHd);
+ void *const mBlockEnd = AddU32ToPtr(mblock, pMBlkHd->blockSize);
+ void *const reqMBlock = NNSi_FndRoundDownPtr(SubU32ToPtr(mBlockEnd, size), alignment);
+ if (ComparePtr(reqMBlock, mblock) >= 0 && foundSize > pMBlkHd->blockSize)
+ {
+ pMBlkHdFound = pMBlkHd;
+ foundSize = pMBlkHd->blockSize;
+ foundMBlock = reqMBlock;
+ if (bAllocFirst || foundSize == size)
+ break;
+ }
+ }
+
+ if (!pMBlkHdFound)
+ return NULL;
+
+ return AllocUsedBlockFromFreeBlock(pExpHeapHd, pMBlkHdFound, foundMBlock, size, 1);
+}
|