Merge pull request #336 from squidbus/sem-polyfill

Add sem_timedwait polyfill for macOS.
This commit is contained in:
georgemoralis 2024-07-29 07:56:18 +03:00 committed by GitHub
commit 9b1092c995
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 7 deletions

View File

@ -85,12 +85,16 @@ if (APPLE)
find_package(date 3.0.1 CONFIG) find_package(date 3.0.1 CONFIG)
endif() endif()
# Note: Windows always has these functions through winpthreads
include(CheckSymbolExists) include(CheckSymbolExists)
check_symbol_exists(pthread_mutex_timedlock "pthread.h" HAVE_PTHREAD_MUTEX_TIMEDLOCK) check_symbol_exists(pthread_mutex_timedlock "pthread.h" HAVE_PTHREAD_MUTEX_TIMEDLOCK)
# Windows always has the function through winpthreads
if(HAVE_PTHREAD_MUTEX_TIMEDLOCK OR WIN32) if(HAVE_PTHREAD_MUTEX_TIMEDLOCK OR WIN32)
add_compile_options(-DHAVE_PTHREAD_MUTEX_TIMEDLOCK) add_compile_options(-DHAVE_PTHREAD_MUTEX_TIMEDLOCK)
endif() endif()
check_symbol_exists(sem_timedwait "semaphore.h" HAVE_SEM_TIMEDWAIT)
if(HAVE_SEM_TIMEDWAIT OR WIN32)
add_compile_options(-DHAVE_SEM_TIMEDWAIT)
endif()
add_subdirectory(externals) add_subdirectory(externals)
include_directories(src) include_directories(src)

View File

@ -1382,13 +1382,38 @@ int PS4_SYSV_ABI posix_sem_wait(sem_t* sem) {
return sem_wait(sem); return sem_wait(sem);
} }
int PS4_SYSV_ABI posix_sem_timedwait(sem_t* sem, const timespec* t) { #ifndef HAVE_SEM_TIMEDWAIT
#ifndef __APPLE__ int sem_timedwait(sem_t* sem, const struct timespec* abstime) {
return sem_timedwait(sem, t); int rc;
#else while ((rc = sem_trywait(sem)) == EAGAIN) {
LOG_ERROR(Kernel_Pthread, "Apple doesn't support sem_timedwait yet"); struct timespec curr_time;
return 0; // unsupported for apple yet clock_gettime(CLOCK_REALTIME, &curr_time);
s64 remaining_ns = 0;
remaining_ns +=
(static_cast<s64>(abstime->tv_sec) - static_cast<s64>(curr_time.tv_sec)) * 1000000000L;
remaining_ns += static_cast<s64>(abstime->tv_nsec) - static_cast<s64>(curr_time.tv_nsec);
if (remaining_ns <= 0) {
return ETIMEDOUT;
}
struct timespec sleep_time;
sleep_time.tv_sec = 0;
if (remaining_ns < 5000000L) {
sleep_time.tv_nsec = remaining_ns;
} else {
sleep_time.tv_nsec = 5000000;
}
nanosleep(&sleep_time, nullptr);
}
return rc;
}
#endif #endif
int PS4_SYSV_ABI posix_sem_timedwait(sem_t* sem, const timespec* t) {
return sem_timedwait(sem, t);
} }
int PS4_SYSV_ABI posix_sem_post(sem_t* sem) { int PS4_SYSV_ABI posix_sem_post(sem_t* sem) {