From 3840647d34e7d1b36c1c87d3c509d98b43697b7a Mon Sep 17 00:00:00 2001 From: Maschell Date: Tue, 14 Apr 2026 17:56:02 +0200 Subject: [PATCH] Use non-newlib function to allocate memory for reent structs to make things simpler --- Dockerfile | 4 +- source/hooks.cpp | 2 - source/utils/reent.cpp | 86 +++++++++++++++--------------------------- source/utils/reent.h | 8 +--- 4 files changed, 35 insertions(+), 65 deletions(-) diff --git a/Dockerfile b/Dockerfile index a0d64fd..514ded9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM ghcr.io/wiiu-env/devkitppc:20260225 -COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:reentfix-dev-20260410-ae8bf4a /artifacts $DEVKITPRO -COPY --from=ghcr.io/wiiu-env/wiiupluginsystem:abifix-dev-20260410-b1ab874 /artifacts $DEVKITPRO +COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:reentfix-dev-20260414-cd66e5f /artifacts $DEVKITPRO +COPY --from=ghcr.io/wiiu-env/wiiupluginsystem:abifix-dev-20260414-a43b43c /artifacts $DEVKITPRO COPY --from=ghcr.io/wiiu-env/libfunctionpatcher:20260331 /artifacts $DEVKITPRO COPY --from=ghcr.io/wiiu-env/libmappedmemory:20260331 /artifacts $DEVKITPRO COPY --from=ghcr.io/wiiu-env/libwupsbackend:20260331 /artifacts $DEVKITPRO diff --git a/source/hooks.cpp b/source/hooks.cpp index edfa10b..99d08bd 100644 --- a/source/hooks.cpp +++ b/source/hooks.cpp @@ -149,9 +149,7 @@ void CallHook(const PluginContainer &plugin, const wups_loader_hook_type_t hook_ } wups_loader_init_reent_args_t_ args; args.version = WUPS_REENT_CUR_API_VERSION; - args.restore_head_ptr = &wups_backend_restore_head; args.get_context_ptr = &wups_backend_get_context; - args.set_sentinel_ptr = &wups_backend_set_sentinel; args.add_reent_context_ptr = &wups_backend_register_context; // clang-format off diff --git a/source/utils/reent.cpp b/source/utils/reent.cpp index f98954f..110e5f8 100644 --- a/source/utils/reent.cpp +++ b/source/utils/reent.cpp @@ -13,7 +13,6 @@ #include #define __WUPS_CONTEXT_THREAD_SPECIFIC_ID 0 -#define WUPS_REENT_ALLOC_SENTINEL ((__wups_reent_node *) 0xFFFFFFFF) #define WUPS_REENT_NODE_VERSION 1 #define WUPS_REENT_NODE_MAGIC 0x57555053 // WUPS @@ -84,57 +83,42 @@ void MarkReentNodesForDeletion() { sGlobalNodes.clear(); } -void *wups_backend_set_sentinel() { - DEBUG_FUNCTION_LINE_VERBOSE("[%p] Set sentinel", OSGetCurrentThread()); - auto *head = wups_get_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID); - wups_set_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID, WUPS_REENT_ALLOC_SENTINEL); - return head; -} - -void wups_backend_restore_head(void *oldHead) { - DEBUG_FUNCTION_LINE_VERBOSE("[%p] Set head to %p", OSGetCurrentThread(), oldHead); - wups_set_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID, oldHead); -} - void ClearDanglingReentPtr() { - auto *oldHead = wups_backend_set_sentinel(); for (auto nodeToFree : sGlobalNodesCopy) { if (nodeToFree->cleanupFn) { DEBUG_FUNCTION_LINE_VERBOSE("[%p] Call cleanupFn(%p) for node %p (dangling)", OSGetCurrentThread(), nodeToFree->reentPtr, nodeToFree); nodeToFree->cleanupFn(nodeToFree->reentPtr); } DEBUG_FUNCTION_LINE_VERBOSE("[%p] Free node %p (dangling)", OSGetCurrentThread(), nodeToFree); - free(nodeToFree); + MEMFreeToDefaultHeap(nodeToFree); } sGlobalNodesCopy.clear(); - wups_backend_restore_head(oldHead); } static void __wups_thread_cleanup(OSThread *thread, void *stack) { auto *head = static_cast<__wups_reent_node *>(wups_get_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID)); - if (!head || head == WUPS_REENT_ALLOC_SENTINEL || head->magic != WUPS_REENT_NODE_MAGIC) { + if (!head || head->magic != WUPS_REENT_NODE_MAGIC) { return; } OSThreadCleanupCallbackFn savedCleanup = head->savedCleanup; - // Set to effective global during free to prevent malloc re-entrancy loops - wups_set_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID, WUPS_REENT_ALLOC_SENTINEL); - auto *curr = head; while (curr) { __wups_reent_node *next = curr->next; + if (curr->magic == WUPS_REENT_NODE_MAGIC && curr->version >= 1) { + if (curr->cleanupFn) { + DEBUG_FUNCTION_LINE_VERBOSE("[%p] Call cleanupFn(%p) for node %p", thread, curr->reentPtr, curr); + curr->cleanupFn(curr->reentPtr); + } - if (curr->cleanupFn) { - DEBUG_FUNCTION_LINE_VERBOSE("[%p] Call cleanupFn(%p) for node %p", thread, curr->reentPtr, curr); - curr->cleanupFn(curr->reentPtr); + removeNodeFromListsSafe(curr); + + DEBUG_FUNCTION_LINE_VERBOSE("[%p] Free node %p", thread, curr); + MEMFreeToDefaultHeap(curr); } - removeNodeFromListsSafe(curr); - - DEBUG_FUNCTION_LINE_VERBOSE("[%p] Free node %p", thread, curr); - free(curr); curr = next; } @@ -147,46 +131,41 @@ static void __wups_thread_cleanup(OSThread *thread, void *stack) { } } -void *wups_backend_get_context(const void *pluginId, wups_loader_init_reent_errors_t_ *outError) { - if (!outError) { - OSFatal("Called wups_backend_get_context with error nullptr"); - return nullptr; +bool wups_backend_get_context(const void *pluginId, void **outPtr) { + if (!outPtr) { + return false; } + *outPtr = nullptr; + if (!OSGetCurrentThread()) { - *outError = WUPSReent_ERROR_NO_THREAD; - return nullptr; + return false; } - auto *head = static_cast<__wups_reent_node *>(wups_get_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID)); - - if (head == WUPS_REENT_ALLOC_SENTINEL) { - *outError = WUPSReent_ERROR_GLOBAL_REENT_REQUESTED; - return nullptr; - } + const auto *head = static_cast<__wups_reent_node *>(wups_get_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID)); if (head && head->magic != WUPS_REENT_NODE_MAGIC) { - *outError = WUPSReent_ERROR_GLOBAL_REENT_REQUESTED; - return nullptr; + return false; } const __wups_reent_node *curr = head; while (curr) { if (curr->version >= 1 && curr->pluginId == pluginId) { - return curr->reentPtr; + *outPtr = curr->reentPtr; + break; } curr = curr->next; } - *outError = WUPSReent_ERROR_NONE; - - return nullptr; + return true; } +bool wups_backend_register_context(const void *pluginId, void *reentPtr, void (*cleanupFn)(void *)) { + auto *oldHead = static_cast<__wups_reent_node *>(wups_get_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID)); + if (oldHead && (oldHead->magic != WUPS_REENT_NODE_MAGIC || oldHead->version < WUPS_REENT_NODE_VERSION)) { + return false; + } -bool wups_backend_register_context(const void *pluginId, void *reentPtr, void (*cleanupFn)(void *), void *oldHeadVoid) { - auto *oldHead = static_cast<__wups_reent_node *>(oldHeadVoid); - - auto *newNode = static_cast<__wups_reent_node *>(malloc(sizeof(__wups_reent_node))); + auto *newNode = static_cast<__wups_reent_node *>(MEMAllocFromDefaultHeap(sizeof(__wups_reent_node))); if (!newNode) { return false; } @@ -199,7 +178,7 @@ bool wups_backend_register_context(const void *pluginId, void *reentPtr, void (* newNode->cleanupFn = cleanupFn; newNode->savedCleanup = nullptr; - if (oldHead == nullptr || oldHead == WUPS_REENT_ALLOC_SENTINEL || oldHead->magic != WUPS_REENT_NODE_MAGIC || oldHead->version < WUPS_REENT_NODE_VERSION) { + if (oldHead == nullptr || oldHead->magic != WUPS_REENT_NODE_MAGIC || oldHead->version < WUPS_REENT_NODE_VERSION) { DEBUG_FUNCTION_LINE_VERBOSE("[%p] Set OSSetThreadCleanupCallback for node %p", OSGetCurrentThread(), newNode); newNode->savedCleanup = OSSetThreadCleanupCallback(OSGetCurrentThread(), &__wups_thread_cleanup); } else { @@ -207,7 +186,6 @@ bool wups_backend_register_context(const void *pluginId, void *reentPtr, void (* newNode->savedCleanup = oldHead->savedCleanup; oldHead->savedCleanup = nullptr; } - OSMemoryBarrier(); wups_set_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID, newNode); @@ -259,7 +237,7 @@ void ClearReentDataForPlugins(const std::vector &plugins) { auto *head = static_cast<__wups_reent_node *>(wups_get_thread_specific_ex(__WUPS_CONTEXT_THREAD_SPECIFIC_ID, t)); // Safety checks with Sentinel/Magic - if (!head || head == WUPS_REENT_ALLOC_SENTINEL || head->magic != WUPS_REENT_NODE_MAGIC) { + if (!head || head->magic != WUPS_REENT_NODE_MAGIC) { t = t->activeLink.next; continue; } @@ -314,7 +292,6 @@ void ClearReentDataForPlugins(const std::vector &plugins) { } // Free removed entries - auto *oldHead = wups_backend_set_sentinel(); __wups_reent_node *nodeToFree = deferredFreeHead; while (nodeToFree) { __wups_reent_node *nextNode = nodeToFree->next; @@ -325,10 +302,9 @@ void ClearReentDataForPlugins(const std::vector &plugins) { removeNodeFromListsSafe(nodeToFree); DEBUG_FUNCTION_LINE_VERBOSE("[%p] Free node %p (cleanup)", OSGetCurrentThread(), nodeToFree); - free(nodeToFree); + MEMFreeToDefaultHeap(nodeToFree); nodeToFree = nextNode; } - wups_backend_restore_head(oldHead); } } diff --git a/source/utils/reent.h b/source/utils/reent.h index 730dd00..4c3a17a 100644 --- a/source/utils/reent.h +++ b/source/utils/reent.h @@ -4,13 +4,9 @@ class PluginContainer; -void *wups_backend_get_context(const void *pluginId, wups_loader_init_reent_errors_t_ *outError); +bool wups_backend_get_context(const void *pluginId, void **outPtr); -void *wups_backend_set_sentinel(); - -void wups_backend_restore_head(void *oldHead); - -bool wups_backend_register_context(const void *pluginId, void *reentPtr, void (*cleanupFn)(void *), void *oldHead); +bool wups_backend_register_context(const void *pluginId, void *reentPtr, void (*cleanupFn)(void *)); void ClearReentDataForPlugins(const std::vector &plugins);