Skip to content

Commit c1e2c37

Browse files
squidbusXcedf
authored andcommitted
semaphore: Add GCD semaphore implementation. (shadps4-emu#1677)
1 parent 99d28ea commit c1e2c37

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

src/core/libraries/kernel/sync/semaphore.h

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
#ifdef _WIN64
1313
#include <windows.h>
14+
#elif defined(__APPLE__)
15+
#include <dispatch/dispatch.h>
1416
#else
1517
#include <semaphore>
1618
#endif
@@ -21,25 +23,32 @@ template <s64 max>
2123
class Semaphore {
2224
public:
2325
Semaphore(s32 initialCount)
24-
#ifndef _WIN64
26+
#if !defined(_WIN64) && !defined(__APPLE__)
2527
: sem{initialCount}
2628
#endif
2729
{
2830
#ifdef _WIN64
2931
sem = CreateSemaphore(nullptr, initialCount, max, nullptr);
3032
ASSERT(sem);
33+
#elif defined(__APPLE__)
34+
sem = dispatch_semaphore_create(initialCount);
35+
ASSERT(sem);
3136
#endif
3237
}
3338

3439
~Semaphore() {
3540
#ifdef _WIN64
3641
CloseHandle(sem);
42+
#elif defined(__APPLE__)
43+
dispatch_release(sem);
3744
#endif
3845
}
3946

4047
void release() {
4148
#ifdef _WIN64
4249
ReleaseSemaphore(sem, 1, nullptr);
50+
#elif defined(__APPLE__)
51+
dispatch_semaphore_signal(sem);
4352
#else
4453
sem.release();
4554
#endif
@@ -53,6 +62,13 @@ class Semaphore {
5362
return;
5463
}
5564
}
65+
#elif defined(__APPLE__)
66+
for (;;) {
67+
const auto res = dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
68+
if (res == 0) {
69+
return;
70+
}
71+
}
5672
#else
5773
sem.acquire();
5874
#endif
@@ -61,6 +77,8 @@ class Semaphore {
6177
bool try_acquire() {
6278
#ifdef _WIN64
6379
return WaitForSingleObjectEx(sem, 0, true) == WAIT_OBJECT_0;
80+
#elif defined(__APPLE__)
81+
return dispatch_semaphore_wait(sem, DISPATCH_TIME_NOW) == 0;
6482
#else
6583
return sem.try_acquire();
6684
#endif
@@ -77,6 +95,10 @@ class Semaphore {
7795
}
7896

7997
return WaitForSingleObjectEx(sem, timeout_ms, true) == WAIT_OBJECT_0;
98+
#elif defined(__APPLE__)
99+
const auto rel_time_ns = std::chrono::ceil<std::chrono::nanoseconds>(rel_time).count();
100+
const auto timeout = dispatch_time(DISPATCH_TIME_NOW, rel_time_ns);
101+
return dispatch_semaphore_wait(sem, timeout) == 0;
80102
#else
81103
return sem.try_acquire_for(rel_time);
82104
#endif
@@ -98,6 +120,16 @@ class Semaphore {
98120

99121
u64 res = WaitForSingleObjectEx(sem, static_cast<u64>(timeout_ms), true);
100122
return res == WAIT_OBJECT_0;
123+
#elif defined(__APPLE__)
124+
auto abs_s = std::chrono::time_point_cast<std::chrono::seconds>(abs_time);
125+
auto abs_ns = std::chrono::time_point_cast<std::chrono::nanoseconds>(abs_time) -
126+
std::chrono::time_point_cast<std::chrono::nanoseconds>(abs_s);
127+
const timespec abs_timespec = {
128+
.tv_sec = abs_s.time_since_epoch().count(),
129+
.tv_nsec = abs_ns.count(),
130+
};
131+
const auto timeout = dispatch_walltime(&abs_timespec, 0);
132+
return dispatch_semaphore_wait(sem, timeout) == 0;
101133
#else
102134
return sem.try_acquire_until(abs_time);
103135
#endif
@@ -106,6 +138,8 @@ class Semaphore {
106138
private:
107139
#ifdef _WIN64
108140
HANDLE sem;
141+
#elif defined(__APPLE__)
142+
dispatch_semaphore_t sem;
109143
#else
110144
std::counting_semaphore<max> sem;
111145
#endif

0 commit comments

Comments
 (0)