diff --git a/soh/include/functions.h b/soh/include/functions.h index b3e59779184..97e3be4d99b 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -2267,7 +2267,7 @@ void __osMallocInit(Arena* arena, void* start, size_t size); void __osMallocAddBlock(Arena* arena, void* start, ptrdiff_t size); void ArenaImpl_RemoveAllBlocks(Arena* arena); void __osMallocCleanup(Arena* arena); -u8 __osMallocIsInitalized(Arena* arena); +s32 __osMallocIsInitialized(Arena* arena); void __osMalloc_FreeBlockTest(Arena* arena, ArenaNode* node); void* __osMalloc_NoLockDebug(Arena* arena, size_t size, const char* file, s32 line); void* __osMallocDebug(Arena* arena, size_t size, const char* file, s32 line); @@ -2284,7 +2284,7 @@ void* __osReallocDebug(Arena* arena, void* ptr, size_t newSize, const char* file void ArenaImpl_GetSizes(Arena* arena, u32* outMaxFree, u32* outFree, u32* outAlloc); void __osDisplayArena(Arena* arena); void ArenaImpl_FaultClient(Arena* arena); -u32 __osCheckArena(Arena* arena); +s32 __osCheckArena(Arena* arena); u8 func_800FF334(Arena* arena); s32 PrintUtils_VPrintf(PrintCallback* pfn, const char* fmt, va_list args); s32 PrintUtils_Printf(PrintCallback* pfn, const char* fmt, ...); @@ -2408,7 +2408,7 @@ OSThread* __osGetCurrFaultedThread(void); u32* osViGetCurrentFramebuffer(void); s32 __osSpSetPc(void* pc); f32 absf(f32); -void* func_801068B0(void* dst, void* src, size_t size); +void* oot_memmove(void* dest, const void* src, size_t len); void Message_UpdateOcarinaGame(PlayState* play); u8 Message_ShouldAdvance(PlayState* play); u8 Message_ShouldAdvanceSilent(PlayState* play); diff --git a/soh/include/z64.h b/soh/include/z64.h index 903805f8c9a..cd66089a8f6 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -2038,13 +2038,13 @@ typedef struct ArenaNode { /* 0x04 */ size_t size; /* 0x08 */ struct ArenaNode* next; /* 0x0C */ struct ArenaNode* prev; - ///* 0x10 */ const char* filename; - ///* 0x14 */ s32 line; - ///* 0x18 */ OSId threadId; - ///* 0x1C */ Arena* arena; - ///* 0x20 */ OSTime time; - ///* 0x28 */ u8 unk_28[0x30-0x28]; // probably padding -} ArenaNode; // size = 0x10 + // /* 0x10 */ const char* filename; + // /* 0x14 */ s32 line; + // /* 0x18 */ OSId threadId; + // /* 0x1C */ Arena* arena; + // /* 0x20 */ OSTime time; + // /* 0x28 */ u8 unk_28[0x30-0x28]; // probably padding +} ArenaNode; // size = 0x30 typedef struct OverlayRelocationSection { /* 0x00 */ u32 textSize; diff --git a/soh/src/code/__osMalloc.c b/soh/src/code/__osMalloc.c index 1604332b74e..895de5fd954 100644 --- a/soh/src/code/__osMalloc.c +++ b/soh/src/code/__osMalloc.c @@ -3,61 +3,132 @@ #include -#define FILL_ALLOCBLOCK (1 << 0) -#define FILL_FREEBLOCK (1 << 1) -#define CHECK_FREE_BLOCK (1 << 2) +// SOH [General] This file corresponds to decomp's "__osMalloc_gc.c", there's currently no file corresponding to decomp's "__osMalloc_n64.c" -#define NODE_MAGIC (0x7373) +// #region SOH [General] We currently don't set OOT_DEBUG when building so set it here manually +#define OOT_DEBUG 1 +// #endregion -#define BLOCK_UNINIT_MAGIC (0xAB) -#define BLOCK_UNINIT_MAGIC_32 (0xABABABAB) -#define BLOCK_ALLOC_MAGIC (0xCD) -#define BLOCK_ALLOC_MAGIC_32 (0xCDCDCDCD) -#define BLOCK_FREE_MAGIC (0xEF) -#define BLOCK_FREE_MAGIC_32 (0xEFEFEFEF) +// #region SOH [General] We renamed OoT's memmove to prevent conflicts with the libc version +#define memmove oot_memmove +// #endregion + +#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 + +#define BLOCK_UNINIT_MAGIC 0xAB +#define BLOCK_UNINIT_MAGIC_32 0xABABABAB +#define BLOCK_ALLOC_MAGIC 0xCD +#define BLOCK_ALLOC_MAGIC_32 0xCDCDCDCD +#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_UNINIT_BLOCK(arena, node, size) memset(node, BLOCK_UNINIT_MAGIC, size) + +#define FILL_ALLOC_BLOCK(arena, alloc, size) \ + if ((arena)->flag & FILL_ALLOC_BLOCK_FLAG) \ + memset(alloc, BLOCK_ALLOC_MAGIC, size) + +#define FILL_FREE_BLOCK_HEADER(arena, node) \ + if ((arena)->flag & FILL_FREE_BLOCK_FLAG) \ + memset(node, BLOCK_FREE_MAGIC, sizeof(ArenaNode)) + +#define FILL_FREE_BLOCK_CONTENTS(arena, node) \ + if ((arena)->flag & FILL_FREE_BLOCK_FLAG) \ + memset((void*)((uintptr_t)(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_UNINIT_BLOCK(arena, node, size) (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 gTotalAllocFailures = 0; // "Arena_failcnt" + +#define CHECK_ALLOC_FAILURE(arena, ptr) \ + do { \ + if ((ptr) == NULL) { \ + gTotalAllocFailures++; \ + (arena)->allocFailures++; \ + } \ + } while (0) + +#endif OSMesg sArenaLockMsg; + +void __osMallocAddBlock(Arena* arena, void* start, ptrdiff_t size); + +#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; } -#if 0 -void ArenaImpl_SetDebugInfo(ArenaNode* node, const char* file, s32 line, Arena* arena) { +void ArenaImpl_SetDebugInfo(ArenaNode* node, const char* file, int line, Arena* arena) { + // Upstream TODO: Figure out why uncommenting this crashes + /* node->filename = file; node->line = line; node->threadId = osGetThreadId(NULL); node->arena = arena; node->time = osGetTime(); + */ } #endif + void ArenaImpl_LockInit(Arena* arena) { osCreateMesgQueue(&arena->lock, &sArenaLockMsg, 1); } @@ -70,6 +141,7 @@ void ArenaImpl_Unlock(Arena* arena) { osRecvMesg(&arena->lock, NULL, OS_MESG_BLOCK); } +#if OOT_DEBUG ArenaNode* ArenaImpl_GetNextBlock(ArenaNode* node) { ArenaNode* next = node->next; @@ -91,16 +163,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; @@ -125,7 +198,7 @@ void __osMallocAddBlock(Arena* arena, void* start, ptrdiff_t size) { size2 = (size - diff) & ~0xF; if (size2 > (ptrdiff_t)sizeof(ArenaNode)) { - memset(firstNode, BLOCK_UNINIT_MAGIC, size2); // memset + FILL_UNINIT_BLOCK(arena, firstNode, size2); firstNode->next = NULL; firstNode->prev = NULL; firstNode->size = size2 - sizeof(ArenaNode); @@ -145,6 +218,7 @@ void __osMallocAddBlock(Arena* arena, void* start, ptrdiff_t size) { } } +#if OOT_DEBUG void ArenaImpl_RemoveAllBlocks(Arena* arena) { ArenaNode* iter; ArenaNode* next; @@ -153,23 +227,27 @@ void ArenaImpl_RemoveAllBlocks(Arena* arena) { iter = arena->head; while (iter != NULL) { - next = ArenaImpl_GetNextBlock(iter); - memset(iter, BLOCK_UNINIT_MAGIC, iter->size + sizeof(ArenaNode)); // memset + next = NODE_GET_NEXT(iter); + memset(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 memset(arena, 0, sizeof(*arena)); } -u8 __osMallocIsInitalized(Arena* arena) { +s32 __osMallocIsInitialized(Arena* arena) { return arena->isInit; } +#if OOT_DEBUG void __osMalloc_FreeBlockTest(Arena* arena, ArenaNode* node) { ArenaNode* node2 = node; u32* start; @@ -194,26 +272,24 @@ void __osMalloc_FreeBlockTest(Arena* arena, ArenaNode* node) { } } -void* __osMalloc_NoLockDebug(Arena* arena, size_t size, const char* file, s32 line) { +void* __osMalloc_NoLockDebug(Arena* arena, size_t size, const char* file, int line) { ArenaNode* iter; u32 blockSize; ArenaNode* newNode; 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*)((uintptr_t)iter + blockSize); - newNode->next = ArenaImpl_GetNextBlock(iter); + newNode->next = NODE_GET_NEXT(iter); newNode->prev = iter; newNode->size = iter->size - blockSize; newNode->isFree = true; @@ -221,29 +297,27 @@ void* __osMalloc_NoLockDebug(Arena* arena, size_t size, const char* file, s32 li 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*)((uintptr_t)iter + sizeof(ArenaNode)); - if (arena->flag & FILL_ALLOCBLOCK) { - memset(alloc, BLOCK_ALLOC_MAGIC, size); - } + FILL_ALLOC_BLOCK(arena, alloc, size); break; } - iter = ArenaImpl_GetNextBlock(iter); + iter = NODE_GET_NEXT(iter); } return alloc; } -void* __osMallocDebug(Arena* arena, size_t size, const char* file, s32 line) { +void* __osMallocDebug(Arena* arena, size_t size, const char* file, int line) { void* alloc; ArenaImpl_Lock(arena); @@ -253,7 +327,7 @@ void* __osMallocDebug(Arena* arena, size_t size, const char* file, s32 line) { return alloc; } -void* __osMallocRDebug(Arena* arena, size_t size, const char* file, s32 line) { +void* __osMallocRDebug(Arena* arena, size_t size, const char* file, int line) { ArenaNode* iter; ArenaNode* newNode; u32 blockSize; @@ -266,21 +340,19 @@ void* __osMallocRDebug(Arena* arena, size_t 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*)((uintptr_t)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; } @@ -288,21 +360,21 @@ void* __osMallocRDebug(Arena* arena, size_t size, const char* file, s32 line) { } iter->isFree = false; - //ArenaImpl_SetDebugInfo(iter, file, line, arena); + SET_DEBUG_INFO(iter, file, line, arena); allocR = (void*)((uintptr_t)iter + sizeof(ArenaNode)); - if (arena->flag & FILL_ALLOCBLOCK) { - memset(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, size_t size) { ArenaNode* iter; @@ -311,20 +383,17 @@ void* __osMalloc_NoLock(Arena* arena, size_t 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*)((uintptr_t)iter + blockSize); - newNode->next = ArenaImpl_GetNextBlock(iter); + newNode->next = NODE_GET_NEXT(iter); newNode->prev = iter; newNode->size = iter->size - blockSize; newNode->isFree = true; @@ -332,24 +401,25 @@ void* __osMalloc_NoLock(Arena* arena, size_t 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*)((uintptr_t)iter + sizeof(ArenaNode)); - if (arena->flag & FILL_ALLOCBLOCK) { - memset(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; } @@ -365,32 +435,33 @@ void* __osMalloc(Arena* arena, size_t size) { void* __osMallocR(Arena* arena, size_t 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*)((uintptr_t)iter + (iter->size - size)); - newNode->next = ArenaImpl_GetNextBlock(iter); + allocNode = (ArenaNode*)((uintptr_t)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; } @@ -398,15 +469,16 @@ void* __osMallocR(Arena* arena, size_t size) { } iter->isFree = false; - //ArenaImpl_SetDebugInfo(iter, NULL, 0, arena); + SET_DEBUG_INFO(iter, NULL, 0, arena); alloc = (void*)((uintptr_t)iter + sizeof(ArenaNode)); - if (arena->flag & FILL_ALLOCBLOCK) { - memset(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; @@ -416,14 +488,13 @@ void __osFree_NoLock(Arena* arena, void* ptr) { ArenaNode* node; ArenaNode* next; ArenaNode* prev; - ArenaNode* newNext; if (ptr == NULL) { return; } node = (ArenaNode*)((uintptr_t)ptr - sizeof(ArenaNode)); - if (node == NULL || node->magic != NODE_MAGIC) { + if (!NODE_IS_VALID(node)) { // "__osFree: Unauthorized release (%08x)" osSyncPrintf(VT_COL(RED, WHITE) "__osFree:不正解放(%08x)\n" VT_RST, ptr); return; @@ -432,34 +503,32 @@ void __osFree_NoLock(Arena* arena, void* ptr) { osSyncPrintf(VT_COL(RED, WHITE) "__osFree:二重解放(%08x)\n" VT_RST, ptr); // "__osFree: Double release (%08x)" return; } - #if 0 +#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); 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) { - memset((uintptr_t)node + sizeof(ArenaNode), BLOCK_FREE_MAGIC, node->size); - } + FILL_FREE_BLOCK_CONTENTS(arena, node); - newNext = next; if ((uintptr_t)next == (uintptr_t)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) { - memset(next, BLOCK_FREE_MAGIC, sizeof(ArenaNode)); - } + FILL_FREE_BLOCK_HEADER(arena, next); node->next = newNext; next = newNext; } @@ -470,9 +539,7 @@ void __osFree_NoLock(Arena* arena, void* ptr) { } prev->next = next; prev->size += node->size + sizeof(ArenaNode); - if (arena->flag & FILL_FREEBLOCK) { - memset(node, BLOCK_FREE_MAGIC, sizeof(ArenaNode)); - } + FILL_FREE_BLOCK_HEADER(arena, node); } } @@ -482,7 +549,8 @@ void __osFree(Arena* arena, void* ptr) { ArenaImpl_Unlock(arena); } -void __osFree_NoLockDebug(Arena* arena, void* ptr, const char* file, s32 line) { +#if OOT_DEBUG +void __osFree_NoLockDebug(Arena* arena, void* ptr, const char* file, int line) { ArenaNode* node; ArenaNode* next; ArenaNode* prev; @@ -493,7 +561,7 @@ void __osFree_NoLockDebug(Arena* arena, void* ptr, const char* file, s32 line) { } node = (ArenaNode*)((uintptr_t)ptr - sizeof(ArenaNode)); - if (node == NULL || node->magic != NODE_MAGIC) { + if (!NODE_IS_VALID(node)) { // "__osFree: Unauthorized release (%08x)" osSyncPrintf(VT_COL(RED, WHITE) "__osFree:不正解放(%08x) [%s:%d ]\n" VT_RST, ptr, file, line); return; @@ -503,34 +571,32 @@ void __osFree_NoLockDebug(Arena* arena, void* ptr, const char* file, s32 line) { osSyncPrintf(VT_COL(RED, WHITE) "__osFree:二重解放(%08x) [%s:%d ]\n" VT_RST, ptr, file, line); return; } - #if 0 + + /* 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); 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, file, line, arena); + SET_DEBUG_INFO(node, file, line, arena); - if (arena->flag & FILL_FREEBLOCK) { - memset((uintptr_t)node + sizeof(ArenaNode), BLOCK_FREE_MAGIC, node->size); - } + FILL_FREE_BLOCK_CONTENTS(arena, node); newNext = node->next; if ((uintptr_t)next == (uintptr_t)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) { - memset(next, BLOCK_FREE_MAGIC, sizeof(ArenaNode)); - } + FILL_FREE_BLOCK_HEADER(arena, next); node->next = newNext; next = newNext; } @@ -541,21 +607,20 @@ 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) { - memset(node, BLOCK_FREE_MAGIC, sizeof(ArenaNode)); - } + FILL_FREE_BLOCK_HEADER(arena, node); } } -void __osFreeDebug(Arena* arena, void* ptr, const char* file, s32 line) { +void __osFreeDebug(Arena* arena, void* ptr, const char* file, int line) { ArenaImpl_Lock(arena); __osFree_NoLockDebug(arena, ptr, file, line); ArenaImpl_Unlock(arena); } +#endif void* __osRealloc(Arena* arena, void* ptr, size_t newSize) { - void* newAlloc; ArenaNode* node; + void* newAlloc; ArenaNode* next; ArenaNode* newNext; ArenaNode* overNext; @@ -582,20 +647,20 @@ void* __osRealloc(Arena* arena, void* ptr, size_t 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 ((uintptr_t)next == ((uintptr_t)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*)((uintptr_t)next + sizeDiff); if (overNext != NULL) { overNext->prev = newNext; } node->next = newNext; node->size = newSize; - func_801068B0(newNext, next, sizeof(ArenaNode)); // memcpy + memmove(node->next, next, sizeof(ArenaNode)); } else { // "Allocate a new memory block and move the contents" osSyncPrintf("新たにメモリブロックを確保して内容を移動します\n"); @@ -607,7 +672,7 @@ void* __osRealloc(Arena* arena, void* ptr, size_t 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" @@ -618,7 +683,7 @@ void* __osRealloc(Arena* arena, void* ptr, size_t 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; } @@ -627,14 +692,14 @@ void* __osRealloc(Arena* arena, void* ptr, size_t newSize) { // "Generated because there is no free block after the current memory block" osSyncPrintf("現メモリブロックの後ろにフリーブロックがないので生成します\n"); newNext2 = (ArenaNode*)((uintptr_t)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; } @@ -644,15 +709,19 @@ void* __osRealloc(Arena* arena, void* ptr, size_t newSize) { ptr = NULL; } } + + CHECK_ALLOC_FAILURE(arena, ptr); } ArenaImpl_Unlock(arena); return ptr; } -void* __osReallocDebug(Arena* arena, void* ptr, size_t newSize, const char* file, s32 line) { +#if OOT_DEBUG +void* __osReallocDebug(Arena* arena, void* ptr, size_t newSize, const char* file, int line) { return __osRealloc(arena, ptr, newSize); } +#endif void ArenaImpl_GetSizes(Arena* arena, u32* outMaxFree, u32* outFree, u32* outAlloc) { ArenaNode* iter; @@ -674,12 +743,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) { size_t freeSize; size_t allocatedSize; @@ -687,7 +757,7 @@ void __osDisplayArena(Arena* arena) { ArenaNode* iter; ArenaNode* next; - if (!__osMallocIsInitalized(arena)) { + if (!__osMallocIsInitialized(arena)) { osSyncPrintf("アリーナは初期化されていません\n"); // "Arena is not initalized" return; } @@ -710,12 +780,14 @@ void __osDisplayArena(Arena* arena) { (next == NULL) ? '$' : (iter != next->prev ? '!' : ' '), iter->isFree ? "空き" : "確保", //? "Free" : "Secure" iter->size); - #if 0 + + /* if (!iter->isFree) { osSyncPrintf(" [%016llu:%2d:%s:%d]", OS_CYCLES_TO_NSEC(iter->time), iter->threadId, iter->filename != NULL ? iter->filename : "**NULL**", iter->line); } - #endif + */ + osSyncPrintf("\n"); if (iter->isFree) { @@ -742,6 +814,7 @@ void __osDisplayArena(Arena* arena) { ArenaImpl_Unlock(arena); } +#endif void ArenaImpl_FaultClient(Arena* arena) { size_t freeSize; @@ -751,7 +824,7 @@ void ArenaImpl_FaultClient(Arena* arena) { ArenaNode* next; FaultDrawer_Printf("ARENA INFO (0x%08x)\n", arena); - if (!__osMallocIsInitalized(arena)) { + if (!__osMallocIsInitialized(arena)) { FaultDrawer_Printf("Arena is uninitalized\n", arena); return; } @@ -793,7 +866,7 @@ void ArenaImpl_FaultClient(Arena* arena) { FaultDrawer_Printf("Largest Free Block Size %08x\n", maxFree); } -u32 __osCheckArena(Arena* arena) { +s32 __osCheckArena(Arena* arena) { ArenaNode* iter; u32 error = 0; @@ -802,13 +875,20 @@ u32 __osCheckArena(Arena* arena) { osSyncPrintf("アリーナの内容をチェックしています... (%08x)\n", arena); iter = arena->head; while (iter != NULL) { - if (iter && iter->magic == NODE_MAGIC) { + //! @bug: Probably intended to be `!NODE_IS_VALID(iter)` + if (NODE_IS_VALID(iter)) { +#if OOT_DEBUG // "Oops!! (%08x %08x)" - osSyncPrintf(VT_COL(RED, WHITE) "おおっと!! (%08x %08x)\n" VT_RST, iter, iter->magic); + osSyncPrintf(VT_COL(RED, WHITE) "おおっと!! (%08x %08x)\n" VT_RST, iter, + iter->magic); +#else + // "Oops!! (%08x %08x)" + osSyncPrintf("おおっと!! (%08x %08x)\n", iter, iter->magic); +#endif error = 1; break; } - iter = ArenaImpl_GetNextBlock(iter); + iter = NODE_GET_NEXT(iter); } if (error == 0) { osSyncPrintf("アリーナはまだ、いけそうです\n"); // "The arena is still going well" @@ -818,6 +898,8 @@ u32 __osCheckArena(Arena* arena) { return error; } -u8 func_800FF334(Arena* arena) { +#if OOT_DEBUG +u8 ArenaImpl_GetAllocFailures(Arena* arena) { return arena->unk_20; } +#endif \ No newline at end of file diff --git a/soh/src/code/code_801068B0.c b/soh/src/code/code_801068B0.c index d673cc5e0fe..87434a2744c 100644 --- a/soh/src/code/code_801068B0.c +++ b/soh/src/code/code_801068B0.c @@ -1,24 +1,33 @@ #include "global.h" -// memmove used in __osMalloc.c -void* func_801068B0(void* dst, void* src, size_t size) { - u8* spC = dst; - u8* sp8 = src; - register s32 a3; +/** + * memmove: copies `len` bytes from memory starting at `src` to memory starting at `dest`. + * + * Unlike memcpy(), the regions of memory may overlap. + * + * @param dest address of start of buffer to write to + * @param src address of start of buffer to read from + * @param len number of bytes to copy. + * + * @return dest + */ +void* oot_memmove(void* dest, const void* src, size_t len) { + char* d = dest; + const char* s = src; - if (spC == sp8) { - return dst; + if (d == s) { + return dest; } - if (spC < sp8) { - for (a3 = size--; a3 != 0; a3 = size--) { - *spC++ = *sp8++; + if (d < s) { + while (len--) { + *d++ = *s++; } } else { - spC += size - 1; - sp8 += size - 1; - for (a3 = size--; a3 != 0; a3 = size--) { - *spC-- = *sp8--; + d += len - 1; + s += len - 1; + while (len--) { + *d-- = *s--; } } - return dst; + return dest; } diff --git a/soh/src/code/debug_malloc.c b/soh/src/code/debug_malloc.c index c1c4f99d003..396e4086d7f 100644 --- a/soh/src/code/debug_malloc.c +++ b/soh/src/code/debug_malloc.c @@ -109,5 +109,5 @@ void DebugArena_Cleanup(void) { } u8 DebugArena_IsInitalized(void) { - return __osMallocIsInitalized(&sDebugArena); + return __osMallocIsInitialized(&sDebugArena); } diff --git a/soh/src/code/system_malloc.c b/soh/src/code/system_malloc.c index e8bfefed398..7995209eec1 100644 --- a/soh/src/code/system_malloc.c +++ b/soh/src/code/system_malloc.c @@ -107,5 +107,5 @@ void SystemArena_Cleanup(void) { } u8 SystemArena_IsInitalized(void) { - return __osMallocIsInitalized(&gSystemArena); + return __osMallocIsInitialized(&gSystemArena); } diff --git a/soh/src/code/z_malloc.c b/soh/src/code/z_malloc.c index acd4429c071..a44c1e47ded 100644 --- a/soh/src/code/z_malloc.c +++ b/soh/src/code/z_malloc.c @@ -106,5 +106,5 @@ void ZeldaArena_Cleanup() { } u8 ZeldaArena_IsInitalized() { - return __osMallocIsInitalized(&sZeldaArena); + return __osMallocIsInitialized(&sZeldaArena); }