Add custom implementation for semaphores.

This commit is contained in:
Skyth 2024-12-22 23:50:19 +03:00
parent f1416c85ba
commit d6444da62f

View file

@ -97,16 +97,16 @@ static std::atomic<uint32_t> g_keSetEventGeneration;
struct Semaphore final : KernelObject, HostObject<XKSEMAPHORE> struct Semaphore final : KernelObject, HostObject<XKSEMAPHORE>
{ {
std::counting_semaphore<> semaphore; std::atomic<uint32_t> count;
uint32_t maximumCount; uint32_t maximumCount;
Semaphore(XKSEMAPHORE* semaphore) 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(uint32_t count, uint32_t maximumCount)
: semaphore(count), maximumCount(maximumCount) : count(count), maximumCount(maximumCount)
{ {
} }
@ -114,11 +114,32 @@ struct Semaphore final : KernelObject, HostObject<XKSEMAPHORE>
{ {
if (timeout == 0) 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) 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; return STATUS_SUCCESS;
} }
else else
@ -130,7 +151,13 @@ struct Semaphore final : KernelObject, HostObject<XKSEMAPHORE>
void Release(uint32_t releaseCount, uint32_t* previousCount) 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();
} }
}; };