From e1ecfb8dd1062d3081821aa25ba619f17c887497 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Fri, 6 Dec 2024 13:46:44 -0800 Subject: [PATCH] semaphore: Add GCD semaphore implementation. (#1677) --- src/core/libraries/kernel/sync/semaphore.h | 36 +++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/kernel/sync/semaphore.h b/src/core/libraries/kernel/sync/semaphore.h index a103472c..884b0896 100644 --- a/src/core/libraries/kernel/sync/semaphore.h +++ b/src/core/libraries/kernel/sync/semaphore.h @@ -11,6 +11,8 @@ #ifdef _WIN64 #include +#elif defined(__APPLE__) +#include #else #include #endif @@ -21,25 +23,32 @@ template class Semaphore { public: Semaphore(s32 initialCount) -#ifndef _WIN64 +#if !defined(_WIN64) && !defined(__APPLE__) : sem{initialCount} #endif { #ifdef _WIN64 sem = CreateSemaphore(nullptr, initialCount, max, nullptr); ASSERT(sem); +#elif defined(__APPLE__) + sem = dispatch_semaphore_create(initialCount); + ASSERT(sem); #endif } ~Semaphore() { #ifdef _WIN64 CloseHandle(sem); +#elif defined(__APPLE__) + dispatch_release(sem); #endif } void release() { #ifdef _WIN64 ReleaseSemaphore(sem, 1, nullptr); +#elif defined(__APPLE__) + dispatch_semaphore_signal(sem); #else sem.release(); #endif @@ -53,6 +62,13 @@ public: return; } } +#elif defined(__APPLE__) + for (;;) { + const auto res = dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); + if (res == 0) { + return; + } + } #else sem.acquire(); #endif @@ -61,6 +77,8 @@ public: bool try_acquire() { #ifdef _WIN64 return WaitForSingleObjectEx(sem, 0, true) == WAIT_OBJECT_0; +#elif defined(__APPLE__) + return dispatch_semaphore_wait(sem, DISPATCH_TIME_NOW) == 0; #else return sem.try_acquire(); #endif @@ -77,6 +95,10 @@ public: } return WaitForSingleObjectEx(sem, timeout_ms, true) == WAIT_OBJECT_0; +#elif defined(__APPLE__) + const auto rel_time_ns = std::chrono::ceil(rel_time).count(); + const auto timeout = dispatch_time(DISPATCH_TIME_NOW, rel_time_ns); + return dispatch_semaphore_wait(sem, timeout) == 0; #else return sem.try_acquire_for(rel_time); #endif @@ -98,6 +120,16 @@ public: u64 res = WaitForSingleObjectEx(sem, static_cast(timeout_ms), true); return res == WAIT_OBJECT_0; +#elif defined(__APPLE__) + auto abs_s = std::chrono::time_point_cast(abs_time); + auto abs_ns = std::chrono::time_point_cast(abs_time) - + std::chrono::time_point_cast(abs_s); + const timespec abs_timespec = { + .tv_sec = abs_s.time_since_epoch().count(), + .tv_nsec = abs_ns.count(), + }; + const auto timeout = dispatch_walltime(&abs_timespec, 0); + return dispatch_semaphore_wait(sem, timeout) == 0; #else return sem.try_acquire_until(abs_time); #endif @@ -106,6 +138,8 @@ public: private: #ifdef _WIN64 HANDLE sem; +#elif defined(__APPLE__) + dispatch_semaphore_t sem; #else std::counting_semaphore sem; #endif