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
typedef struct {
u32 Tag;
} Mutex;
#pragma once
#include <sys/lock.h>
typedef struct {
u32 Owner;
Mutex Lock;
size_t Count;
} RMutex;
typedef _LOCK_T Mutex;
typedef _LOCK_RECURSIVE_T RMutex;
void mutexLock(Mutex* m);
void mutexUnlock(Mutex* m);

View File

@ -11,7 +11,7 @@ static u32 _GetTag() {
void mutexLock(Mutex* m) {
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) {
if (cur == 0) {
@ -26,44 +26,44 @@ void mutexLock(Mutex* m) {
if (cur & HAS_LISTENERS) {
// 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 {
// 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) {
// 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) {
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) {
svcArbitrateUnlock(&m->Tag);
svcArbitrateUnlock((u32*)m);
}
}
void rmutexLock(RMutex* m) {
if (m->Owner == _GetTag()) {
m->Count++;
if (m->thread_tag == _GetTag()) {
m->counter++;
}
else {
mutexLock(&m->Lock);
m->Owner = _GetTag();
mutexLock(&m->lock);
m->thread_tag = _GetTag();
}
}
void rmutexUnlock(RMutex* m) {
if (--m->Count == 0) {
m->Owner = 0;
mutexUnlock(&m->Lock);
if (--m->counter == 0) {
m->thread_tag = 0;
mutexUnlock(&m->lock);
}
}

View File

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

View File

@ -4,15 +4,15 @@
#include <sys/lock.h>
#include <sys/reent.h>
void __attribute__((weak)) NORETURN __libnx_exit(void);
static void NORETURN _ExitImpl(int rc) {
__libnx_exit();
}
void __attribute__((weak)) NORETURN __libnx_exit(int rc);
void newlibSetup() {
void exitImpl(int rc);
__syscalls.exit = _ExitImpl;
// Register newlib syscalls
__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;
}