Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ include $(TOPDIR)/share/wums_rules

export WUMS_MAJOR := 0
export WUMS_MINOR := 3
export WUMS_PATCH := 5
export WUMS_PATCH := 6

VERSION := $(WUMS_MAJOR).$(WUMS_MINOR).$(WUMS_PATCH)

Expand Down Expand Up @@ -102,10 +102,10 @@ lib:
@[ -d $@ ] || mkdir -p $@

release:
@[ -d $@ ] || mkdir -p $@
@$(shell [ ! -d 'release' ] && mkdir -p 'release')

debug:
@[ -d $@ ] || mkdir -p $@
@$(shell [ ! -d 'debug' ] && mkdir -p 'debug')

lib/libwums.a : lib release $(SOURCES) $(INCLUDES)
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
Expand Down
8 changes: 4 additions & 4 deletions include/wums/defines/module_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ typedef struct module_information_single_t {
uint32_t number_export_entries;
hook_data_t * hook_entries;
uint32_t number_hook_entries;
uint32_t bssAddr;
uint32_t bssSize;
uint32_t sbssAddr;
uint32_t sbssSize;
uint32_t bssAddr; // deprecated
uint32_t bssSize; // deprecated
uint32_t sbssAddr; // deprecated
uint32_t sbssSize; // deprecated
uint32_t startAddress;
uint32_t endAddress;
uint32_t entrypoint;
Expand Down
13 changes: 12 additions & 1 deletion include/wums/hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include "common.h"
#include "defines/module_defines.h"
#include "reent_internal.h"

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -68,7 +69,9 @@ typedef enum wums_hook_type_t {
WUMS_HOOK_GET_CUSTOM_RPL_ALLOCATOR, // for internal usage only
WUMS_HOOK_CLEAR_ALLOCATED_RPL_MEMORY, // for internal usage only
// 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;

typedef uint32_t (*WUMSRPLAllocatorAllocFn)(int32_t size, int32_t align, void **outAddr);
Expand Down Expand Up @@ -196,6 +199,14 @@ typedef struct wums_relocs_done_args_t {
} \
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() \
__EXTERN_C_MACRO void __init_wut_socket(); \
WUMS_HOOK_EX(WUMS_HOOK_INIT_WUT_SOCKETS, __init_wut_socket); \
Expand Down
3 changes: 2 additions & 1 deletion include/wums/meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
extern "C" {
#endif

#define WUMS_VERSION "0.3.5"
#define WUMS_VERSION "0.3.6"

#define WUMS_MODULE_EXPORT_NAME(__module_name) \
WUMS_META(export_name, __module_name); \
Expand All @@ -50,6 +50,7 @@ extern "C" {
WUMS_USE_WUT_THREAD(); \
WUMS___INIT_WRAPPER(); \
WUMS___FINI_WRAPPER(); \
WUMS_INIT_REENT_FUNCTIONS(); \
WUMS_META(buildtimestamp, __DATE__ " " __TIME__); \
extern const char wums_meta_module_name[] WUMS_SECTION("meta"); \
const char wums_meta_module_name[] = __module_name; \
Expand Down
25 changes: 25 additions & 0 deletions include/wums/reent_internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef bool (*WUMSReent_GetReentContext)(const void *moduleId, void **outPtr);
typedef bool (*WUMSReent_AddReentContext)(const void *moduleId, void *reentPtr, void (*cleanupFn)(void *));

typedef uint32_t WUMS_REENT_API_VERSION;

#define WUMS_REENT_CUR_API_VERSION 0x02

typedef struct wums_loader_init_reent_args_t_ {
WUMS_REENT_API_VERSION version;
WUMSReent_GetReentContext get_context_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
19 changes: 19 additions & 0 deletions include/wums/wums_debug.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

extern "C" void OSReport(const char *fmt, ...);

#ifdef __cplusplus
extern "C" {
#endif
extern const char wums_meta_info_dump[];
#ifdef __cplusplus
}
#endif

#ifdef DEBUG
#define WUMS_DEBUG_REPORT(fmt, ...) OSReport("[%s] " fmt, wums_meta_info_dump, ##__VA_ARGS__)
#else
#define WUMS_DEBUG_REPORT(fmt, ...)
#endif

#define WUMS_DEBUG_WARN(fmt, ...) OSReport("\033[33m[%s] " fmt "\033[0m", wums_meta_info_dump, ##__VA_ARGS__)
23 changes: 16 additions & 7 deletions libraries/libwums/crt.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "wums/wums_debug.h"
#include "wums_reent.h"
#include "wums_thread_specific.h"

#include <cstdio>
#include <cstring>

Expand Down Expand Up @@ -43,16 +44,22 @@ 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);
}
typedef enum __wut_thread_specific_id {
WUT_THREAD_SPECIFIC_0 = 0,
WUT_THREAD_SPECIFIC_1 = 1,
} __wut_thread_specific_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) {
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[];
Expand Down Expand Up @@ -100,6 +107,8 @@ __assert_func(const char *file,
}

OSFatal(buffer);
while (true)
;
/* NOTREACHED */
}

Expand Down
129 changes: 75 additions & 54 deletions libraries/libwums/wums_reent.cpp
Original file line number Diff line number Diff line change
@@ -1,78 +1,99 @@
#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;
#include "wums_reent.h"

extern const char wums_meta_info_dump[];
#include "wums/hooks.h"
#include "wums/reent_internal.h"
#include "wums/wums_debug.h"

extern "C" void OSFatal(const char *);
extern "C" void OSReport(const char *, ...);
#include <stdlib.h>

extern "C" OSThread *OSGetCurrentThread();
extern "C" void OSFatal(const char *format, ...);
extern "C" void *OSGetCurrentThread();

typedef void (*OSThreadCleanupCallbackFn)(OSThread *thread, void *stack);
typedef void *(*MEMAllocFromDefaultHeapFn)(uint32_t size);
typedef void *(*MEMAllocFromDefaultHeapExFn)(uint32_t size, int32_t alignment);
typedef void (*MEMFreeToDefaultHeapFn)(void *ptr);

extern "C" OSThreadCleanupCallbackFn
OSSetThreadCleanupCallback(OSThread *thread,
OSThreadCleanupCallbackFn callback);
extern MEMAllocFromDefaultHeapFn MEMAllocFromDefaultHeap;
extern MEMAllocFromDefaultHeapExFn MEMAllocFromDefaultHeapEx;
extern MEMFreeToDefaultHeapFn MEMFreeToDefaultHeap;


struct __wums_thread_context {
struct _reent reent;
OSThreadCleanupCallbackFn savedCleanup;
struct wums_loader_init_reent_args_t {
WUMSReent_GetReentContext get_context_ptr = nullptr;
WUMSReent_AddReentContext add_reent_context_ptr = nullptr;
};

static void
__wums_thread_cleanup(OSThread *thread,
void *stack) {
struct __wums_thread_context *context;
static wums_loader_init_reent_args_t __internal_functions = {};

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");
void WUMSReentAPI_InitInternal(wums_loader_init_reent_args_t_ args) {
if (args.version > WUMS_REENT_CUR_API_VERSION) {
OSFatal("Incompatible reent api version");
return;
}
WUMS_DEBUG_REPORT("WUMSReentAPI_InitInternal: Initializing reent module\n");

if (context->savedCleanup) {
context->savedCleanup(thread, stack);
}
__internal_functions.get_context_ptr = args.get_context_ptr;
__internal_functions.add_reent_context_ptr = args.add_reent_context_ptr;
}

// use variable in the .data section as unique module id
static const int sReentModuleId = 0;

_reclaim_reent(&context->reent);
bool wums_backend_get_context(const void *id, void **outPtr) {
return __internal_functions.get_context_ptr(id, outPtr);
}

// Use global reent during free since the current reent is getting freed
wums_set_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID, _GLOBAL_REENT);
bool wums_backend_register_context(const void *moduleId, void *reentPtr, void (*cleanupFn)(void *)) {
return __internal_functions.add_reent_context_ptr(moduleId, reentPtr, cleanupFn);
}

free(context);
static void reclaim_reent_trampoline(void *payload) {
WUMS_DEBUG_REPORT("reclaim_reent_trampoline: Destroying reent payload: %p\n", payload);

wums_set_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID, NULL);
if (payload) {
auto *reentPtr = static_cast<_reent *>(payload);
_reclaim_reent(reentPtr);

// Make sure to use MEMFreeToDefaultHeap
MEMFreeToDefaultHeap(reentPtr);
}
}

struct _reent *
__wums_getreent(void) {
struct __wums_thread_context *context;
struct _reent *__wums_getreent() {
if (!OSGetCurrentThread()) {
return _GLOBAL_REENT;
}
void *existingCtx = nullptr;
if (!wums_backend_get_context(&sReentModuleId, &existingCtx)) {
return _GLOBAL_REENT;
}
// if non-null we can use it
if (existingCtx) {
return static_cast<_reent *>(existingCtx);
}

// Use `MEMAllocFromDefaultHeap` to avoid creating a new reent for allocating the reent
auto *newReent = static_cast<struct _reent *>(MEMAllocFromDefaultHeap(sizeof(struct _reent)));
if (!newReent) {
return _GLOBAL_REENT;
}

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);
WUMS_DEBUG_REPORT("Allocated context! for thread %p: %p\n", OSGetCurrentThread(), newReent);

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(newReent);

_REENT_INIT_PTR(&context->reent);
context->savedCleanup = OSSetThreadCleanupCallback(OSGetCurrentThread(), &__wums_thread_cleanup);
const bool result = wums_backend_register_context(
&sReentModuleId,
newReent,
reclaim_reent_trampoline);

wums_set_thread_specific(__WUMS_CONTEXT_THREAD_SPECIFIC_ID, context);
if (!result) {
WUMS_DEBUG_WARN("Failed to register context for thread %p\n", OSGetCurrentThread());
_reclaim_reent(newReent);
// Make sure to call the free function
MEMFreeToDefaultHeap(newReent);
return _GLOBAL_REENT;
}

return &context->reent;
}
return newReent;
}
57 changes: 0 additions & 57 deletions libraries/libwums/wums_thread_specific.cpp

This file was deleted.

Loading
Loading