Implement devkitARM/newlib lock support & dynamic reent

This commit is contained in:
fincs 2015-11-21 14:14:56 +01:00
parent 1c18b0bffe
commit 05b8ce5b5d
8 changed files with 72 additions and 27 deletions

View File

@ -3,17 +3,13 @@
* @brief Provides synchronization locks. * @brief Provides synchronization locks.
*/ */
#pragma once #pragma once
#include <sys/lock.h>
/// A light lock. /// A light lock.
typedef s32 LightLock; typedef _LOCK_T LightLock;
/// A recursive lock. /// A recursive lock.
typedef struct typedef _LOCK_RECURSIVE_T RecursiveLock;
{
LightLock lock; ///< Inner light lock.
u32 thread_tag; ///< Tag of the thread that currently has the lock.
u32 counter; ///< Lock count.
} RecursiveLock;
/// Performs a Data Synchronization Barrier operation. /// Performs a Data Synchronization Barrier operation.
static inline void __dsb(void) static inline void __dsb(void)

View File

@ -4,10 +4,15 @@
#include <3ds/svc.h> #include <3ds/svc.h>
#include <sys/reent.h> #include <sys/reent.h>
#define THREADVARS_MAGIC 0x21545624 // !TV$
#define FS_OVERRIDE_MAGIC 0x21465324 // !FS$ #define FS_OVERRIDE_MAGIC 0x21465324 // !FS$
// Keep this structure under 0x80 bytes
typedef struct typedef struct
{ {
// Magic value used to check if the struct is initialized
u32 magic;
// Pointer to this thread's newlib state // Pointer to this thread's newlib state
struct _reent* reent; struct _reent* reent;

View File

@ -11,7 +11,7 @@ u32 __ctru_heap_size;
u32 __ctru_linear_heap; u32 __ctru_linear_heap;
u32 __ctru_linear_heap_size; u32 __ctru_linear_heap_size;
void __attribute__((weak)) __system_allocateHeaps() { void __attribute__((weak)) __system_allocateHeaps(void) {
u32 tmp=0; u32 tmp=0;
if(envIsHomebrew()) { if(envIsHomebrew()) {

View File

@ -6,7 +6,7 @@
#include <3ds/services/fs.h> #include <3ds/services/fs.h>
#include <3ds/services/hid.h> #include <3ds/services/hid.h>
void __attribute__((weak)) __appExit() { void __attribute__((weak)) __appExit(void) {
// Exit services // Exit services
sdmcExit(); sdmcExit();
fsExit(); fsExit();

View File

@ -6,7 +6,7 @@
#include <3ds/services/fs.h> #include <3ds/services/fs.h>
#include <3ds/services/hid.h> #include <3ds/services/hid.h>
void __attribute__((weak)) __appInit() { void __attribute__((weak)) __appInit(void) {
// Initialize services // Initialize services
srvInit(); srvInit();
aptInit(); aptInit();

View File

@ -10,7 +10,7 @@ char** __system_argv;
extern char* fake_heap_start; extern char* fake_heap_start;
extern char* fake_heap_end; extern char* fake_heap_end;
void __system_initArgv() void __system_initArgv(void)
{ {
int i; int i;
const char* arglist = envGetSystemArgList(); const char* arglist = envGetSystemArgList();

View File

@ -8,31 +8,27 @@
void (*__system_retAddr)(void); void (*__system_retAddr)(void);
void __system_allocateHeaps(); void __system_initSyscalls(void);
void __system_initArgv(); void __system_allocateHeaps(void);
void __appInit(); void __system_initArgv(void);
void __appInit(void);
Result __sync_init(void);
void __ctru_exit(int rc);
int __libctru_gtod(struct _reent *ptr, struct timeval *tp, struct timezone *tz);
Result __sync_init(void) __attribute__((weak));
void __attribute__((weak)) __libctru_init(void (*retAddr)(void)) void __attribute__((weak)) __libctru_init(void (*retAddr)(void))
{ {
// Store the return address
// Register newlib exit() syscall
__syscalls.exit = __ctru_exit;
__syscalls.gettod_r = __libctru_gtod;
__system_retAddr = envIsHomebrew() ? retAddr : NULL; __system_retAddr = envIsHomebrew() ? retAddr : NULL;
if (__sync_init) // Initialize the synchronization subsystem
__sync_init(); __sync_init();
// Initialize newlib support system calls
__system_initSyscalls();
// Allocate application and linear heaps
__system_allocateHeaps(); __system_allocateHeaps();
// Build argc/argv if present // Build argc/argv if present
__system_initArgv(); __system_initArgv();
} }

View File

@ -0,0 +1,48 @@
#include <sys/iosupport.h>
#include <sys/time.h>
#include <sys/lock.h>
#include <sys/reent.h>
#include <string.h>
#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;
}