diff --git a/CMakeLists.txt b/CMakeLists.txt index 08cc4103..9cb5f0ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,12 +85,16 @@ if (APPLE) find_package(date 3.0.1 CONFIG) endif() +# Note: Windows always has these functions through winpthreads include(CheckSymbolExists) 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) add_compile_options(-DHAVE_PTHREAD_MUTEX_TIMEDLOCK) 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) include_directories(src) diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 0992009a..d5e2adea 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -1382,13 +1382,38 @@ int PS4_SYSV_ABI posix_sem_wait(sem_t* sem) { return sem_wait(sem); } -int PS4_SYSV_ABI posix_sem_timedwait(sem_t* sem, const timespec* t) { -#ifndef __APPLE__ - return sem_timedwait(sem, t); -#else - LOG_ERROR(Kernel_Pthread, "Apple doesn't support sem_timedwait yet"); - return 0; // unsupported for apple yet +#ifndef HAVE_SEM_TIMEDWAIT +int sem_timedwait(sem_t* sem, const struct timespec* abstime) { + int rc; + while ((rc = sem_trywait(sem)) == EAGAIN) { + struct timespec curr_time; + clock_gettime(CLOCK_REALTIME, &curr_time); + + s64 remaining_ns = 0; + remaining_ns += + (static_cast(abstime->tv_sec) - static_cast(curr_time.tv_sec)) * 1000000000L; + remaining_ns += static_cast(abstime->tv_nsec) - static_cast(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 + +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) {