mirror of
https://github.com/wiiu-env/WiiUModuleSystem.git
synced 2026-09-10 09:25:11 -05:00
Move reent logic into WUMSLoader
This commit is contained in:
2
Makefile
2
Makefile
@@ -3,7 +3,7 @@ include $(TOPDIR)/share/wums_rules
|
|||||||
|
|
||||||
export WUMS_MAJOR := 0
|
export WUMS_MAJOR := 0
|
||||||
export WUMS_MINOR := 3
|
export WUMS_MINOR := 3
|
||||||
export WUMS_PATCH := 5
|
export WUMS_PATCH := 6
|
||||||
|
|
||||||
VERSION := $(WUMS_MAJOR).$(WUMS_MINOR).$(WUMS_PATCH)
|
VERSION := $(WUMS_MAJOR).$(WUMS_MINOR).$(WUMS_PATCH)
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "defines/module_defines.h"
|
#include "defines/module_defines.h"
|
||||||
|
#include "reent_internal.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -68,7 +69,9 @@ typedef enum wums_hook_type_t {
|
|||||||
WUMS_HOOK_GET_CUSTOM_RPL_ALLOCATOR, // for internal usage only
|
WUMS_HOOK_GET_CUSTOM_RPL_ALLOCATOR, // for internal usage only
|
||||||
WUMS_HOOK_CLEAR_ALLOCATED_RPL_MEMORY, // for internal usage only
|
WUMS_HOOK_CLEAR_ALLOCATED_RPL_MEMORY, // for internal usage only
|
||||||
// Introduced in 0.3.5
|
// Introduced in 0.3.5
|
||||||
WUMS_HOOK_INIT_WUT_THREAD // for internal usage only
|
WUMS_HOOK_INIT_WUT_THREAD, // for internal usage only
|
||||||
|
// Introduced in 0.3.6
|
||||||
|
WUMS_HOOK_INIT_REENT_FUNCTIONS // for internal usage only
|
||||||
} wums_hook_type_t;
|
} wums_hook_type_t;
|
||||||
|
|
||||||
typedef uint32_t (*WUMSRPLAllocatorAllocFn)(int32_t size, int32_t align, void **outAddr);
|
typedef uint32_t (*WUMSRPLAllocatorAllocFn)(int32_t size, int32_t align, void **outAddr);
|
||||||
@@ -196,6 +199,14 @@ typedef struct wums_relocs_done_args_t {
|
|||||||
} \
|
} \
|
||||||
WUMS_HOOK_EX(WUMS_HOOK_INIT_WUT_THREAD, on_init_wut_thread);
|
WUMS_HOOK_EX(WUMS_HOOK_INIT_WUT_THREAD, on_init_wut_thread);
|
||||||
|
|
||||||
|
#define WUMS_INIT_REENT_FUNCTIONS() \
|
||||||
|
__EXTERN_C_MACRO void WUMSReentAPI_InitInternal(wums_loader_init_reent_args_t_); \
|
||||||
|
void wums_init_reent_functions(wums_loader_init_reent_args_t_ args); \
|
||||||
|
WUMS_HOOK_EX(WUMS_HOOK_INIT_REENT_FUNCTIONS, wums_init_reent_functions); \
|
||||||
|
void wums_init_reent_functions(wums_loader_init_reent_args_t_ args) { \
|
||||||
|
return WUMSReentAPI_InitInternal(args); \
|
||||||
|
}
|
||||||
|
|
||||||
#define WUMS_USE_WUT_SOCKETS() \
|
#define WUMS_USE_WUT_SOCKETS() \
|
||||||
__EXTERN_C_MACRO void __init_wut_socket(); \
|
__EXTERN_C_MACRO void __init_wut_socket(); \
|
||||||
WUMS_HOOK_EX(WUMS_HOOK_INIT_WUT_SOCKETS, __init_wut_socket); \
|
WUMS_HOOK_EX(WUMS_HOOK_INIT_WUT_SOCKETS, __init_wut_socket); \
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WUMS_VERSION "0.3.5"
|
#define WUMS_VERSION "0.3.6"
|
||||||
|
|
||||||
#define WUMS_MODULE_EXPORT_NAME(__module_name) \
|
#define WUMS_MODULE_EXPORT_NAME(__module_name) \
|
||||||
WUMS_META(export_name, __module_name); \
|
WUMS_META(export_name, __module_name); \
|
||||||
@@ -50,6 +50,7 @@ extern "C" {
|
|||||||
WUMS_USE_WUT_THREAD(); \
|
WUMS_USE_WUT_THREAD(); \
|
||||||
WUMS___INIT_WRAPPER(); \
|
WUMS___INIT_WRAPPER(); \
|
||||||
WUMS___FINI_WRAPPER(); \
|
WUMS___FINI_WRAPPER(); \
|
||||||
|
WUMS_INIT_REENT_FUNCTIONS(); \
|
||||||
WUMS_META(buildtimestamp, __DATE__ " " __TIME__); \
|
WUMS_META(buildtimestamp, __DATE__ " " __TIME__); \
|
||||||
extern const char wums_meta_module_name[] WUMS_SECTION("meta"); \
|
extern const char wums_meta_module_name[] WUMS_SECTION("meta"); \
|
||||||
const char wums_meta_module_name[] = __module_name; \
|
const char wums_meta_module_name[] = __module_name; \
|
||||||
|
|||||||
35
include/wums/reent_internal.h
Normal file
35
include/wums/reent_internal.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum wums_loader_init_reent_errors_t_ {
|
||||||
|
WUMSReent_ERROR_NONE = 0,
|
||||||
|
WUMSReent_ERROR_GLOBAL_REENT_REQUESTED = 1,
|
||||||
|
WUMSReent_ERROR_NO_THREAD = 2,
|
||||||
|
} wums_loader_init_reent_errors_t_;
|
||||||
|
|
||||||
|
typedef void *(*WUMSReent_GetReentContext)(const void *moduleId, wums_loader_init_reent_errors_t_ *outError);
|
||||||
|
typedef void *(*WUMSReent_SetSentinel)();
|
||||||
|
typedef void (*WUMSReent_RestoreHead)(void *oldHead);
|
||||||
|
typedef bool (*WUMSReent_AddReentContext)(const void *moduleId, void *reentPtr, void (*cleanupFn)(void *), void *oldHead);
|
||||||
|
|
||||||
|
typedef uint32_t WUMS_REENT_API_VERSION;
|
||||||
|
|
||||||
|
#define WUMS_REENT_CUR_API_VERSION 0x01
|
||||||
|
|
||||||
|
typedef struct wums_loader_init_reent_args_t_ {
|
||||||
|
WUMS_REENT_API_VERSION version;
|
||||||
|
WUMSReent_GetReentContext get_context_ptr;
|
||||||
|
WUMSReent_SetSentinel set_sentinel_ptr;
|
||||||
|
WUMSReent_RestoreHead restore_head_ptr;
|
||||||
|
WUMSReent_AddReentContext add_reent_context_ptr;
|
||||||
|
} wums_loader_init_reent_args_t_;
|
||||||
|
|
||||||
|
void WUMSReentAPI_InitInternal(wums_loader_init_reent_args_t_ args);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,25 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
extern "C" void OSReport(const char *fmt, ...);
|
||||||
|
|
||||||
#define WUMS_FORMAT_PRINTF(fmt, args) __attribute__((__format__(__printf__, fmt, args)))
|
|
||||||
|
|
||||||
#else // not __GNUC__ and not __clang__
|
|
||||||
|
|
||||||
#define WUMS_FORMAT_PRINTF(fmt, args)
|
|
||||||
|
|
||||||
#endif //__GNUC__ or __clang__
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
extern void OSReport(const char *fmt, ...) WUMS_FORMAT_PRINTF(1, 2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern const char wums_meta_info_dump[];
|
extern const char wums_meta_info_dump[];
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
@@ -31,4 +16,4 @@ extern const char wums_meta_info_dump[];
|
|||||||
#define WUMS_DEBUG_REPORT(fmt, ...)
|
#define WUMS_DEBUG_REPORT(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WUMS_DEBUG_WARN(fmt, ...) OSReport("[%s] " fmt, wums_meta_info_dump, ##__VA_ARGS__)
|
#define WUMS_DEBUG_WARN(fmt, ...) OSReport("\033[33m[%s] " fmt "\033[0m", wums_meta_info_dump, ##__VA_ARGS__)
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
|
#include "wums/wums_debug.h"
|
||||||
#include "wums_reent.h"
|
#include "wums_reent.h"
|
||||||
#include "wums_thread_specific.h"
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C" void OSFatal(const char *);
|
||||||
extern "C" void OSFatal(const char *);
|
extern "C" void OSFatal(const char *);
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
@@ -43,16 +45,22 @@ struct _reent *__getreent(void) {
|
|||||||
return __wums_getreent();
|
return __wums_getreent();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void __attribute__((weak)) wut_set_thread_specific(__wut_thread_specific_id id, void *value);
|
typedef enum __wut_thread_specific_id {
|
||||||
|
WUT_THREAD_SPECIFIC_0 = 0,
|
||||||
void wut_set_thread_specific(__wut_thread_specific_id id, void *value) {
|
WUT_THREAD_SPECIFIC_1 = 1,
|
||||||
return wums_set_thread_specific(id, value);
|
} __wut_thread_specific_id;
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void *__attribute__((weak)) wut_get_thread_specific(__wut_thread_specific_id id);
|
extern "C" void *__attribute__((weak)) wut_get_thread_specific(__wut_thread_specific_id id);
|
||||||
|
|
||||||
void *wut_get_thread_specific(__wut_thread_specific_id id) {
|
void *wut_get_thread_specific(__wut_thread_specific_id id) {
|
||||||
return wums_get_thread_specific(id);
|
if ((uint32_t) id == 0x13371337) { // Mechanism to detect if the function was overridden properly
|
||||||
|
return (void *) 0x42424242;
|
||||||
|
}
|
||||||
|
|
||||||
|
WUMS_DEBUG_WARN("wums_get_thread_specific: NOT SUPPORTED\n");
|
||||||
|
OSFatal("wums_get_thread_specific: NOT SUPPORTED\n");
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" const char wums_meta_module_name[];
|
extern "C" const char wums_meta_module_name[];
|
||||||
@@ -100,6 +108,8 @@ __assert_func(const char *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
OSFatal(buffer);
|
OSFatal(buffer);
|
||||||
|
while (true)
|
||||||
|
;
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,175 +1,105 @@
|
|||||||
#include "wums_reent.h"
|
#include "wums_reent.h"
|
||||||
#include "wums_thread_specific.h"
|
|
||||||
#include <cstring>
|
#include "wums/hooks.h"
|
||||||
#include <stdint.h>
|
#include "wums/reent_internal.h"
|
||||||
|
#include "wums/wums_debug.h"
|
||||||
|
|
||||||
|
extern "C" void OSFatal(const char *format, ...);
|
||||||
|
extern "C" void *OSGetCurrentThread();
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wums/wums_debug.h>
|
|
||||||
|
|
||||||
#define __WUMS_CONTEXT_THREAD_SPECIFIC_ID WUT_THREAD_SPECIFIC_0
|
struct wums_loader_init_reent_args_t {
|
||||||
#define WUMS_REENT_ALLOC_SENTINEL ((__wums_reent_node *) 0xFFFFFFFF)
|
WUMSReent_GetReentContext get_context_ptr = nullptr;
|
||||||
|
WUMSReent_SetSentinel set_sentinel_ptr = nullptr;
|
||||||
extern "C" __attribute__((weak)) void wut_set_thread_specific(__wut_thread_specific_id id, void *value);
|
WUMSReent_RestoreHead restore_head_ptr = nullptr;
|
||||||
extern "C" __attribute__((weak)) void *wut_get_thread_specific(__wut_thread_specific_id);
|
WUMSReent_AddReentContext add_reent_context_ptr = nullptr;
|
||||||
|
|
||||||
typedef uint32_t OSThread;
|
|
||||||
|
|
||||||
extern "C" void OSFatal(const char *);
|
|
||||||
extern "C" void OSReport(const char *, ...);
|
|
||||||
|
|
||||||
extern "C" OSThread *OSGetCurrentThread();
|
|
||||||
|
|
||||||
typedef void (*OSThreadCleanupCallbackFn)(OSThread *thread, void *stack);
|
|
||||||
|
|
||||||
extern "C" OSThreadCleanupCallbackFn
|
|
||||||
OSSetThreadCleanupCallback(OSThread *thread,
|
|
||||||
OSThreadCleanupCallbackFn callback);
|
|
||||||
|
|
||||||
#define WUMS_REENT_NODE_VERSION 1
|
|
||||||
#define WUMS_REENT_NODE_MAGIC 0x57554D53 // WUMS
|
|
||||||
static const int sReentModuleId = 0;
|
|
||||||
|
|
||||||
struct __wums_reent_node {
|
|
||||||
// FIXED HEADER (Never move or change these offsets!)
|
|
||||||
uint32_t magic; // Guarantees this is a __wums_reent_node
|
|
||||||
uint32_t version;
|
|
||||||
__wums_reent_node *next;
|
|
||||||
|
|
||||||
// Node Version 1 Payload
|
|
||||||
const void *moduleId;
|
|
||||||
void *reentPtr;
|
|
||||||
void (*cleanupFn)(__wums_reent_node *);
|
|
||||||
OSThreadCleanupCallbackFn savedCleanup;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void reclaim_reent_trampoline(__wums_reent_node *node) {
|
static wums_loader_init_reent_args_t __internal_functions = {};
|
||||||
WUMS_DEBUG_REPORT("reclaim_reent_trampoline: Destroying node %p (reent: %p)\n", node, node->reentPtr);
|
|
||||||
|
|
||||||
if (node->reentPtr) {
|
void WUMSReentAPI_InitInternal(wums_loader_init_reent_args_t_ args) {
|
||||||
_reclaim_reent(static_cast<_reent *>(node->reentPtr));
|
if (args.version > WUMS_REENT_CUR_API_VERSION) {
|
||||||
free(node->reentPtr);
|
OSFatal("Incompatible reent api version");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
free(node);
|
WUMS_DEBUG_REPORT("WUMSReentAPI_InitInternal: Initializing reent module\n");
|
||||||
|
|
||||||
|
__internal_functions.get_context_ptr = args.get_context_ptr;
|
||||||
|
__internal_functions.set_sentinel_ptr = args.set_sentinel_ptr;
|
||||||
|
__internal_functions.add_reent_context_ptr = args.add_reent_context_ptr;
|
||||||
|
__internal_functions.restore_head_ptr = args.restore_head_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __wums_thread_cleanup(OSThread *thread, void *stack) {
|
// use variable in the .data section as unique module id
|
||||||
auto *head = static_cast<__wums_reent_node *>(wut_get_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID));
|
static const int sReentModuleId = 0;
|
||||||
|
|
||||||
if (!head || head == WUMS_REENT_ALLOC_SENTINEL) {
|
void *wums_backend_get_context(const void *id, wums_loader_init_reent_errors_t_ *outError) {
|
||||||
return;
|
return __internal_functions.get_context_ptr(id, outError);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (head->magic != WUMS_REENT_NODE_MAGIC) {
|
void *wums_backend_set_sentinel() {
|
||||||
WUMS_DEBUG_WARN("__wums_thread_cleanup: Unexpected node magic word: %08X (expected %08X).\n", head->magic, WUMS_REENT_NODE_MAGIC);
|
return __internal_functions.set_sentinel_ptr();
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
WUMS_DEBUG_REPORT("__wums_thread_cleanup: Triggered for thread %p\n", thread);
|
void wums_backend_restore_head(void *head) {
|
||||||
|
__internal_functions.restore_head_ptr(head);
|
||||||
|
}
|
||||||
|
|
||||||
OSThreadCleanupCallbackFn savedCleanup = nullptr;
|
bool wums_backend_register_context(const void *moduleId, void *reentPtr, void (*cleanupFn)(void *), void *oldHead) {
|
||||||
if (head->version >= 1) {
|
return __internal_functions.add_reent_context_ptr(moduleId, reentPtr, cleanupFn, oldHead);
|
||||||
savedCleanup = head->savedCleanup;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Set to effective global during free to prevent malloc re-entrancy loops
|
static void reclaim_reent_trampoline(void *payload) {
|
||||||
wut_set_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID, WUMS_REENT_ALLOC_SENTINEL);
|
WUMS_DEBUG_REPORT("reclaim_reent_trampoline: Destroying reent payload: %p\n", payload);
|
||||||
|
|
||||||
// Safely iterate the ABI-stable list.
|
if (payload) {
|
||||||
auto *curr = head;
|
auto *reentPtr = static_cast<_reent *>(payload);
|
||||||
while (curr) {
|
_reclaim_reent(reentPtr);
|
||||||
// Read the "next" pointer BEFORE destroying the current node.
|
free(reentPtr);
|
||||||
__wums_reent_node *next = curr->next;
|
|
||||||
|
|
||||||
// Trigger the self-destruct sequence. Frees curr
|
|
||||||
if (curr->cleanupFn) {
|
|
||||||
curr->cleanupFn(curr);
|
|
||||||
}
|
|
||||||
|
|
||||||
curr = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
wut_set_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID, nullptr);
|
|
||||||
|
|
||||||
if (savedCleanup) {
|
|
||||||
WUMS_DEBUG_REPORT("__wums_thread_cleanup: Chaining to saved cleanup for thread %p\n", thread);
|
|
||||||
savedCleanup(thread, stack);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct _reent *__wums_getreent() {
|
struct _reent *__wums_getreent() {
|
||||||
if (!wut_get_thread_specific || !wut_set_thread_specific || OSGetCurrentThread() == nullptr) {
|
if (!OSGetCurrentThread()) {
|
||||||
return _GLOBAL_REENT;
|
return _GLOBAL_REENT;
|
||||||
}
|
}
|
||||||
|
wums_loader_init_reent_errors_t_ error = WUMSReent_ERROR_NONE;
|
||||||
auto head = static_cast<__wums_reent_node *>(wut_get_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID));
|
if (void *existingCtx = wums_backend_get_context(&sReentModuleId, &error)) {
|
||||||
|
return static_cast<_reent *>(existingCtx);
|
||||||
if (head == WUMS_REENT_ALLOC_SENTINEL) {
|
}
|
||||||
return _GLOBAL_REENT;
|
switch (error) {
|
||||||
|
case WUMSReent_ERROR_GLOBAL_REENT_REQUESTED:
|
||||||
|
case WUMSReent_ERROR_NO_THREAD:
|
||||||
|
return _GLOBAL_REENT;
|
||||||
|
case WUMSReent_ERROR_NONE:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (head && head->magic != WUMS_REENT_NODE_MAGIC) {
|
auto *oldHead = wums_backend_set_sentinel();
|
||||||
WUMS_DEBUG_WARN("__wums_getreent: Unexpected node magic word: %08X (expected %08X).\n", head->magic, WUMS_REENT_NODE_MAGIC);
|
|
||||||
return _GLOBAL_REENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for already allocated reent ptr.
|
|
||||||
// (Intentionally not logging here to prevent console spam on the fast path)
|
|
||||||
const __wums_reent_node *curr = head;
|
|
||||||
while (curr) {
|
|
||||||
// Use a memory address as a unique id
|
|
||||||
if (curr->version >= 1 && curr->moduleId == &sReentModuleId) {
|
|
||||||
return static_cast<_reent *>(curr->reentPtr);
|
|
||||||
}
|
|
||||||
curr = curr->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
WUMS_DEBUG_REPORT("__wums_getreent: Allocating new context for thread %p\n", OSGetCurrentThread());
|
|
||||||
|
|
||||||
// If not found allocate a new for THIS module.
|
|
||||||
// Temporarily effectively use global reent during context allocation
|
|
||||||
wut_set_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID, WUMS_REENT_ALLOC_SENTINEL);
|
|
||||||
|
|
||||||
auto *newNode = static_cast<__wums_reent_node *>(malloc(sizeof(__wums_reent_node)));
|
|
||||||
auto *newReent = static_cast<struct _reent *>(malloc(sizeof(struct _reent)));
|
auto *newReent = static_cast<struct _reent *>(malloc(sizeof(struct _reent)));
|
||||||
|
if (!newReent) {
|
||||||
if (!newNode || !newReent) {
|
wums_backend_restore_head(oldHead);
|
||||||
WUMS_DEBUG_WARN("__wums_getreent: Failed to allocate context! Falling back to _GLOBAL_REENT.\n");
|
|
||||||
if (newNode) {
|
|
||||||
free(newNode);
|
|
||||||
}
|
|
||||||
if (newReent) {
|
|
||||||
free(newReent);
|
|
||||||
}
|
|
||||||
// reset on error
|
|
||||||
wut_set_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID, head);
|
|
||||||
return _GLOBAL_REENT;
|
return _GLOBAL_REENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WUMS_DEBUG_REPORT("Allocated context! for thread %p: %p\n", OSGetCurrentThread(), newReent);
|
||||||
|
|
||||||
_REENT_INIT_PTR(newReent);
|
_REENT_INIT_PTR(newReent);
|
||||||
|
|
||||||
newNode->magic = WUMS_REENT_NODE_MAGIC;
|
bool result = wums_backend_register_context(
|
||||||
newNode->version = WUMS_REENT_NODE_VERSION;
|
&sReentModuleId,
|
||||||
newNode->next = head;
|
newReent,
|
||||||
newNode->moduleId = &sReentModuleId;
|
reclaim_reent_trampoline,
|
||||||
newNode->reentPtr = newReent;
|
oldHead);
|
||||||
newNode->cleanupFn = reclaim_reent_trampoline;
|
|
||||||
newNode->savedCleanup = nullptr;
|
|
||||||
|
|
||||||
auto oldHead = head;
|
if (!result) {
|
||||||
|
WUMS_DEBUG_WARN("Failed to register context for thread %p\n", OSGetCurrentThread());
|
||||||
// Hook cleanup logic
|
_reclaim_reent(newReent);
|
||||||
if (oldHead == nullptr) {
|
free(newReent);
|
||||||
WUMS_DEBUG_REPORT("__wums_getreent: Hooking OSSetThreadCleanupCallback for thread %p\n", OSGetCurrentThread());
|
wums_backend_restore_head(oldHead);
|
||||||
newNode->savedCleanup = OSSetThreadCleanupCallback(OSGetCurrentThread(), &__wums_thread_cleanup);
|
return _GLOBAL_REENT;
|
||||||
} else {
|
|
||||||
WUMS_DEBUG_REPORT("__wums_getreent: Prepending to existing list for thread %p\n", OSGetCurrentThread());
|
|
||||||
// We prepend, so we must inherit the saved cleanup from the previous head
|
|
||||||
if (oldHead->version >= 1) {
|
|
||||||
newNode->savedCleanup = oldHead->savedCleanup;
|
|
||||||
oldHead->savedCleanup = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wut_set_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID, newNode);
|
|
||||||
|
|
||||||
return newReent;
|
return newReent;
|
||||||
}
|
}
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
#include "wums_thread_specific.h"
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
extern "C" void OSFatal(const char *);
|
|
||||||
extern "C" void OSReport(const char *, ...);
|
|
||||||
|
|
||||||
typedef struct OSThread {
|
|
||||||
uint8_t other[0x68c];
|
|
||||||
void *reserved[5];
|
|
||||||
} OSThread;
|
|
||||||
|
|
||||||
static_assert(offsetof(OSThread, reserved) == 0x68c, "OSThread: \"reserved\" at wrong offset");
|
|
||||||
static_assert(sizeof(OSThread) == 0x6a0, "OSThread: wrong size");
|
|
||||||
|
|
||||||
extern "C" const char wums_meta_info_dump[];
|
|
||||||
|
|
||||||
void wums_set_thread_specific(__wut_thread_specific_id id, void *value) {
|
|
||||||
OSThread *thread;
|
|
||||||
asm volatile("lwz %0, -0x20(0)"
|
|
||||||
: "=r"(thread)); // OSGetCurrentThread()
|
|
||||||
if (thread != nullptr) {
|
|
||||||
if (id == WUT_THREAD_SPECIFIC_0) {
|
|
||||||
thread->reserved[1] = value;
|
|
||||||
} else if (id == WUT_THREAD_SPECIFIC_1) {
|
|
||||||
thread->reserved[2] = value;
|
|
||||||
} else {
|
|
||||||
OSReport("[%s] wums_set_thread_specific: invalid id\n", wums_meta_info_dump);
|
|
||||||
OSFatal("wut_set_thread_specific: invalid id");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
OSReport("[%s] wums_set_thread_specific: invalid thread\n", wums_meta_info_dump);
|
|
||||||
OSFatal("wums_set_thread_specific: invalid thread");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *wums_get_thread_specific(__wut_thread_specific_id id) {
|
|
||||||
OSThread *thread;
|
|
||||||
asm volatile("lwz %0, -0x20(0)"
|
|
||||||
: "=r"(thread)); // OSGetCurrentThread()
|
|
||||||
if (thread != nullptr) {
|
|
||||||
if (id == WUT_THREAD_SPECIFIC_0) {
|
|
||||||
return thread->reserved[1];
|
|
||||||
} else if (id == WUT_THREAD_SPECIFIC_1) {
|
|
||||||
return thread->reserved[2];
|
|
||||||
} else if ((uint32_t) id == 0x13371337) { // Mechanism to detect if the function was overridden properly
|
|
||||||
return (void *) 0x42424242;
|
|
||||||
} else {
|
|
||||||
OSReport("[%s] wums_get_thread_specific: invalid id\n", wums_meta_info_dump);
|
|
||||||
OSFatal("wums_get_thread_specific: invalid id");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
OSReport("[%s] wums_get_thread_specific: invalid thread\n", wums_meta_info_dump);
|
|
||||||
OSFatal("wums_get_thread_specific: invalid thread\n");
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
typedef enum __wut_thread_specific_id {
|
|
||||||
WUT_THREAD_SPECIFIC_0 = 0,
|
|
||||||
WUT_THREAD_SPECIFIC_1 = 1,
|
|
||||||
} __wut_thread_specific_id;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void wums_set_thread_specific(__wut_thread_specific_id id, void *value);
|
|
||||||
|
|
||||||
void *wums_get_thread_specific(__wut_thread_specific_id id);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
Reference in New Issue
Block a user