mirror of
https://github.com/wiiu-env/WiiUModuleSystem.git
synced 2024-11-22 01:39:19 +01:00
Fix reent usage for modules
This commit is contained in:
parent
a137f10ee9
commit
313f281ee8
2
Makefile
2
Makefile
@ -30,7 +30,7 @@ CFLAGS := -g -Wall -Werror -save-temps \
|
||||
|
||||
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -D__WUM__
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -std=gnu++17
|
||||
CXXFLAGS := $(CFLAGS) -fno-exceptions -fno-rtti -std=gnu++20
|
||||
|
||||
ASFLAGS := -g $(MACHDEP)
|
||||
|
||||
|
@ -39,9 +39,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define WUMS_MODULE_EXPORT_NAME(x) \
|
||||
WUMS_META(export_name, x); \
|
||||
WUMS_META(wums, "0.3.2"); \
|
||||
#define WUMS_VERSION "0.3.2"
|
||||
|
||||
#define WUMS_MODULE_EXPORT_NAME(__module_name) \
|
||||
WUMS_META(export_name, __module_name); \
|
||||
WUMS_META(wums, WUMS_VERSION); \
|
||||
WUMS_USE_WUT_MALLOC(); \
|
||||
WUMS_USE_WUT_SOCKETS(); \
|
||||
WUMS_USE_WUT_NEWLIB(); \
|
||||
@ -50,11 +52,15 @@ extern "C" {
|
||||
WUMS___FINI_WRAPPER(); \
|
||||
__EXTERN_C_MACRO void abort(); \
|
||||
void abort() { \
|
||||
OSFatal(x ": abort() called. Uncaught exception?"); \
|
||||
OSFatal(__module_name ": abort() called. Uncaught exception?"); \
|
||||
while (1) \
|
||||
; \
|
||||
} \
|
||||
WUMS_META(buildtimestamp, __DATE__ " " __TIME__)
|
||||
WUMS_META(buildtimestamp, __DATE__ " " __TIME__); \
|
||||
extern const char wums_meta_info_dump[] WUMS_SECTION("meta"); \
|
||||
const char wums_meta_info_dump[] = "(module: " __module_name ";" \
|
||||
"wums " WUMS_VERSION ";" \
|
||||
"buildtime: " __DATE__ " " __TIME__ ")"
|
||||
|
||||
#define WUMS_MODULE_AUTHOR(x) WUMS_META(author, x)
|
||||
#define WUMS_MODULE_VERSION(x) WUMS_META(version, x)
|
||||
|
@ -1,27 +0,0 @@
|
||||
int main(int argc, char **argv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern __attribute__((weak)) void __wut_socket_init_devoptab();
|
||||
extern __attribute__((weak)) void __wut_socket_fini_devoptab();
|
||||
|
||||
static int __wut_socket_devoptab_added = 0;
|
||||
|
||||
extern void socket_lib_init();
|
||||
|
||||
void __attribute__((weak)) __init_wut_socket() {
|
||||
if (!&__wut_socket_init_devoptab) return;
|
||||
if (!__wut_socket_devoptab_added) {
|
||||
socket_lib_init();
|
||||
__wut_socket_init_devoptab();
|
||||
__wut_socket_devoptab_added = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __fini_wut_socket() {
|
||||
if (!&__wut_socket_init_devoptab || !&__wut_socket_fini_devoptab) return;
|
||||
if (__wut_socket_devoptab_added) {
|
||||
__wut_socket_fini_devoptab();
|
||||
__wut_socket_devoptab_added = 0;
|
||||
}
|
||||
}
|
54
libraries/libwums/crt.cpp
Normal file
54
libraries/libwums/crt.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include "wums_reent.h"
|
||||
#include "wums_thread_specific.h"
|
||||
|
||||
extern "C" void OSFatal(const char *);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
OSFatal("This file needs to be run with the Wii U Module Loader.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" __attribute__((weak)) void __wut_socket_init_devoptab();
|
||||
|
||||
extern "C" __attribute__((weak)) void __wut_socket_fini_devoptab();
|
||||
|
||||
static int __wut_socket_devoptab_added = 0;
|
||||
|
||||
extern "C" __attribute__((weak)) void socket_lib_init();
|
||||
|
||||
extern "C" void __attribute__((weak)) __init_wut_socket();
|
||||
|
||||
void __attribute__((weak)) __init_wut_socket() {
|
||||
if (!&__wut_socket_init_devoptab || !&socket_lib_init) return;
|
||||
if (!__wut_socket_devoptab_added) {
|
||||
socket_lib_init();
|
||||
__wut_socket_init_devoptab();
|
||||
__wut_socket_devoptab_added = 1;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void __attribute__((weak)) __fini_wut_socket();
|
||||
|
||||
void __attribute__((weak)) __fini_wut_socket() {
|
||||
if (!&__wut_socket_init_devoptab || !&__wut_socket_fini_devoptab) return;
|
||||
if (__wut_socket_devoptab_added) {
|
||||
__wut_socket_fini_devoptab();
|
||||
__wut_socket_devoptab_added = 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct _reent *__getreent(void) {
|
||||
return __wums_getreent();
|
||||
}
|
||||
|
||||
extern "C" void __attribute__((weak)) wut_set_thread_specific(__wut_thread_specific_id id, void *value);
|
||||
|
||||
void wut_set_thread_specific(__wut_thread_specific_id id, void *value) {
|
||||
return wums_set_thread_specific(id, value);
|
||||
}
|
||||
|
||||
extern "C" void *__attribute__((weak)) 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);
|
||||
}
|
78
libraries/libwums/wums_reent.cpp
Normal file
78
libraries/libwums/wums_reent.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
#include "wums_thread_specific.h"
|
||||
#include <cstring>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define __WUMS_CONTEXT_THREAD_SPECIFIC_ID WUT_THREAD_SPECIFIC_1
|
||||
|
||||
typedef uint32_t OSThread;
|
||||
|
||||
extern const char wums_meta_info_dump[];
|
||||
|
||||
extern void OSFatal(const char *);
|
||||
extern void OSReport(const char *, ...);
|
||||
|
||||
extern OSThread *OSGetCurrentThread();
|
||||
|
||||
typedef void (*OSThreadCleanupCallbackFn)(OSThread *thread, void *stack);
|
||||
|
||||
OSThreadCleanupCallbackFn
|
||||
OSSetThreadCleanupCallback(OSThread *thread,
|
||||
OSThreadCleanupCallbackFn callback);
|
||||
|
||||
|
||||
struct __wums_thread_context {
|
||||
struct _reent reent;
|
||||
OSThreadCleanupCallbackFn savedCleanup;
|
||||
};
|
||||
|
||||
static void
|
||||
__wums_thread_cleanup(OSThread *thread,
|
||||
void *stack) {
|
||||
struct __wums_thread_context *context;
|
||||
|
||||
context = (struct __wums_thread_context *) wums_get_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID);
|
||||
if (!context || &context->reent == _GLOBAL_REENT) {
|
||||
OSReport("[%s] __wums_thread_cleanup: Context was NULL or reent was global\n", wums_meta_info_dump);
|
||||
OSFatal("__wums_thread_cleanup: Context was NULL or reent was global");
|
||||
}
|
||||
|
||||
if (context->savedCleanup) {
|
||||
context->savedCleanup(thread, stack);
|
||||
}
|
||||
|
||||
_reclaim_reent(&context->reent);
|
||||
|
||||
// Use global reent during free since the current reent is getting freed
|
||||
wums_set_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID, _GLOBAL_REENT);
|
||||
|
||||
free(context);
|
||||
|
||||
wums_set_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID, NULL);
|
||||
}
|
||||
|
||||
struct _reent *
|
||||
__wums_getreent(void) {
|
||||
struct __wums_thread_context *context;
|
||||
|
||||
context = (struct __wums_thread_context *) wums_get_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID);
|
||||
if (!context) {
|
||||
// Temporarily use global reent during context allocation
|
||||
wums_set_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID, _GLOBAL_REENT);
|
||||
|
||||
context = (struct __wums_thread_context *) malloc(sizeof(*context));
|
||||
if (!context) {
|
||||
OSReport("[%s] __wums_getreent: Failed to allocate reent context\n", wums_meta_info_dump);
|
||||
OSFatal("__wums_getreent: Failed to allocate reent context");
|
||||
wums_set_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_REENT_INIT_PTR(&context->reent);
|
||||
context->savedCleanup = OSSetThreadCleanupCallback(OSGetCurrentThread(), &__wums_thread_cleanup);
|
||||
|
||||
wums_set_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID, context);
|
||||
}
|
||||
|
||||
return &context->reent;
|
||||
}
|
3
libraries/libwums/wums_reent.h
Normal file
3
libraries/libwums/wums_reent.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
struct _reent *__wums_getreent();
|
55
libraries/libwums/wums_thread_specific.cpp
Normal file
55
libraries/libwums/wums_thread_specific.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#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[3] = value;
|
||||
} else if (id == WUT_THREAD_SPECIFIC_1) {
|
||||
thread->reserved[4] = 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[3];
|
||||
} else if (id == WUT_THREAD_SPECIFIC_1) {
|
||||
return thread->reserved[4];
|
||||
} 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;
|
||||
}
|
18
libraries/libwums/wums_thread_specific.h
Normal file
18
libraries/libwums/wums_thread_specific.h
Normal file
@ -0,0 +1,18 @@
|
||||
#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
|
Loading…
Reference in New Issue
Block a user