mirror of
https://github.com/wiiu-env/WiiUPluginSystem.git
synced 2025-01-25 23:41:29 +01:00
Fix reent support
This commit is contained in:
parent
66f48504d3
commit
b2ae19f572
@ -38,9 +38,10 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WUPS_PLUGIN_NAME(x) \
|
#define WUPS_VERSION_STR "0.7.1"
|
||||||
WUPS_META(name, x); \
|
#define WUPS_PLUGIN_NAME(__plugin_name) \
|
||||||
WUPS_META(wups, "0.7.1"); \
|
WUPS_META(name, __plugin_name); \
|
||||||
|
WUPS_META(wups, WUPS_VERSION_STR); \
|
||||||
WUPS_USE_WUT_MALLOC(); \
|
WUPS_USE_WUT_MALLOC(); \
|
||||||
WUPS_USE_WUT_SOCKETS(); \
|
WUPS_USE_WUT_SOCKETS(); \
|
||||||
WUPS_USE_WUT_NEWLIB(); \
|
WUPS_USE_WUT_NEWLIB(); \
|
||||||
@ -50,11 +51,15 @@ extern "C" {
|
|||||||
__EXTERN_C_MACRO void abort(); \
|
__EXTERN_C_MACRO void abort(); \
|
||||||
__EXTERN_C_MACRO void OSFatal(const char *msg); \
|
__EXTERN_C_MACRO void OSFatal(const char *msg); \
|
||||||
void abort() { \
|
void abort() { \
|
||||||
OSFatal(x ": abort() called. Uncaught exception?"); \
|
OSFatal(__plugin_name ": abort() called. Uncaught exception?"); \
|
||||||
while (1) \
|
while (1) \
|
||||||
; \
|
; \
|
||||||
} \
|
} \
|
||||||
WUPS_META(buildtimestamp, __DATE__ " " __TIME__);
|
WUPS_META(buildtimestamp, __DATE__ " " __TIME__); \
|
||||||
|
extern const char wups_meta_info_dump[] WUPS_SECTION("meta"); \
|
||||||
|
const char wups_meta_info_dump[] = "(plugin: " __plugin_name ";" \
|
||||||
|
"wups " WUPS_VERSION_STR ";" \
|
||||||
|
"buildtime: " __DATE__ " " __TIME__ ")"
|
||||||
|
|
||||||
#define WUPS_PLUGIN_AUTHOR(x) WUPS_META(author, x)
|
#define WUPS_PLUGIN_AUTHOR(x) WUPS_META(author, x)
|
||||||
#define WUPS_PLUGIN_VERSION(x) WUPS_META(version, x)
|
#define WUPS_PLUGIN_VERSION(x) WUPS_META(version, x)
|
||||||
|
@ -1,19 +1,26 @@
|
|||||||
extern "C" void OSFatal(const char *msg);
|
#include "wups_reent.h"
|
||||||
|
#include "wups_thread_specific.h"
|
||||||
|
#include <cstddef>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
extern "C" void OSFatal(const char *);
|
||||||
|
|
||||||
extern "C" void __wups_start() {
|
extern "C" void __wups_start() {
|
||||||
OSFatal("This file needs to be run with the Wii U Plugin System.");
|
OSFatal("This file needs to be run with the Wii U Plugin System.");
|
||||||
}
|
}
|
||||||
|
|
||||||
extern __attribute__((weak)) void __wut_socket_init_devoptab();
|
extern "C" __attribute__((weak)) void __wut_socket_init_devoptab();
|
||||||
|
|
||||||
extern __attribute__((weak)) void __wut_socket_fini_devoptab();
|
extern "C" __attribute__((weak)) void __wut_socket_fini_devoptab();
|
||||||
|
|
||||||
static int __wut_socket_devoptab_added = 0;
|
static int __wut_socket_devoptab_added = 0;
|
||||||
|
|
||||||
extern void socket_lib_init();
|
extern "C" __attribute__((weak)) void socket_lib_init();
|
||||||
|
|
||||||
|
extern "C" void __attribute__((weak)) __init_wut_socket();
|
||||||
|
|
||||||
void __attribute__((weak)) __init_wut_socket() {
|
void __attribute__((weak)) __init_wut_socket() {
|
||||||
if (!&__wut_socket_init_devoptab) return;
|
if (!&__wut_socket_init_devoptab || !&socket_lib_init) return;
|
||||||
if (!__wut_socket_devoptab_added) {
|
if (!__wut_socket_devoptab_added) {
|
||||||
socket_lib_init();
|
socket_lib_init();
|
||||||
__wut_socket_init_devoptab();
|
__wut_socket_init_devoptab();
|
||||||
@ -21,6 +28,8 @@ void __attribute__((weak)) __init_wut_socket() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void __attribute__((weak)) __fini_wut_socket();
|
||||||
|
|
||||||
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_init_devoptab || !&__wut_socket_fini_devoptab) return;
|
||||||
if (__wut_socket_devoptab_added) {
|
if (__wut_socket_devoptab_added) {
|
||||||
@ -28,3 +37,19 @@ void __attribute__((weak)) __fini_wut_socket() {
|
|||||||
__wut_socket_devoptab_added = 0;
|
__wut_socket_devoptab_added = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" struct _reent *__getreent(void) {
|
||||||
|
return __wups_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 wups_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 wups_get_thread_specific(id);
|
||||||
|
}
|
||||||
|
81
libraries/libwups/wups_reent.cpp
Normal file
81
libraries/libwups/wups_reent.cpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#include "wups_reent.h"
|
||||||
|
#include "wups_thread_specific.h"
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define __WUPS_CONTEXT_THREAD_SPECIFIC_ID WUT_THREAD_SPECIFIC_1
|
||||||
|
|
||||||
|
extern "C" __attribute__((weak)) void wut_set_thread_specific(__wut_thread_specific_id id, void *value);
|
||||||
|
extern "C" __attribute__((weak)) void *wut_get_thread_specific(__wut_thread_specific_id);
|
||||||
|
|
||||||
|
typedef uint32_t OSThread;
|
||||||
|
|
||||||
|
extern const char wups_meta_info_dump[];
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
struct __wups_thread_context {
|
||||||
|
struct _reent reent;
|
||||||
|
OSThreadCleanupCallbackFn savedCleanup;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
__wups_thread_cleanup(OSThread *thread,
|
||||||
|
void *stack) {
|
||||||
|
struct __wups_thread_context *context;
|
||||||
|
|
||||||
|
context = (struct __wups_thread_context *) wut_get_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID);
|
||||||
|
if (!context || &context->reent == _GLOBAL_REENT) {
|
||||||
|
OSReport("[%s] __wups_thread_cleanup: Context was NULL or reent was global\n", wups_meta_info_dump);
|
||||||
|
OSFatal("__wups_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
|
||||||
|
wut_set_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID, _GLOBAL_REENT);
|
||||||
|
|
||||||
|
free(context);
|
||||||
|
|
||||||
|
wut_set_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _reent *
|
||||||
|
__wups_getreent(void) {
|
||||||
|
struct __wups_thread_context *context;
|
||||||
|
|
||||||
|
context = (struct __wups_thread_context *) wut_get_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID);
|
||||||
|
if (!context) {
|
||||||
|
// Temporarily use global reent during context allocation
|
||||||
|
wut_set_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID, _GLOBAL_REENT);
|
||||||
|
|
||||||
|
context = (struct __wups_thread_context *) malloc(sizeof(*context));
|
||||||
|
if (!context) {
|
||||||
|
OSReport("[%s] __wups_getreent: Failed to allocate reent context\n", wups_meta_info_dump);
|
||||||
|
OSFatal("__wups_getreent: Failed to allocate reent context");
|
||||||
|
wut_set_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_REENT_INIT_PTR(&context->reent);
|
||||||
|
context->savedCleanup = OSSetThreadCleanupCallback(OSGetCurrentThread(), &__wups_thread_cleanup);
|
||||||
|
|
||||||
|
wut_set_thread_specific(__WUPS_CONTEXT_THREAD_SPECIFIC_ID, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return &context->reent;
|
||||||
|
}
|
3
libraries/libwups/wups_reent.h
Normal file
3
libraries/libwups/wups_reent.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct _reent *__wups_getreent();
|
55
libraries/libwups/wups_thread_specific.cpp
Normal file
55
libraries/libwups/wups_thread_specific.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#include "wups_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 wups_meta_info_dump[];
|
||||||
|
|
||||||
|
void wups_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] wups_set_thread_specific: invalid id\n", wups_meta_info_dump);
|
||||||
|
OSFatal("wups_set_thread_specific: invalid id");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
OSReport("[%s] wups_set_thread_specific: invalid thread\n", wups_meta_info_dump);
|
||||||
|
OSFatal("wups_set_thread_specific: invalid thread");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *wups_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] wups_get_thread_specific: invalid id\n", wups_meta_info_dump);
|
||||||
|
OSFatal("wups_get_thread_specific: invalid id");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
OSReport("[%s] wups_get_thread_specific: invalid thread\n", wups_meta_info_dump);
|
||||||
|
OSFatal("wups_get_thread_specific: invalid thread\n");
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
18
libraries/libwups/wups_thread_specific.h
Normal file
18
libraries/libwups/wups_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 wups_set_thread_specific(__wut_thread_specific_id id, void *value);
|
||||||
|
|
||||||
|
void *wups_get_thread_specific(__wut_thread_specific_id id);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user