Integrate newlib locks with libnx (R)Mutex (untested, incomplete)

This commit is contained in:
fincs 2017-11-08 18:54:23 +01:00
parent 757349c5c4
commit f27685b7b3
4 changed files with 27 additions and 31 deletions

View File

@ -1,13 +1,9 @@
// Copyright 2017 plutoo // Copyright 2017 plutoo
typedef struct { #pragma once
u32 Tag; #include <sys/lock.h>
} Mutex;
typedef struct { typedef _LOCK_T Mutex;
u32 Owner; typedef _LOCK_RECURSIVE_T RMutex;
Mutex Lock;
size_t Count;
} RMutex;
void mutexLock(Mutex* m); void mutexLock(Mutex* m);
void mutexUnlock(Mutex* m); void mutexUnlock(Mutex* m);

View File

@ -11,7 +11,7 @@ static u32 _GetTag() {
void mutexLock(Mutex* m) { void mutexLock(Mutex* m) {
u32 self = _GetTag(); u32 self = _GetTag();
u32 cur = __sync_val_compare_and_swap(&m->Tag, 0, self); u32 cur = __sync_val_compare_and_swap(m, 0, self);
while (1) { while (1) {
if (cur == 0) { if (cur == 0) {
@ -26,44 +26,44 @@ void mutexLock(Mutex* m) {
if (cur & HAS_LISTENERS) { if (cur & HAS_LISTENERS) {
// The flag is already set, we can use the syscall. // The flag is already set, we can use the syscall.
svcArbitrateLock(cur &~ HAS_LISTENERS, &m->Tag, self); svcArbitrateLock(cur &~ HAS_LISTENERS, (u32*)m, self);
} }
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->Tag, cur, cur | HAS_LISTENERS); u32 old = __sync_val_compare_and_swap(m, cur, cur | HAS_LISTENERS);
if (old == cur) { if (old == cur) {
// Flag was set successfully. // Flag was set successfully.
svcArbitrateLock(cur &~ HAS_LISTENERS, &m->Tag, self); svcArbitrateLock(cur &~ HAS_LISTENERS, (u32*)m, self);
} }
} }
cur = __sync_val_compare_and_swap(&m->Tag, 0, self); cur = __sync_val_compare_and_swap(m, 0, self);
} }
} }
void mutexUnlock(Mutex* m) { void mutexUnlock(Mutex* m) {
u32 self = _GetTag(); u32 self = _GetTag();
u32 old = __sync_val_compare_and_swap(&m->Tag, self, 0); u32 old = __sync_val_compare_and_swap(m, self, 0);
if (old & HAS_LISTENERS) { if (old & HAS_LISTENERS) {
svcArbitrateUnlock(&m->Tag); svcArbitrateUnlock((u32*)m);
} }
} }
void rmutexLock(RMutex* m) { void rmutexLock(RMutex* m) {
if (m->Owner == _GetTag()) { if (m->thread_tag == _GetTag()) {
m->Count++; m->counter++;
} }
else { else {
mutexLock(&m->Lock); mutexLock(&m->lock);
m->Owner = _GetTag(); m->thread_tag = _GetTag();
} }
} }
void rmutexUnlock(RMutex* m) { void rmutexUnlock(RMutex* m) {
if (--m->Count == 0) { if (--m->counter == 0) {
m->Owner = 0; m->thread_tag = 0;
mutexUnlock(&m->Lock); mutexUnlock(&m->lock);
} }
} }

View File

@ -63,7 +63,7 @@ void __attribute__((weak)) __libnx_init(void)
__libc_init_array(); __libc_init_array();
} }
void __attribute__((weak)) NORETURN __libnx_exit(void) void __attribute__((weak)) NORETURN __libnx_exit(int rc)
{ {
// Call destructors. // Call destructors.
void __libc_fini_array(void); void __libc_fini_array(void);

View File

@ -4,15 +4,15 @@
#include <sys/lock.h> #include <sys/lock.h>
#include <sys/reent.h> #include <sys/reent.h>
void __attribute__((weak)) NORETURN __libnx_exit(void); void __attribute__((weak)) NORETURN __libnx_exit(int rc);
static void NORETURN _ExitImpl(int rc) {
__libnx_exit();
}
void newlibSetup() { void newlibSetup() {
void exitImpl(int rc); // Register newlib syscalls
__syscalls.exit = _ExitImpl; __syscalls.exit = __libnx_exit;
// Register locking syscalls
__syscalls.lock_acquire = mutexLock;
__syscalls.lock_release = mutexUnlock;
__syscalls.lock_acquire_recursive = rmutexLock;
__syscalls.lock_release_recursive = rmutexUnlock;
} }