From d31df2deadc11d0833ca3597db93b7507985b44c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=9A=93?= Date: Fri, 1 Aug 2025 14:53:18 -0400 Subject: [PATCH] Use Grand Central Dispatch semaphores instead of POSIX semaphores in libretro Darwin builds POSIX semaphores are available in the standard library, but creation of unnamed POSIX semaphores always fails, so they're basically useless for our purposes. --- meson.build | 40 ++++++++++++++++++++++++++++------------ src/mkxp-polyfill.cpp | 12 +++++++++++- src/mkxp-polyfill.h | 10 ++++++++++ 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/meson.build b/meson.build index 755ec7ce..108565e2 100644 --- a/meson.build +++ b/meson.build @@ -284,18 +284,34 @@ if not compilers['cpp'].has_header('pthread.h') or not compilers['cpp'].links('' global_args += '-DMKXPZ_NO_PTHREAD_H_MUTEX' endif global_args += '-DMKXPZ_NO_SEMAPHORE_H' -elif not compilers['cpp'].has_header('semaphore.h') or not compilers['cpp'].links(''' - #include - int main(void) { - sem_t sem; - sem_init(&sem, 0, 0); - sem_post(&sem); - sem_wait(&sem); - sem_destroy(&sem); - return 0; - } -''', args: link_test_args, name: 'semaphore.h sanity check') - global_args += '-DMKXPZ_NO_SEMAPHORE_H' +else + if host_system == 'darwin' or not compilers['cpp'].has_header('semaphore.h') or not compilers['cpp'].links(''' + #include + int main(void) { + sem_t sem; + sem_init(&sem, 0, 0); + sem_post(&sem); + sem_wait(&sem); + sem_destroy(&sem); + return 0; + } + ''', args: link_test_args, name: 'semaphore.h sanity check') + global_args += '-DMKXPZ_NO_SEMAPHORE_H' + endif + + if not compilers['cpp'].has_header('dispatch/dispatch.h') or not compilers['cpp'].links(''' + #include + int main(void) { + dispatch_semaphore_t sem; + sem = dispatch_semaphore_create(0); + dispatch_semaphore_signal(sem); + dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); + dispatch_release(sem); + return 0; + } + ''', args: link_test_args, name: 'dispatch/dispatch.h sanity check') + global_args += '-DMKXPZ_NO_DISPATCH_DISPATCH_H' + endif endif if not compilers['cpp'].has_header('pthread.h') or not compilers['cpp'].links(''' diff --git a/src/mkxp-polyfill.cpp b/src/mkxp-polyfill.cpp index 8af3831a..3af0b94b 100644 --- a/src/mkxp-polyfill.cpp +++ b/src/mkxp-polyfill.cpp @@ -192,7 +192,7 @@ static void ctr_thread_launcher(void *data) { } #endif -#if defined(MKXPZ_NO_SEMAPHORE_H) && !defined(MKXPZ_NO_PTHREAD_H_MUTEX) +#if defined(MKXPZ_NO_SEMAPHORE_H) && defined(MKXPZ_NO_DISPATCH_DISPATCH_H) && !defined(MKXPZ_NO_PTHREAD_H_MUTEX) struct mkxp_sem_private { unsigned int value; mkxp_mutex_t mutex; @@ -380,6 +380,8 @@ extern "C" int mkxp_cond_wait(mkxp_cond_t *cond, mkxp_mutex_t *mutex) { extern "C" int mkxp_sem_init(mkxp_sem_t *sem, unsigned int value) { #ifndef MKXPZ_NO_SEMAPHORE_H return sem_init(sem, 0, value); +#elif !defined(MKXPZ_NO_DISPATCH_DISPATCH_H) + return (*sem = dispatch_semaphore_create(value)) == nullptr ? -1 : 0; #elif !defined(MKXPZ_NO_PTHREAD_H_MUTEX) *sem = (void *)new mkxp_sem_private; int mutex_init_result = mkxp_mutex_init(&((struct mkxp_sem_private *)*sem)->mutex, false); @@ -402,6 +404,9 @@ extern "C" int mkxp_sem_init(mkxp_sem_t *sem, unsigned int value) { extern "C" int mkxp_sem_destroy(mkxp_sem_t *sem) { #ifndef MKXPZ_NO_SEMAPHORE_H return sem_destroy(sem); +#elif !defined(MKXPZ_NO_DISPATCH_DISPATCH_H) + dispatch_release(*sem); + return 0; #elif !defined(MKXPZ_NO_PTHREAD_H_MUTEX) mkxp_cond_destroy(&((struct mkxp_sem_private *)*sem)->cond); mkxp_mutex_destroy(&((struct mkxp_sem_private *)*sem)->mutex); @@ -415,6 +420,9 @@ extern "C" int mkxp_sem_destroy(mkxp_sem_t *sem) { extern "C" int mkxp_sem_post(mkxp_sem_t *sem) { #ifndef MKXPZ_NO_SEMAPHORE_H return sem_post(sem); +#elif !defined(MKXPZ_NO_DISPATCH_DISPATCH_H) + dispatch_semaphore_signal(*sem); + return 0; #elif !defined(MKXPZ_NO_PTHREAD_H_MUTEX) while (mkxp_mutex_lock(&((struct mkxp_sem_private *)*sem)->mutex)) {} ++((struct mkxp_sem_private *)*sem)->value; @@ -430,6 +438,8 @@ extern "C" int mkxp_sem_post(mkxp_sem_t *sem) { extern "C" int mkxp_sem_wait(mkxp_sem_t *sem) { #ifndef MKXPZ_NO_SEMAPHORE_H return sem_wait(sem); +#elif !defined(MKXPZ_NO_DISPATCH_DISPATCH_H) + return dispatch_semaphore_wait(*sem, DISPATCH_TIME_FOREVER); #elif !defined(MKXPZ_NO_PTHREAD_H_MUTEX) while (mkxp_mutex_lock(&((struct mkxp_sem_private *)*sem)->mutex)) {} for (;;) { diff --git a/src/mkxp-polyfill.h b/src/mkxp-polyfill.h index f0063f9d..832b7b6e 100644 --- a/src/mkxp-polyfill.h +++ b/src/mkxp-polyfill.h @@ -30,6 +30,10 @@ #include #include +#if defined(__APPLE__) && !defined(MKXPZ_NO_SEMAPHORE_H) +# define MKXPZ_NO_SEMAPHORE_H +#endif + #if !defined(MKXPZ_NO_PTHREAD_H_MUTEX) || !defined(MKXPZ_NO_PTHREAD_H_THREAD) # include #endif @@ -38,6 +42,10 @@ # include #endif +#ifndef MKXPZ_NO_DISPATCH_DISPATCH_H +# include +#endif + #if !defined(__cplusplus) || defined(MKXPZ_NO_EXCEPTIONS) # define MKXPZ_THROW(...) do { fprintf(stderr, "Exception thrown: %s\n", (__VA_ARGS__).what()); fflush(stderr); abort(); } while (0) # define MKXPZ_RETHROW do { } while (0) @@ -76,6 +84,8 @@ typedef bool mkxp_cond_t; #ifndef MKXPZ_NO_SEMAPHORE_H typedef sem_t mkxp_sem_t; +#elif !defined(MKXPZ_NO_DISPATCH_DISPATCH_H) +typedef dispatch_semaphore_t mkxp_sem_t; #elif !defined(MKXPZ_NO_PTHREAD_H_MUTEX) typedef void *mkxp_sem_t; #else