From 05b8ce5b5db6c0d95f6fcaf3121b6f96cc2eafd3 Mon Sep 17 00:00:00 2001 From: fincs Date: Sat, 21 Nov 2015 14:14:56 +0100 Subject: [PATCH] Implement devkitARM/newlib lock support & dynamic reent --- libctru/include/3ds/synchronization.h | 10 ++---- libctru/source/internal.h | 5 +++ libctru/source/system/allocateHeaps.c | 2 +- libctru/source/system/appExit.c | 2 +- libctru/source/system/appInit.c | 2 +- libctru/source/system/initArgv.c | 2 +- libctru/source/system/initSystem.c | 28 +++++++--------- libctru/source/system/syscalls.c | 48 +++++++++++++++++++++++++++ 8 files changed, 72 insertions(+), 27 deletions(-) create mode 100644 libctru/source/system/syscalls.c diff --git a/libctru/include/3ds/synchronization.h b/libctru/include/3ds/synchronization.h index 05d94c6..d6dc068 100644 --- a/libctru/include/3ds/synchronization.h +++ b/libctru/include/3ds/synchronization.h @@ -3,17 +3,13 @@ * @brief Provides synchronization locks. */ #pragma once +#include /// A light lock. -typedef s32 LightLock; +typedef _LOCK_T LightLock; /// A recursive lock. -typedef struct -{ - LightLock lock; ///< Inner light lock. - u32 thread_tag; ///< Tag of the thread that currently has the lock. - u32 counter; ///< Lock count. -} RecursiveLock; +typedef _LOCK_RECURSIVE_T RecursiveLock; /// Performs a Data Synchronization Barrier operation. static inline void __dsb(void) diff --git a/libctru/source/internal.h b/libctru/source/internal.h index 7bf09ec..53a4c9f 100644 --- a/libctru/source/internal.h +++ b/libctru/source/internal.h @@ -4,10 +4,15 @@ #include <3ds/svc.h> #include +#define THREADVARS_MAGIC 0x21545624 // !TV$ #define FS_OVERRIDE_MAGIC 0x21465324 // !FS$ +// Keep this structure under 0x80 bytes typedef struct { + // Magic value used to check if the struct is initialized + u32 magic; + // Pointer to this thread's newlib state struct _reent* reent; diff --git a/libctru/source/system/allocateHeaps.c b/libctru/source/system/allocateHeaps.c index 0d7859c..02c9964 100644 --- a/libctru/source/system/allocateHeaps.c +++ b/libctru/source/system/allocateHeaps.c @@ -11,7 +11,7 @@ u32 __ctru_heap_size; u32 __ctru_linear_heap; u32 __ctru_linear_heap_size; -void __attribute__((weak)) __system_allocateHeaps() { +void __attribute__((weak)) __system_allocateHeaps(void) { u32 tmp=0; if(envIsHomebrew()) { diff --git a/libctru/source/system/appExit.c b/libctru/source/system/appExit.c index d2e9d48..9ac6c08 100644 --- a/libctru/source/system/appExit.c +++ b/libctru/source/system/appExit.c @@ -6,7 +6,7 @@ #include <3ds/services/fs.h> #include <3ds/services/hid.h> -void __attribute__((weak)) __appExit() { +void __attribute__((weak)) __appExit(void) { // Exit services sdmcExit(); fsExit(); diff --git a/libctru/source/system/appInit.c b/libctru/source/system/appInit.c index c3213e0..d9c4301 100644 --- a/libctru/source/system/appInit.c +++ b/libctru/source/system/appInit.c @@ -6,7 +6,7 @@ #include <3ds/services/fs.h> #include <3ds/services/hid.h> -void __attribute__((weak)) __appInit() { +void __attribute__((weak)) __appInit(void) { // Initialize services srvInit(); aptInit(); diff --git a/libctru/source/system/initArgv.c b/libctru/source/system/initArgv.c index d566b00..5e61582 100644 --- a/libctru/source/system/initArgv.c +++ b/libctru/source/system/initArgv.c @@ -10,7 +10,7 @@ char** __system_argv; extern char* fake_heap_start; extern char* fake_heap_end; -void __system_initArgv() +void __system_initArgv(void) { int i; const char* arglist = envGetSystemArgList(); diff --git a/libctru/source/system/initSystem.c b/libctru/source/system/initSystem.c index 0d0ac97..236fbd0 100644 --- a/libctru/source/system/initSystem.c +++ b/libctru/source/system/initSystem.c @@ -8,31 +8,27 @@ void (*__system_retAddr)(void); -void __system_allocateHeaps(); -void __system_initArgv(); -void __appInit(); +void __system_initSyscalls(void); +void __system_allocateHeaps(void); +void __system_initArgv(void); +void __appInit(void); - -void __ctru_exit(int rc); -int __libctru_gtod(struct _reent *ptr, struct timeval *tp, struct timezone *tz); - -Result __sync_init(void) __attribute__((weak)); +Result __sync_init(void); void __attribute__((weak)) __libctru_init(void (*retAddr)(void)) { - - // Register newlib exit() syscall - __syscalls.exit = __ctru_exit; - __syscalls.gettod_r = __libctru_gtod; - + // Store the return address __system_retAddr = envIsHomebrew() ? retAddr : NULL; - if (__sync_init) - __sync_init(); + // Initialize the synchronization subsystem + __sync_init(); + // Initialize newlib support system calls + __system_initSyscalls(); + + // Allocate application and linear heaps __system_allocateHeaps(); // Build argc/argv if present __system_initArgv(); - } diff --git a/libctru/source/system/syscalls.c b/libctru/source/system/syscalls.c new file mode 100644 index 0000000..3cb5734 --- /dev/null +++ b/libctru/source/system/syscalls.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include + +#include <3ds/types.h> +#include <3ds/svc.h> +#include <3ds/env.h> +#include <3ds/synchronization.h> +#include "../internal.h" + +void __ctru_exit(int rc); +int __libctru_gtod(struct _reent *ptr, struct timeval *tp, struct timezone *tz); + +static struct _reent* __ctru_get_reent() +{ + ThreadVars* tv = getThreadVars(); + if (tv->magic != THREADVARS_MAGIC) + { + svcBreak(USERBREAK_PANIC); + for (;;); + } + return tv->reent; +} + +void __system_initSyscalls(void) +{ + // Register newlib syscalls + __syscalls.exit = __ctru_exit; + __syscalls.gettod_r = __libctru_gtod; + __syscalls.getreent = __ctru_get_reent; + + // Register locking syscalls + __syscalls.lock_init = LightLock_Init; + __syscalls.lock_acquire = LightLock_Lock; + __syscalls.lock_try_acquire = LightLock_TryLock; + __syscalls.lock_release = LightLock_Unlock; + __syscalls.lock_init_recursive = RecursiveLock_Init; + __syscalls.lock_acquire_recursive = RecursiveLock_Lock; + __syscalls.lock_try_acquire_recursive = RecursiveLock_TryLock; + __syscalls.lock_release_recursive = RecursiveLock_Unlock; + + // Initialize thread vars for the main thread + ThreadVars* tv = getThreadVars(); + tv->magic = THREADVARS_MAGIC; + tv->reent = _impure_ptr; +}