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<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
+
+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) {