mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-08-31 19:23:04 +02:00
Add mutex and condition variable polyfill for libretro 3DS builds
This commit is contained in:
parent
a73dec9cad
commit
0b9baa1007
4 changed files with 111 additions and 41 deletions
|
@ -26,6 +26,7 @@
|
|||
#include "etc.h"
|
||||
#include "binding-util.h"
|
||||
#include "sharedstate.h"
|
||||
#include "mkxp-polyfill.h" // sprintf
|
||||
|
||||
namespace mkxp_sandbox {
|
||||
static struct mkxp_sandbox::bindings::rb_data_type color_type;
|
||||
|
|
|
@ -190,7 +190,7 @@ if not compilers['cpp'].has_header_symbol('thread', 'std::this_thread::yield')
|
|||
global_args += '-DMKXPZ_NO_STD_THIS_THREAD_YIELD'
|
||||
endif
|
||||
|
||||
if not compilers['cpp'].has_header('pthread.h') or not compilers['cpp'].compiles('''
|
||||
if not compilers['cpp'].has_header('pthread.h') or not compilers['cpp'].links('''
|
||||
#include <pthread.h>
|
||||
int main(void) {
|
||||
pthread_mutex_t mutex;
|
||||
|
@ -207,9 +207,9 @@ if not compilers['cpp'].has_header('pthread.h') or not compilers['cpp'].compiles
|
|||
return result;
|
||||
}
|
||||
''', name: 'pthread.h sanity check')
|
||||
global_args += '-DMKXPZ_NO_PTHREAD_H'
|
||||
global_args += is_devkitarm ? '-DMKXPZ_DEVKITARM_NO_PTHREAD_H' : '-DMKXPZ_NO_PTHREAD_H'
|
||||
global_args += '-DMKXPZ_NO_SEMAPHORE_H'
|
||||
elif not compilers['cpp'].has_header('semaphore.h') or not compilers['cpp'].compiles('''
|
||||
elif not compilers['cpp'].has_header('semaphore.h') or not compilers['cpp'].links('''
|
||||
#include <semaphore.h>
|
||||
int main(void) {
|
||||
sem_t sem;
|
||||
|
|
|
@ -80,16 +80,33 @@ extern "C" void mkxp_aligned_free(void *ptr) {
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef MKXPZ_DEVKITARM_NO_PTHREAD_H
|
||||
extern "C" {
|
||||
void *threadGetCurrent(void);
|
||||
void LightLock_Init(_LOCK_T *);
|
||||
void LightLock_Lock(_LOCK_T *);
|
||||
void LightLock_Unlock(_LOCK_T *);
|
||||
void RecursiveLock_Init(_LOCK_RECURSIVE_T *);
|
||||
void RecursiveLock_Lock(_LOCK_RECURSIVE_T *);
|
||||
void RecursiveLock_Unlock(_LOCK_RECURSIVE_T *);
|
||||
void CondVar_Init(mkxp_cond_t *);
|
||||
void CondVar_Wait(mkxp_cond_t *, _LOCK_T *);
|
||||
void CondVar_WakeUp(mkxp_cond_t *, int32_t);
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(MKXPZ_NO_SEMAPHORE_H) && !defined(MKXPZ_NO_PTHREAD_H)
|
||||
struct mkxp_sem_private {
|
||||
unsigned int value;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
mkxp_mutex_t mutex;
|
||||
mkxp_cond_t cond;
|
||||
};
|
||||
#endif
|
||||
|
||||
extern "C" mkxp_thread_t mkxp_thread_self() {
|
||||
#ifndef MKXPZ_NO_PTHREAD_H
|
||||
#ifdef MKXPZ_DEVKITARM_NO_PTHREAD_H
|
||||
return threadGetCurrent();
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
return pthread_self();
|
||||
#else
|
||||
return 42;
|
||||
|
@ -97,7 +114,15 @@ extern "C" mkxp_thread_t mkxp_thread_self() {
|
|||
}
|
||||
|
||||
extern "C" int mkxp_mutex_init(mkxp_mutex_t *mutex, bool recursive) {
|
||||
#ifndef MKXPZ_NO_PTHREAD_H
|
||||
#ifdef MKXPZ_DEVKITARM_NO_PTHREAD_H
|
||||
mutex->recursive = recursive;
|
||||
if (recursive) {
|
||||
RecursiveLock_Init(&mutex->inner.recursive);
|
||||
} else {
|
||||
LightLock_Init(&mutex->inner.light);
|
||||
}
|
||||
return 0;
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
if (recursive) {
|
||||
pthread_mutexattr_t attr;
|
||||
if (pthread_mutexattr_init(&attr)) {
|
||||
|
@ -117,7 +142,9 @@ extern "C" int mkxp_mutex_init(mkxp_mutex_t *mutex, bool recursive) {
|
|||
}
|
||||
|
||||
extern "C" int mkxp_mutex_destroy(mkxp_mutex_t *mutex) {
|
||||
#ifndef MKXPZ_NO_PTHREAD_H
|
||||
#ifdef MKXPZ_DEVKITARM_NO_PTHREAD_H
|
||||
return 0;
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
return pthread_mutex_destroy(mutex);
|
||||
#else
|
||||
assert(!*mutex);
|
||||
|
@ -126,7 +153,14 @@ extern "C" int mkxp_mutex_destroy(mkxp_mutex_t *mutex) {
|
|||
}
|
||||
|
||||
extern "C" int mkxp_mutex_lock(mkxp_mutex_t *mutex) {
|
||||
#ifndef MKXPZ_NO_PTHREAD_H
|
||||
#ifdef MKXPZ_DEVKITARM_NO_PTHREAD_H
|
||||
if (mutex->recursive) {
|
||||
RecursiveLock_Lock(&mutex->inner.recursive);
|
||||
} else {
|
||||
LightLock_Lock(&mutex->inner.light);
|
||||
}
|
||||
return 0;
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
return pthread_mutex_lock(mutex);
|
||||
#else
|
||||
++*mutex;
|
||||
|
@ -135,7 +169,14 @@ extern "C" int mkxp_mutex_lock(mkxp_mutex_t *mutex) {
|
|||
}
|
||||
|
||||
extern "C" int mkxp_mutex_unlock(mkxp_mutex_t *mutex) {
|
||||
#ifndef MKXPZ_NO_PTHREAD_H
|
||||
#ifdef MKXPZ_DEVKITARM_NO_PTHREAD_H
|
||||
if (mutex->recursive) {
|
||||
RecursiveLock_Unlock(&mutex->inner.recursive);
|
||||
} else {
|
||||
LightLock_Unlock(&mutex->inner.light);
|
||||
}
|
||||
return 0;
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
return pthread_mutex_unlock(mutex);
|
||||
#else
|
||||
assert(*mutex);
|
||||
|
@ -145,7 +186,10 @@ extern "C" int mkxp_mutex_unlock(mkxp_mutex_t *mutex) {
|
|||
}
|
||||
|
||||
extern "C" int mkxp_cond_init(mkxp_cond_t *cond) {
|
||||
#ifndef MKXPZ_NO_PTHREAD_H
|
||||
#ifdef MKXPZ_DEVKITARM_NO_PTHREAD_H
|
||||
CondVar_Init(cond);
|
||||
return 0;
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
return pthread_cond_init(cond, NULL);
|
||||
#else
|
||||
return 0;
|
||||
|
@ -153,7 +197,9 @@ extern "C" int mkxp_cond_init(mkxp_cond_t *cond) {
|
|||
}
|
||||
|
||||
extern "C" int mkxp_cond_destroy(mkxp_cond_t *cond) {
|
||||
#ifndef MKXPZ_NO_PTHREAD_H
|
||||
#ifdef MKXPZ_DEVKITARM_NO_PTHREAD_H
|
||||
return 0;
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
return pthread_cond_destroy(cond);
|
||||
#else
|
||||
return 0;
|
||||
|
@ -161,7 +207,10 @@ extern "C" int mkxp_cond_destroy(mkxp_cond_t *cond) {
|
|||
}
|
||||
|
||||
extern "C" int mkxp_cond_signal(mkxp_cond_t *cond) {
|
||||
#ifndef MKXPZ_NO_PTHREAD_H
|
||||
#ifdef MKXPZ_DEVKITARM_NO_PTHREAD_H
|
||||
CondVar_WakeUp(cond, 1);
|
||||
return 0;
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
return pthread_cond_signal(cond);
|
||||
#else
|
||||
return 0;
|
||||
|
@ -169,7 +218,10 @@ extern "C" int mkxp_cond_signal(mkxp_cond_t *cond) {
|
|||
}
|
||||
|
||||
extern "C" int mkxp_cond_broadcast(mkxp_cond_t *cond) {
|
||||
#ifndef MKXPZ_NO_PTHREAD_H
|
||||
#ifdef MKXPZ_DEVKITARM_NO_PTHREAD_H
|
||||
CondVar_WakeUp(cond, -1);
|
||||
return 0;
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
return pthread_cond_broadcast(cond);
|
||||
#else
|
||||
return 0;
|
||||
|
@ -177,7 +229,13 @@ extern "C" int mkxp_cond_broadcast(mkxp_cond_t *cond) {
|
|||
}
|
||||
|
||||
extern "C" int mkxp_cond_wait(mkxp_cond_t *cond, mkxp_mutex_t *mutex) {
|
||||
#ifndef MKXPZ_NO_PTHREAD_H
|
||||
#ifdef MKXPZ_DEVKITARM_NO_PTHREAD_H
|
||||
if (mutex->recursive) {
|
||||
std::abort();
|
||||
}
|
||||
CondVar_Wait(cond, &mutex->inner.light);
|
||||
return 0;
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
return pthread_cond_wait(cond, mutex);
|
||||
#else
|
||||
return 0;
|
||||
|
@ -189,13 +247,13 @@ extern "C" int mkxp_sem_init(mkxp_sem_t *sem, unsigned int value) {
|
|||
return sem_init(sem, 0, value);
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
*sem = (void *)new mkxp_sem_private;
|
||||
int mutex_init_result = pthread_mutex_init(&((struct mkxp_sem_private *)*sem)->mutex, NULL);
|
||||
int mutex_init_result = mkxp_mutex_init(&((struct mkxp_sem_private *)*sem)->mutex, false);
|
||||
if (mutex_init_result) {
|
||||
return -1;
|
||||
}
|
||||
int cond_init_result = pthread_cond_init(&((struct mkxp_sem_private *)*sem)->cond, NULL);
|
||||
int cond_init_result = mkxp_cond_init(&((struct mkxp_sem_private *)*sem)->cond);
|
||||
if (cond_init_result) {
|
||||
pthread_mutex_destroy(&((struct mkxp_sem_private *)*sem)->mutex);
|
||||
mkxp_mutex_destroy(&((struct mkxp_sem_private *)*sem)->mutex);
|
||||
return -1;
|
||||
}
|
||||
((struct mkxp_sem_private *)*sem)->value = value;
|
||||
|
@ -210,8 +268,8 @@ extern "C" int mkxp_sem_destroy(mkxp_sem_t *sem) {
|
|||
#ifndef MKXPZ_NO_SEMAPHORE_H
|
||||
return sem_destroy(sem);
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
pthread_cond_destroy(&((struct mkxp_sem_private *)*sem)->cond);
|
||||
pthread_mutex_destroy(&((struct mkxp_sem_private *)*sem)->mutex);
|
||||
mkxp_cond_destroy(&((struct mkxp_sem_private *)*sem)->cond);
|
||||
mkxp_mutex_destroy(&((struct mkxp_sem_private *)*sem)->mutex);
|
||||
delete (struct mkxp_sem_private *)*sem;
|
||||
return 0;
|
||||
#else
|
||||
|
@ -223,10 +281,10 @@ extern "C" int mkxp_sem_post(mkxp_sem_t *sem) {
|
|||
#ifndef MKXPZ_NO_SEMAPHORE_H
|
||||
return sem_post(sem);
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
while (pthread_mutex_lock(&((struct mkxp_sem_private *)*sem)->mutex)) {}
|
||||
while (mkxp_mutex_lock(&((struct mkxp_sem_private *)*sem)->mutex)) {}
|
||||
++((struct mkxp_sem_private *)*sem)->value;
|
||||
pthread_cond_signal(&((struct mkxp_sem_private *)*sem)->cond);
|
||||
pthread_mutex_unlock(&((struct mkxp_sem_private *)*sem)->mutex);
|
||||
mkxp_cond_signal(&((struct mkxp_sem_private *)*sem)->cond);
|
||||
mkxp_mutex_unlock(&((struct mkxp_sem_private *)*sem)->mutex);
|
||||
return 0;
|
||||
#else
|
||||
++*sem;
|
||||
|
@ -238,14 +296,14 @@ extern "C" int mkxp_sem_wait(mkxp_sem_t *sem) {
|
|||
#ifndef MKXPZ_NO_SEMAPHORE_H
|
||||
return sem_wait(sem);
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
while (pthread_mutex_lock(&((struct mkxp_sem_private *)*sem)->mutex)) {}
|
||||
while (mkxp_mutex_lock(&((struct mkxp_sem_private *)*sem)->mutex)) {}
|
||||
for (;;) {
|
||||
if (((struct mkxp_sem_private *)*sem)->value) {
|
||||
--((struct mkxp_sem_private *)*sem)->value;
|
||||
pthread_mutex_unlock(&((struct mkxp_sem_private *)*sem)->mutex);
|
||||
mkxp_mutex_unlock(&((struct mkxp_sem_private *)*sem)->mutex);
|
||||
return 0;
|
||||
}
|
||||
while (pthread_cond_wait(&((struct mkxp_sem_private *)*sem)->cond, &((struct mkxp_sem_private *)*sem)->mutex)) {}
|
||||
while (mkxp_cond_wait(&((struct mkxp_sem_private *)*sem)->cond, &((struct mkxp_sem_private *)*sem)->mutex)) {}
|
||||
}
|
||||
#else
|
||||
assert(*sem);
|
||||
|
|
|
@ -36,21 +36,18 @@
|
|||
# include <semaphore.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <string>
|
||||
|
||||
extern "C" long long strtoll(const char *str, char **str_end, int base);
|
||||
extern "C" unsigned long long strtoull(const char *str, char **str_end, int base);
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef MKXPZ_NO_PTHREAD_H
|
||||
#ifdef MKXPZ_DEVKITARM_NO_PTHREAD_H
|
||||
# include <sys/lock.h>
|
||||
typedef void *mkxp_thread_t;
|
||||
typedef struct {
|
||||
union {
|
||||
_LOCK_T light;
|
||||
_LOCK_RECURSIVE_T recursive;
|
||||
} inner;
|
||||
bool recursive;
|
||||
} mkxp_mutex_t;
|
||||
typedef int32_t mkxp_cond_t;
|
||||
#elif !defined(MKXPZ_NO_PTHREAD_H)
|
||||
typedef pthread_t mkxp_thread_t;
|
||||
typedef pthread_mutex_t mkxp_mutex_t;
|
||||
typedef pthread_cond_t mkxp_cond_t;
|
||||
|
@ -72,6 +69,20 @@ typedef unsigned int mkxp_sem_t;
|
|||
# define MKXPZ_HAVE_ANY_ALIGNED_MALLOC 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <string>
|
||||
|
||||
extern "C" long long strtoll(const char *str, char **str_end, int base);
|
||||
extern "C" unsigned long long strtoull(const char *str, char **str_end, int base);
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef MKXPZ_NO_SPRINTF
|
||||
int sprintf(char *buffer, const char *format, ...);
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue