From d9a1148d13d1b0b32ea89e8dbafb58aae8cc8919 Mon Sep 17 00:00:00 2001 From: cadmic Date: Fri, 2 Feb 2024 14:37:32 -0800 Subject: [PATCH] Match retail __osMalloc.c (#1684) * Match retail __osMalloc.c * Add TODO about N64 ArenaNode debug info * FLAG prefix -> FLAG suffix --- include/functions.h | 36 ++---- include/z64.h | 4 +- src/code/__osMalloc.c | 271 +++++++++++++++++++++++++----------------- 3 files changed, 173 insertions(+), 138 deletions(-) diff --git a/include/functions.h b/include/functions.h index dad884450d..d2baeb8ae7 100644 --- a/include/functions.h +++ b/include/functions.h @@ -1786,45 +1786,23 @@ void Rand_Seed_Variable(u32* rndNum, u32 seed); u32 Rand_Next_Variable(u32* rndNum); f32 Rand_ZeroOne_Variable(u32* rndNum); f32 Rand_Centered_Variable(u32* rndNum); -u32 ArenaImpl_GetFillAllocBlock(Arena* arena); -u32 ArenaImpl_GetFillFreeBlock(Arena* arena); -u32 ArenaImpl_GetCheckFreeBlock(Arena* arena); -void ArenaImpl_SetFillAllocBlock(Arena* arena); -void ArenaImpl_SetFillFreeBlock(Arena* arena); -void ArenaImpl_SetCheckFreeBlock(Arena* arena); -void ArenaImpl_UnsetFillAllocBlock(Arena* arena); -void ArenaImpl_UnsetFillFreeBlock(Arena* arena); -void ArenaImpl_UnsetCheckFreeBlock(Arena* arena); -void ArenaImpl_SetDebugInfo(ArenaNode* node, const char* file, s32 line, Arena* arena); -void ArenaImpl_LockInit(Arena* arena); -void ArenaImpl_Lock(Arena* arena); -void ArenaImpl_Unlock(Arena* arena); -ArenaNode* ArenaImpl_GetNextBlock(ArenaNode* node); -ArenaNode* ArenaImpl_GetPrevBlock(ArenaNode* node); -ArenaNode* ArenaImpl_GetLastBlock(Arena* arena); void __osMallocInit(Arena* arena, void* start, u32 size); void __osMallocAddBlock(Arena* arena, void* start, s32 size); -void ArenaImpl_RemoveAllBlocks(Arena* arena); void __osMallocCleanup(Arena* arena); u8 __osMallocIsInitialized(Arena* arena); -void __osMalloc_FreeBlockTest(Arena* arena, ArenaNode* node); -void* __osMalloc_NoLockDebug(Arena* arena, u32 size, const char* file, s32 line); -void* __osMallocDebug(Arena* arena, u32 size, const char* file, s32 line); -void* __osMallocRDebug(Arena* arena, u32 size, const char* file, s32 line); -void* __osMalloc_NoLock(Arena* arena, u32 size); void* __osMalloc(Arena* arena, u32 size); void* __osMallocR(Arena* arena, u32 size); -void __osFree_NoLock(Arena* arena, void* ptr); void __osFree(Arena* arena, void* ptr); -void __osFree_NoLockDebug(Arena* arena, void* ptr, const char* file, s32 line); -void __osFreeDebug(Arena* arena, void* ptr, const char* file, s32 line); void* __osRealloc(Arena* arena, void* ptr, u32 newSize); -void* __osReallocDebug(Arena* arena, void* ptr, u32 newSize, const char* file, s32 line); void ArenaImpl_GetSizes(Arena* arena, u32* outMaxFree, u32* outFree, u32* outAlloc); -void __osDisplayArena(Arena* arena); -void ArenaImpl_FaultClient(Arena* arena); u32 __osCheckArena(Arena* arena); -u8 func_800FF334(Arena* arena); +#if OOT_DEBUG +void* __osMallocDebug(Arena* arena, u32 size, const char* file, s32 line); +void* __osMallocRDebug(Arena* arena, u32 size, const char* file, s32 line); +void __osFreeDebug(Arena* arena, void* ptr, const char* file, s32 line); +void* __osReallocDebug(Arena* arena, void* ptr, u32 newSize, const char* file, s32 line); +void __osDisplayArena(Arena* arena); +#endif s32 PrintUtils_VPrintf(PrintCallback* pfn, const char* fmt, va_list args); s32 PrintUtils_Printf(PrintCallback* pfn, const char* fmt, ...); void Sleep_Cycles(OSTime cycles); diff --git a/include/z64.h b/include/z64.h index 0d8b37d843..92ce7fb686 100644 --- a/include/z64.h +++ b/include/z64.h @@ -704,7 +704,7 @@ typedef struct Arena { /* 0x00 */ struct ArenaNode* head; /* 0x04 */ void* start; /* 0x08 */ OSMesgQueue lockQueue; - /* 0x20 */ u8 unk_20; + /* 0x20 */ u8 allocFailures; // only used in non-debug builds /* 0x21 */ u8 isInit; /* 0x22 */ u8 flag; } Arena; // size = 0x24 @@ -715,12 +715,14 @@ typedef struct ArenaNode { /* 0x04 */ u32 size; /* 0x08 */ struct ArenaNode* next; /* 0x0C */ struct ArenaNode* prev; +#if OOT_DEBUG // TODO: This debug info is also present in N64 retail builds /* 0x10 */ const char* filename; /* 0x14 */ s32 line; /* 0x18 */ OSId threadId; /* 0x1C */ Arena* arena; /* 0x20 */ OSTime time; /* 0x28 */ u8 unk_28[0x30-0x28]; // probably padding +#endif } ArenaNode; // size = 0x30 /* Relocation entry field getters */ diff --git a/src/code/__osMalloc.c b/src/code/__osMalloc.c index 6a12b5a5a8..6119f8af07 100644 --- a/src/code/__osMalloc.c +++ b/src/code/__osMalloc.c @@ -1,9 +1,9 @@ #include "global.h" #include "terminal.h" -#define FILL_ALLOCBLOCK (1 << 0) -#define FILL_FREEBLOCK (1 << 1) -#define CHECK_FREE_BLOCK (1 << 2) +#define FILL_ALLOC_BLOCK_FLAG (1 << 0) +#define FILL_FREE_BLOCK_FLAG (1 << 1) +#define CHECK_FREE_BLOCK_FLAG (1 << 2) #define NODE_MAGIC (0x7373) @@ -14,37 +14,90 @@ #define BLOCK_FREE_MAGIC (0xEF) #define BLOCK_FREE_MAGIC_32 (0xEFEFEFEF) +#define NODE_IS_VALID(node) (((node) != NULL) && ((node)->magic == NODE_MAGIC)) + +#if OOT_DEBUG + +#define NODE_GET_NEXT(node) ArenaImpl_GetNextBlock(node) +#define NODE_GET_PREV(node) ArenaImpl_GetPrevBlock(node) + +#define SET_DEBUG_INFO(node, file, line, arena) ArenaImpl_SetDebugInfo(node, file, line, arena) + +#define FILL_ALLOC_BLOCK(arena, alloc, size) \ + if ((arena)->flag & FILL_ALLOC_BLOCK_FLAG) \ + __osMemset(alloc, BLOCK_ALLOC_MAGIC, size) + +#define FILL_FREE_BLOCK_HEADER(arena, node) \ + if ((arena)->flag & FILL_FREE_BLOCK_FLAG) \ + __osMemset(node, BLOCK_FREE_MAGIC, sizeof(ArenaNode)) + +#define FILL_FREE_BLOCK_CONTENTS(arena, node) \ + if ((arena)->flag & FILL_FREE_BLOCK_FLAG) \ + __osMemset((void*)((u32)(node) + sizeof(ArenaNode)), BLOCK_FREE_MAGIC, (node)->size) + +#define CHECK_FREE_BLOCK(arena, node) \ + if ((arena)->flag & CHECK_FREE_BLOCK_FLAG) \ + __osMalloc_FreeBlockTest(arena, node) + +#define CHECK_ALLOC_FAILURE(arena, ptr) (void)0 + +#else + +#define NODE_GET_NEXT(node) (NODE_IS_VALID((node)->next) ? (node)->next : NULL) +#define NODE_GET_PREV(node) (NODE_IS_VALID((node)->prev) ? (node)->prev : NULL) + +#define SET_DEBUG_INFO(node, file, line, arena) (void)0 +#define FILL_ALLOC_BLOCK(arena, alloc, size) (void)0 +#define FILL_FREE_BLOCK_HEADER(arena, node) (void)0 +#define FILL_FREE_BLOCK_CONTENTS(arena, node) (void)0 +#define CHECK_FREE_BLOCK(arena, node) (void)0 + +// Number of allocation failures across all arenas. +u32 sTotalAllocFailures = 0; + +#define CHECK_ALLOC_FAILURE(arena, ptr) \ + do { \ + if ((ptr) == NULL) { \ + sTotalAllocFailures++; \ + (arena)->allocFailures++; \ + } \ + } while (0) + +#endif + OSMesg sArenaLockMsg; + +#if OOT_DEBUG u32 __osMalloc_FreeBlockTest_Enable; u32 ArenaImpl_GetFillAllocBlock(Arena* arena) { - return (arena->flag & FILL_ALLOCBLOCK) != 0; + return (arena->flag & FILL_ALLOC_BLOCK_FLAG) != 0; } u32 ArenaImpl_GetFillFreeBlock(Arena* arena) { - return (arena->flag & FILL_FREEBLOCK) != 0; + return (arena->flag & FILL_FREE_BLOCK_FLAG) != 0; } u32 ArenaImpl_GetCheckFreeBlock(Arena* arena) { - return (arena->flag & CHECK_FREE_BLOCK) != 0; + return (arena->flag & CHECK_FREE_BLOCK_FLAG) != 0; } void ArenaImpl_SetFillAllocBlock(Arena* arena) { - arena->flag |= FILL_ALLOCBLOCK; + arena->flag |= FILL_ALLOC_BLOCK_FLAG; } void ArenaImpl_SetFillFreeBlock(Arena* arena) { - arena->flag |= FILL_FREEBLOCK; + arena->flag |= FILL_FREE_BLOCK_FLAG; } void ArenaImpl_SetCheckFreeBlock(Arena* arena) { - arena->flag |= CHECK_FREE_BLOCK; + arena->flag |= CHECK_FREE_BLOCK_FLAG; } void ArenaImpl_UnsetFillAllocBlock(Arena* arena) { - arena->flag &= ~FILL_ALLOCBLOCK; + arena->flag &= ~FILL_ALLOC_BLOCK_FLAG; } void ArenaImpl_UnsetFillFreeBlock(Arena* arena) { - arena->flag &= ~FILL_FREEBLOCK; + arena->flag &= ~FILL_FREE_BLOCK_FLAG; } void ArenaImpl_UnsetCheckFreeBlock(Arena* arena) { - arena->flag &= ~CHECK_FREE_BLOCK; + arena->flag &= ~CHECK_FREE_BLOCK_FLAG; } void ArenaImpl_SetDebugInfo(ArenaNode* node, const char* file, s32 line, Arena* arena) { @@ -54,6 +107,7 @@ void ArenaImpl_SetDebugInfo(ArenaNode* node, const char* file, s32 line, Arena* node->arena = arena; node->time = osGetTime(); } +#endif void ArenaImpl_LockInit(Arena* arena) { osCreateMesgQueue(&arena->lockQueue, &sArenaLockMsg, 1); @@ -67,6 +121,7 @@ void ArenaImpl_Unlock(Arena* arena) { osRecvMesg(&arena->lockQueue, NULL, OS_MESG_BLOCK); } +#if OOT_DEBUG ArenaNode* ArenaImpl_GetNextBlock(ArenaNode* node) { ArenaNode* next = node->next; @@ -88,16 +143,17 @@ ArenaNode* ArenaImpl_GetPrevBlock(ArenaNode* node) { } return prev; } +#endif ArenaNode* ArenaImpl_GetLastBlock(Arena* arena) { ArenaNode* last = NULL; ArenaNode* iter; - if (arena != NULL && arena->head != NULL && arena->head->magic == NODE_MAGIC) { + if (arena != NULL && NODE_IS_VALID(arena->head)) { iter = arena->head; while (iter != NULL) { last = iter; - iter = ArenaImpl_GetNextBlock(iter); + iter = NODE_GET_NEXT(last); } } return last; @@ -122,7 +178,9 @@ void __osMallocAddBlock(Arena* arena, void* start, s32 size) { size2 = (size - diff) & ~0xF; if (size2 > (s32)sizeof(ArenaNode)) { +#if OOT_DEBUG __osMemset(firstNode, BLOCK_UNINIT_MAGIC, size2); +#endif firstNode->next = NULL; firstNode->prev = NULL; firstNode->size = size2 - sizeof(ArenaNode); @@ -142,6 +200,7 @@ void __osMallocAddBlock(Arena* arena, void* start, s32 size) { } } +#if OOT_DEBUG void ArenaImpl_RemoveAllBlocks(Arena* arena) { ArenaNode* iter; ArenaNode* next; @@ -150,16 +209,19 @@ void ArenaImpl_RemoveAllBlocks(Arena* arena) { iter = arena->head; while (iter != NULL) { - next = ArenaImpl_GetNextBlock(iter); + next = NODE_GET_NEXT(iter); __osMemset(iter, BLOCK_UNINIT_MAGIC, iter->size + sizeof(ArenaNode)); iter = next; } ArenaImpl_Unlock(arena); } +#endif void __osMallocCleanup(Arena* arena) { +#if OOT_DEBUG ArenaImpl_RemoveAllBlocks(arena); +#endif bzero(arena, sizeof(*arena)); } @@ -167,6 +229,7 @@ u8 __osMallocIsInitialized(Arena* arena) { return arena->isInit; } +#if OOT_DEBUG void __osMalloc_FreeBlockTest(Arena* arena, ArenaNode* node) { ArenaNode* node2 = node; u32* start; @@ -204,13 +267,11 @@ void* __osMalloc_NoLockDebug(Arena* arena, u32 size, const char* file, s32 line) while (iter != NULL) { if (iter->isFree && iter->size >= size) { - if (arena->flag & CHECK_FREE_BLOCK) { - __osMalloc_FreeBlockTest(arena, iter); - } + CHECK_FREE_BLOCK(arena, iter); if (blockSize < iter->size) { newNode = (ArenaNode*)((u32)iter + blockSize); - newNode->next = ArenaImpl_GetNextBlock(iter); + newNode->next = NODE_GET_NEXT(iter); newNode->prev = iter; newNode->size = iter->size - blockSize; newNode->isFree = true; @@ -218,23 +279,21 @@ void* __osMalloc_NoLockDebug(Arena* arena, u32 size, const char* file, s32 line) iter->next = newNode; iter->size = size; - next = ArenaImpl_GetNextBlock(newNode); + next = NODE_GET_NEXT(newNode); if (next) { next->prev = newNode; } } iter->isFree = false; - ArenaImpl_SetDebugInfo(iter, file, line, arena); + SET_DEBUG_INFO(iter, file, line, arena); alloc = (void*)((u32)iter + sizeof(ArenaNode)); - if (arena->flag & FILL_ALLOCBLOCK) { - __osMemset(alloc, BLOCK_ALLOC_MAGIC, size); - } + FILL_ALLOC_BLOCK(arena, alloc, size); break; } - iter = ArenaImpl_GetNextBlock(iter); + iter = NODE_GET_NEXT(iter); } return alloc; @@ -263,21 +322,19 @@ void* __osMallocRDebug(Arena* arena, u32 size, const char* file, s32 line) { while (iter != NULL) { if (iter->isFree && iter->size >= size) { - if (arena->flag & CHECK_FREE_BLOCK) { - __osMalloc_FreeBlockTest(arena, iter); - } + CHECK_FREE_BLOCK(arena, iter); blockSize = ALIGN16(size) + sizeof(ArenaNode); if (blockSize < iter->size) { newNode = (ArenaNode*)((u32)iter + (iter->size - size)); - newNode->next = ArenaImpl_GetNextBlock(iter); + newNode->next = NODE_GET_NEXT(iter); newNode->prev = iter; newNode->size = size; newNode->magic = NODE_MAGIC; iter->next = newNode; iter->size -= blockSize; - next = ArenaImpl_GetNextBlock(newNode); + next = NODE_GET_NEXT(newNode); if (next) { next->prev = newNode; } @@ -285,21 +342,20 @@ void* __osMallocRDebug(Arena* arena, u32 size, const char* file, s32 line) { } iter->isFree = false; - ArenaImpl_SetDebugInfo(iter, file, line, arena); + SET_DEBUG_INFO(iter, file, line, arena); allocR = (void*)((u32)iter + sizeof(ArenaNode)); - if (arena->flag & FILL_ALLOCBLOCK) { - __osMemset(allocR, BLOCK_ALLOC_MAGIC, size); - } + FILL_ALLOC_BLOCK(arena, allocR, size); break; } - iter = ArenaImpl_GetPrevBlock(iter); + iter = NODE_GET_PREV(iter); } ArenaImpl_Unlock(arena); return allocR; } +#endif void* __osMalloc_NoLock(Arena* arena, u32 size) { ArenaNode* iter; @@ -308,20 +364,17 @@ void* __osMalloc_NoLock(Arena* arena, u32 size) { void* alloc = NULL; ArenaNode* next; - iter = arena->head; size = ALIGN16(size); blockSize = ALIGN16(size) + sizeof(ArenaNode); + iter = arena->head; while (iter != NULL) { if (iter->isFree && iter->size >= size) { - if (arena->flag & CHECK_FREE_BLOCK) { - __osMalloc_FreeBlockTest(arena, iter); - } - + CHECK_FREE_BLOCK(arena, iter); if (blockSize < iter->size) { newNode = (ArenaNode*)((u32)iter + blockSize); - newNode->next = ArenaImpl_GetNextBlock(iter); + newNode->next = NODE_GET_NEXT(iter); newNode->prev = iter; newNode->size = iter->size - blockSize; newNode->isFree = true; @@ -329,24 +382,24 @@ void* __osMalloc_NoLock(Arena* arena, u32 size) { iter->next = newNode; iter->size = size; - next = ArenaImpl_GetNextBlock(newNode); + next = NODE_GET_NEXT(newNode); if (next) { next->prev = newNode; } } iter->isFree = false; - ArenaImpl_SetDebugInfo(iter, NULL, 0, arena); + SET_DEBUG_INFO(iter, NULL, 0, arena); alloc = (void*)((u32)iter + sizeof(ArenaNode)); - if (arena->flag & FILL_ALLOCBLOCK) { - __osMemset(alloc, BLOCK_ALLOC_MAGIC, size); - } + FILL_ALLOC_BLOCK(arena, alloc, size); break; } - iter = ArenaImpl_GetNextBlock(iter); + iter = NODE_GET_NEXT(iter); } + CHECK_ALLOC_FAILURE(arena, alloc); + return alloc; } @@ -362,32 +415,33 @@ void* __osMalloc(Arena* arena, u32 size) { void* __osMallocR(Arena* arena, u32 size) { ArenaNode* iter; + ArenaNode* allocNode; ArenaNode* newNode; - u32 blockSize; ArenaNode* next; void* alloc = NULL; + u32 blockSize; size = ALIGN16(size); + blockSize = ALIGN16(size) + sizeof(ArenaNode); ArenaImpl_Lock(arena); iter = ArenaImpl_GetLastBlock(arena); while (iter != NULL) { if (iter->isFree && iter->size >= size) { - if (arena->flag & CHECK_FREE_BLOCK) { - __osMalloc_FreeBlockTest(arena, iter); - } + CHECK_FREE_BLOCK(arena, iter); - blockSize = ALIGN16(size) + sizeof(ArenaNode); if (blockSize < iter->size) { - newNode = (ArenaNode*)((u32)iter + (iter->size - size)); - newNode->next = ArenaImpl_GetNextBlock(iter); + allocNode = (ArenaNode*)((u32)iter + (iter->size - size)); + allocNode->next = NODE_GET_NEXT(iter); + + newNode = allocNode; newNode->prev = iter; newNode->size = size; newNode->magic = NODE_MAGIC; iter->next = newNode; iter->size -= blockSize; - next = ArenaImpl_GetNextBlock(newNode); + next = NODE_GET_NEXT(newNode); if (next) { next->prev = newNode; } @@ -395,15 +449,16 @@ void* __osMallocR(Arena* arena, u32 size) { } iter->isFree = false; - ArenaImpl_SetDebugInfo(iter, NULL, 0, arena); + SET_DEBUG_INFO(iter, NULL, 0, arena); alloc = (void*)((u32)iter + sizeof(ArenaNode)); - if (arena->flag & FILL_ALLOCBLOCK) { - __osMemset(alloc, BLOCK_ALLOC_MAGIC, size); - } + FILL_ALLOC_BLOCK(arena, alloc, size); break; } - iter = ArenaImpl_GetPrevBlock(iter); + iter = NODE_GET_PREV(iter); } + + CHECK_ALLOC_FAILURE(arena, alloc); + ArenaImpl_Unlock(arena); return alloc; @@ -413,7 +468,6 @@ void __osFree_NoLock(Arena* arena, void* ptr) { ArenaNode* node; ArenaNode* next; ArenaNode* prev; - ArenaNode* newNext; if (ptr == NULL) { return; @@ -422,40 +476,37 @@ void __osFree_NoLock(Arena* arena, void* ptr) { node = (ArenaNode*)((u32)ptr - sizeof(ArenaNode)); if (node == NULL || node->magic != NODE_MAGIC) { // "__osFree: Unauthorized release (%08x)" - osSyncPrintf(VT_COL(RED, WHITE) "__osFree:不正解放(%08x)\n" VT_RST, ptr); + PRINTF(VT_COL(RED, WHITE) "__osFree:不正解放(%08x)\n" VT_RST, ptr); return; } if (node->isFree) { - osSyncPrintf(VT_COL(RED, WHITE) "__osFree:二重解放(%08x)\n" VT_RST, ptr); // "__osFree: Double release (%08x)" + PRINTF(VT_COL(RED, WHITE) "__osFree:二重解放(%08x)\n" VT_RST, ptr); // "__osFree: Double release (%08x)" return; } +#if OOT_DEBUG if (arena != node->arena && arena != NULL) { // "__osFree:Tried to release in a different way than when it was secured (%08x:%08x)" - osSyncPrintf(VT_COL(RED, WHITE) "__osFree:確保時と違う方法で解放しようとした (%08x:%08x)\n" VT_RST, arena, - node->arena); + PRINTF(VT_COL(RED, WHITE) "__osFree:確保時と違う方法で解放しようとした (%08x:%08x)\n" VT_RST, arena, + node->arena); return; } +#endif - next = ArenaImpl_GetNextBlock(node); - prev = ArenaImpl_GetPrevBlock(node); + next = NODE_GET_NEXT(node); + prev = NODE_GET_PREV(node); node->isFree = true; - ArenaImpl_SetDebugInfo(node, NULL, 0, arena); + SET_DEBUG_INFO(node, NULL, 0, arena); - if (arena->flag & FILL_FREEBLOCK) { - __osMemset((void*)((u32)node + sizeof(ArenaNode)), BLOCK_FREE_MAGIC, node->size); - } + FILL_FREE_BLOCK_CONTENTS(arena, node); - newNext = next; if ((u32)next == (u32)node + sizeof(ArenaNode) + node->size && next->isFree) { - newNext = ArenaImpl_GetNextBlock(next); + ArenaNode* newNext = NODE_GET_NEXT(next); if (newNext != NULL) { newNext->prev = node; } node->size += next->size + sizeof(ArenaNode); - if (arena->flag & FILL_FREEBLOCK) { - __osMemset(next, BLOCK_FREE_MAGIC, sizeof(ArenaNode)); - } + FILL_FREE_BLOCK_HEADER(arena, next); node->next = newNext; next = newNext; } @@ -466,9 +517,7 @@ void __osFree_NoLock(Arena* arena, void* ptr) { } prev->next = next; prev->size += node->size + sizeof(ArenaNode); - if (arena->flag & FILL_FREEBLOCK) { - __osMemset(node, BLOCK_FREE_MAGIC, sizeof(ArenaNode)); - } + FILL_FREE_BLOCK_HEADER(arena, node); } } @@ -478,6 +527,7 @@ void __osFree(Arena* arena, void* ptr) { ArenaImpl_Unlock(arena); } +#if OOT_DEBUG void __osFree_NoLockDebug(Arena* arena, void* ptr, const char* file, s32 line) { ArenaNode* node; ArenaNode* next; @@ -491,41 +541,37 @@ void __osFree_NoLockDebug(Arena* arena, void* ptr, const char* file, s32 line) { node = (ArenaNode*)((u32)ptr - sizeof(ArenaNode)); if (node == NULL || node->magic != NODE_MAGIC) { // "__osFree: Unauthorized release (%08x)" - osSyncPrintf(VT_COL(RED, WHITE) "__osFree:不正解放(%08x) [%s:%d ]\n" VT_RST, ptr, file, line); + PRINTF(VT_COL(RED, WHITE) "__osFree:不正解放(%08x) [%s:%d ]\n" VT_RST, ptr, file, line); return; } if (node->isFree) { // "__osFree: Double release (%08x)" - osSyncPrintf(VT_COL(RED, WHITE) "__osFree:二重解放(%08x) [%s:%d ]\n" VT_RST, ptr, file, line); + PRINTF(VT_COL(RED, WHITE) "__osFree:二重解放(%08x) [%s:%d ]\n" VT_RST, ptr, file, line); return; } if (arena != node->arena && arena != NULL) { // "__osFree:Tried to release in a different way than when it was secured (%08x:%08x)" - osSyncPrintf(VT_COL(RED, WHITE) "__osFree:確保時と違う方法で解放しようとした (%08x:%08x)\n" VT_RST, arena, - node->arena); + PRINTF(VT_COL(RED, WHITE) "__osFree:確保時と違う方法で解放しようとした (%08x:%08x)\n" VT_RST, arena, + node->arena); return; } - next = ArenaImpl_GetNextBlock(node); - prev = ArenaImpl_GetPrevBlock(node); + next = NODE_GET_NEXT(node); + prev = NODE_GET_PREV(node); node->isFree = true; - ArenaImpl_SetDebugInfo(node, file, line, arena); + SET_DEBUG_INFO(node, file, line, arena); - if (arena->flag & FILL_FREEBLOCK) { - __osMemset((void*)((u32)node + sizeof(ArenaNode)), BLOCK_FREE_MAGIC, node->size); - } + FILL_FREE_BLOCK_CONTENTS(arena, node); newNext = node->next; if ((u32)next == (u32)node + sizeof(ArenaNode) + node->size && next->isFree) { - newNext = ArenaImpl_GetNextBlock(next); + newNext = NODE_GET_NEXT(next); if (newNext != NULL) { newNext->prev = node; } node->size += next->size + sizeof(ArenaNode); - if (arena->flag & FILL_FREEBLOCK) { - __osMemset(next, BLOCK_FREE_MAGIC, sizeof(ArenaNode)); - } + FILL_FREE_BLOCK_HEADER(arena, next); node->next = newNext; next = newNext; } @@ -536,9 +582,7 @@ void __osFree_NoLockDebug(Arena* arena, void* ptr, const char* file, s32 line) { } prev->next = next; prev->size += node->size + sizeof(ArenaNode); - if (arena->flag & FILL_FREEBLOCK) { - __osMemset(node, BLOCK_FREE_MAGIC, sizeof(ArenaNode)); - } + FILL_FREE_BLOCK_HEADER(arena, node); } } @@ -547,10 +591,11 @@ void __osFreeDebug(Arena* arena, void* ptr, const char* file, s32 line) { __osFree_NoLockDebug(arena, ptr, file, line); ArenaImpl_Unlock(arena); } +#endif void* __osRealloc(Arena* arena, void* ptr, u32 newSize) { - void* newAlloc; ArenaNode* node; + void* newAlloc; ArenaNode* next; ArenaNode* newNext; ArenaNode* overNext; @@ -577,20 +622,20 @@ void* __osRealloc(Arena* arena, void* ptr, u32 newSize) { // "Does nothing because the memory block size does not change" osSyncPrintf("メモリブロックサイズが変わらないためなにもしません\n"); } else if (node->size < newSize) { - next = ArenaImpl_GetNextBlock(node); + next = NODE_GET_NEXT(node); sizeDiff = newSize - node->size; if ((u32)next == ((u32)node + node->size + sizeof(ArenaNode)) && next->isFree && next->size >= sizeDiff) { // "Merge because there is a free block after the current memory block" osSyncPrintf("現メモリブロックの後ろにフリーブロックがあるので結合します\n"); next->size -= sizeDiff; - overNext = ArenaImpl_GetNextBlock(next); + overNext = NODE_GET_NEXT(next); newNext = (ArenaNode*)((u32)next + sizeDiff); if (overNext != NULL) { overNext->prev = newNext; } node->next = newNext; node->size = newSize; - __osMemmove(newNext, next, sizeof(ArenaNode)); + __osMemmove(node->next, next, sizeof(ArenaNode)); } else { // "Allocate a new memory block and move the contents" osSyncPrintf("新たにメモリブロックを確保して内容を移動します\n"); @@ -602,9 +647,10 @@ void* __osRealloc(Arena* arena, void* ptr, u32 newSize) { ptr = newAlloc; } } else if (newSize < node->size) { - next2 = ArenaImpl_GetNextBlock(node); + next2 = NODE_GET_NEXT(node); if (next2 != NULL && next2->isFree) { blockSize = ALIGN16(newSize) + sizeof(ArenaNode); + // "Increased free block behind current memory block" osSyncPrintf("現メモリブロックの後ろのフリーブロックを大きくしました\n"); newNext2 = (ArenaNode*)((u32)node + blockSize); @@ -613,23 +659,24 @@ void* __osRealloc(Arena* arena, void* ptr, u32 newSize) { newNext2->size += node->size - newSize; node->next = newNext2; node->size = newSize; - overNext2 = ArenaImpl_GetNextBlock(newNext2); + overNext2 = NODE_GET_NEXT(newNext2); if (overNext2 != NULL) { overNext2->prev = newNext2; } } else if (newSize + sizeof(ArenaNode) < node->size) { blockSize = ALIGN16(newSize) + sizeof(ArenaNode); + // "Generated because there is no free block after the current memory block" osSyncPrintf("現メモリブロックの後ろにフリーブロックがないので生成します\n"); newNext2 = (ArenaNode*)((u32)node + blockSize); - newNext2->next = ArenaImpl_GetNextBlock(node); + newNext2->next = NODE_GET_NEXT(node); newNext2->prev = node; newNext2->size = node->size - blockSize; newNext2->isFree = true; newNext2->magic = NODE_MAGIC; node->next = newNext2; node->size = newSize; - overNext2 = ArenaImpl_GetNextBlock(newNext2); + overNext2 = NODE_GET_NEXT(newNext2); if (overNext2 != NULL) { overNext2->prev = newNext2; } @@ -639,15 +686,19 @@ void* __osRealloc(Arena* arena, void* ptr, u32 newSize) { ptr = NULL; } } + + CHECK_ALLOC_FAILURE(arena, ptr); } ArenaImpl_Unlock(arena); return ptr; } +#if OOT_DEBUG void* __osReallocDebug(Arena* arena, void* ptr, u32 newSize, const char* file, s32 line) { return __osRealloc(arena, ptr, newSize); } +#endif void ArenaImpl_GetSizes(Arena* arena, u32* outMaxFree, u32* outFree, u32* outAlloc) { ArenaNode* iter; @@ -669,12 +720,13 @@ void ArenaImpl_GetSizes(Arena* arena, u32* outMaxFree, u32* outFree, u32* outAll *outAlloc += iter->size; } - iter = ArenaImpl_GetNextBlock(iter); + iter = NODE_GET_NEXT(iter); } ArenaImpl_Unlock(arena); } +#if OOT_DEBUG void __osDisplayArena(Arena* arena) { u32 freeSize; u32 allocatedSize; @@ -737,6 +789,7 @@ void __osDisplayArena(Arena* arena) { ArenaImpl_Unlock(arena); } +#endif void ArenaImpl_FaultClient(Arena* arena) { u32 freeSize; @@ -803,7 +856,7 @@ u32 __osCheckArena(Arena* arena) { error = 1; break; } - iter = ArenaImpl_GetNextBlock(iter); + iter = NODE_GET_NEXT(iter); } if (error == 0) { osSyncPrintf("アリーナはまだ、いけそうです\n"); // "The arena is still going well" @@ -813,6 +866,8 @@ u32 __osCheckArena(Arena* arena) { return error; } -u8 func_800FF334(Arena* arena) { - return arena->unk_20; +#if OOT_DEBUG +u8 ArenaImpl_GetAllocFailures(Arena* arena) { + return arena->allocFailures; } +#endif