mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-22 21:02:39 +02:00
Mutex bringup
This commit is contained in:
parent
42fbabe9d1
commit
69ce83479a
@ -8,6 +8,9 @@ _start:
|
|||||||
|
|
||||||
.org _start+0x80
|
.org _start+0x80
|
||||||
startup:
|
startup:
|
||||||
|
// save main thread handle
|
||||||
|
mov x27, x1
|
||||||
|
|
||||||
// get aslr base
|
// get aslr base
|
||||||
sub x28, x30, #4
|
sub x28, x30, #4
|
||||||
|
|
||||||
@ -32,7 +35,7 @@ bss_loop:
|
|||||||
bl __nx_dynamic
|
bl __nx_dynamic
|
||||||
|
|
||||||
// initialize system
|
// initialize system
|
||||||
mov x0, x28
|
mov x0, x27
|
||||||
bl __libnx_init
|
bl __libnx_init
|
||||||
|
|
||||||
// call entrypoint
|
// call entrypoint
|
||||||
|
@ -9,6 +9,9 @@ typedef struct {
|
|||||||
// Magic value used to check if the struct is initialized
|
// Magic value used to check if the struct is initialized
|
||||||
u32 magic;
|
u32 magic;
|
||||||
|
|
||||||
|
// Thread handle, for mutexes
|
||||||
|
Handle handle;
|
||||||
|
|
||||||
// Pointer to the current thread (if exists)
|
// Pointer to the current thread (if exists)
|
||||||
Thread* thread_ptr;
|
Thread* thread_ptr;
|
||||||
|
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
// Copyright 2017 plutoo
|
// Copyright 2017 plutoo
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
|
#include "../internal.h"
|
||||||
|
|
||||||
#define HAS_LISTENERS 0x40000000
|
#define HAS_LISTENERS 0x40000000
|
||||||
|
|
||||||
static u32 _GetTag() {
|
static u32 _GetTag() {
|
||||||
// todo: Needs filling in at thread creation.
|
return getThreadVars()->handle;
|
||||||
// todo: Must always be assigned non-zero.
|
|
||||||
return ((u32*)armGetTls()) [0x1FC/4];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mutexLock(Mutex* m) {
|
void mutexLock(Mutex* m) {
|
||||||
u32 self = _GetTag();
|
u32 self = _GetTag();
|
||||||
u32 cur = __sync_val_compare_and_swap(m, 0, self);
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
u32 cur = __sync_val_compare_and_swap((u32*)m, 0, self);
|
||||||
|
|
||||||
if (cur == 0) {
|
if (cur == 0) {
|
||||||
// We won the race!
|
// We won the race!
|
||||||
return;
|
return;
|
||||||
@ -30,21 +30,18 @@ void mutexLock(Mutex* m) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// The flag is not set, we need to set it.
|
// The flag is not set, we need to set it.
|
||||||
u32 old = __sync_val_compare_and_swap(m, cur, cur | HAS_LISTENERS);
|
u32 old = __sync_val_compare_and_swap((u32*)m, cur, cur | HAS_LISTENERS);
|
||||||
|
|
||||||
if (old == cur) {
|
if (old == cur) {
|
||||||
// Flag was set successfully.
|
// Flag was set successfully.
|
||||||
svcArbitrateLock(cur &~ HAS_LISTENERS, (u32*)m, self);
|
svcArbitrateLock(cur &~ HAS_LISTENERS, (u32*)m, self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = __sync_val_compare_and_swap(m, 0, self);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mutexUnlock(Mutex* m) {
|
void mutexUnlock(Mutex* m) {
|
||||||
u32 self = _GetTag();
|
u32 old = __sync_lock_test_and_set((u32*)m, 0);
|
||||||
u32 old = __sync_val_compare_and_swap(m, self, 0);
|
|
||||||
|
|
||||||
if (old & HAS_LISTENERS) {
|
if (old & HAS_LISTENERS) {
|
||||||
svcArbitrateUnlock((u32*)m);
|
svcArbitrateUnlock((u32*)m);
|
||||||
|
@ -104,10 +104,12 @@ SVC_END
|
|||||||
|
|
||||||
SVC_BEGIN svcArbitrateLock
|
SVC_BEGIN svcArbitrateLock
|
||||||
svc 0x1a
|
svc 0x1a
|
||||||
|
ret
|
||||||
SVC_END
|
SVC_END
|
||||||
|
|
||||||
SVC_BEGIN svcArbitrateUnlock
|
SVC_BEGIN svcArbitrateUnlock
|
||||||
svc 0x1b
|
svc 0x1b
|
||||||
|
ret
|
||||||
SVC_END
|
SVC_END
|
||||||
|
|
||||||
SVC_BEGIN svcConnectToNamedPort
|
SVC_BEGIN svcConnectToNamedPort
|
||||||
|
@ -25,6 +25,7 @@ static void _EntryWrap(ThreadEntryArgs* args) {
|
|||||||
tv->thread_ptr = args->t;
|
tv->thread_ptr = args->t;
|
||||||
tv->reent = args->reent;
|
tv->reent = args->reent;
|
||||||
tv->tls_tp = (u8*)args->tls-2*sizeof(void*); // subtract size of Thread Control Block (TCB)
|
tv->tls_tp = (u8*)args->tls-2*sizeof(void*); // subtract size of Thread Control Block (TCB)
|
||||||
|
tv->handle = args->t->handle;
|
||||||
|
|
||||||
// Launch thread entrypoint
|
// Launch thread entrypoint
|
||||||
args->entry(args->arg);
|
args->entry(args->arg);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
void __nx_exit(int rc);
|
void __nx_exit(int rc);
|
||||||
|
|
||||||
void virtmemSetup();
|
void virtmemSetup();
|
||||||
void newlibSetup();
|
void newlibSetup(Handle main_thread);
|
||||||
|
|
||||||
#define INNER_HEAP_SIZE 0x20000
|
#define INNER_HEAP_SIZE 0x20000
|
||||||
__attribute__((weak)) size_t __nx_inner_heap_size = INNER_HEAP_SIZE;
|
__attribute__((weak)) size_t __nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||||
@ -11,12 +11,12 @@ __attribute__((weak)) char __nx_inner_heap[INNER_HEAP_SIZE];
|
|||||||
__attribute__((weak)) size_t __nx_outer_heap_size = 0x2000000*4;//Must be a multiple of 0x2000000.
|
__attribute__((weak)) size_t __nx_outer_heap_size = 0x2000000*4;//Must be a multiple of 0x2000000.
|
||||||
|
|
||||||
static void _SetupHeap() {
|
static void _SetupHeap() {
|
||||||
char* addr;
|
u64 addr;
|
||||||
Result rc = svcSetHeapSize((void**)&addr, __nx_outer_heap_size);
|
Result rc = svcSetHeapSize((void**)&addr, __nx_outer_heap_size);
|
||||||
size_t size = __nx_outer_heap_size;
|
size_t size = __nx_outer_heap_size;
|
||||||
|
|
||||||
if (R_FAILED(rc)) {
|
if (R_FAILED(rc)) {
|
||||||
addr = &__nx_inner_heap[0];
|
addr = (u64) &__nx_inner_heap[0];
|
||||||
size = __nx_inner_heap_size;
|
size = __nx_inner_heap_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,8 +24,8 @@ static void _SetupHeap() {
|
|||||||
extern char* fake_heap_start;
|
extern char* fake_heap_start;
|
||||||
extern char* fake_heap_end;
|
extern char* fake_heap_end;
|
||||||
|
|
||||||
fake_heap_start = addr;
|
fake_heap_start = (char*)addr;
|
||||||
fake_heap_end = addr + size;
|
fake_heap_end = (char*)addr + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __attribute__((weak)) __appInit(void)
|
void __attribute__((weak)) __appInit(void)
|
||||||
@ -46,12 +46,12 @@ void __attribute__((weak)) __appExit(void)
|
|||||||
smExit();
|
smExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __attribute__((weak)) __libnx_init(void)
|
void __attribute__((weak)) __libnx_init(Handle main_thread)
|
||||||
{
|
{
|
||||||
// Called by crt0.
|
// Called by crt0.
|
||||||
|
|
||||||
// Libnx initialization goes here.
|
// Libnx initialization goes here.
|
||||||
newlibSetup();
|
newlibSetup(main_thread);
|
||||||
virtmemSetup();
|
virtmemSetup();
|
||||||
_SetupHeap();
|
_SetupHeap();
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ static struct _reent* __libnx_get_reent() {
|
|||||||
return tv->reent;
|
return tv->reent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void newlibSetup() {
|
void newlibSetup(Handle main_thread) {
|
||||||
// Register newlib syscalls
|
// Register newlib syscalls
|
||||||
__syscalls.exit = __libnx_exit;
|
__syscalls.exit = __libnx_exit;
|
||||||
__syscalls.getreent = __libnx_get_reent;
|
__syscalls.getreent = __libnx_get_reent;
|
||||||
@ -37,6 +37,7 @@ void newlibSetup() {
|
|||||||
tv->thread_ptr = NULL;
|
tv->thread_ptr = NULL;
|
||||||
tv->reent = _impure_ptr;
|
tv->reent = _impure_ptr;
|
||||||
tv->tls_tp = __tls_start-2*sizeof(void*); // subtract size of Thread Control Block (TCB)
|
tv->tls_tp = __tls_start-2*sizeof(void*); // subtract size of Thread Control Block (TCB)
|
||||||
|
tv->handle = main_thread;
|
||||||
|
|
||||||
u32 tls_size = __tdata_lma_end - __tdata_lma;
|
u32 tls_size = __tdata_lma_end - __tdata_lma;
|
||||||
if (tls_size)
|
if (tls_size)
|
||||||
|
Loading…
Reference in New Issue
Block a user