mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
Integrate newlib locks with libnx (R)Mutex (untested, incomplete)
This commit is contained in:
parent
757349c5c4
commit
f27685b7b3
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user