From d6444da62fbf7c067b659a5224eb0d3abf4bc47c Mon Sep 17 00:00:00 2001 From: Skyth <19259897+blueskythlikesclouds@users.noreply.github.com> Date: Sun, 22 Dec 2024 23:50:19 +0300 Subject: [PATCH] Add custom implementation for semaphores. --- UnleashedRecomp/kernel/imports.cpp | 39 +++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/UnleashedRecomp/kernel/imports.cpp b/UnleashedRecomp/kernel/imports.cpp index dfa1664..2cc2aae 100644 --- a/UnleashedRecomp/kernel/imports.cpp +++ b/UnleashedRecomp/kernel/imports.cpp @@ -97,16 +97,16 @@ static std::atomic g_keSetEventGeneration; struct Semaphore final : KernelObject, HostObject { - std::counting_semaphore<> semaphore; + std::atomic count; uint32_t maximumCount; Semaphore(XKSEMAPHORE* semaphore) - : semaphore(semaphore->Header.SignalState), maximumCount(semaphore->Limit) + : count(semaphore->Header.SignalState), maximumCount(semaphore->Limit) { } Semaphore(uint32_t count, uint32_t maximumCount) - : semaphore(count), maximumCount(maximumCount) + : count(count), maximumCount(maximumCount) { } @@ -114,11 +114,32 @@ struct Semaphore final : KernelObject, HostObject { if (timeout == 0) { - return semaphore.try_acquire() ? STATUS_SUCCESS : STATUS_TIMEOUT; + uint32_t currentCount = count.load(); + if (currentCount != 0) + { + if (count.compare_exchange_weak(currentCount, currentCount - 1)) + return STATUS_SUCCESS; + } + + return STATUS_TIMEOUT; } else if (timeout == INFINITE) { - semaphore.acquire(); + uint32_t currentCount; + while (true) + { + currentCount = count.load(); + if (currentCount != 0) + { + if (count.compare_exchange_weak(currentCount, currentCount - 1)) + return STATUS_SUCCESS; + } + else + { + count.wait(0); + } + } + return STATUS_SUCCESS; } else @@ -130,7 +151,13 @@ struct Semaphore final : KernelObject, HostObject void Release(uint32_t releaseCount, uint32_t* previousCount) { - semaphore.release(releaseCount); + if (previousCount != nullptr) + *previousCount = count; + + assert(count + releaseCount <= maximumCount); + + count += releaseCount; + count.notify_all(); } };