[+] AuLoop::NewSemaphoreEx with max count option for in-process (not ipc) limiting the total wakes.
This is required for Xbox, Xbox 360, and Win32 emulators deriving a mutex via a the NT semaphore primitive instead of the builtin binary semaphore (event) and mutex.
This commit is contained in:
parent
7cc41f1359
commit
55cac676f5
@ -54,12 +54,6 @@ namespace Aurora::IO::Loop
|
||||
virtual bool Unlock() = 0;
|
||||
};
|
||||
|
||||
struct IConditionVar : virtual ILoopSource
|
||||
{
|
||||
virtual bool Signal() = 0;
|
||||
virtual bool Broadcast() = 0;
|
||||
};
|
||||
|
||||
struct ITimer : virtual ILoopSource
|
||||
{
|
||||
/* Warning: IO timers use wall time (CurrentClock[M/NS), not SteadyClock[M/N]S()).
|
||||
@ -77,21 +71,23 @@ namespace Aurora::IO::Loop
|
||||
virtual void *GetLastSignalInfo() = 0;
|
||||
};
|
||||
|
||||
AUKN_SYM AuSPtr<ITimer> NewLSTimer(AuUInt64 absStartTimeMs /*CurrentClockMS()*/, AuUInt32 reschedStepMsOrZero = 0, AuUInt32 maxIterationsOrZero = 0, bool bSingleshot = false /*cannot be changed*/);
|
||||
AUKN_SYM AuSPtr<ITimer> NewLSTimer(AuUInt64 absStartTimeMs /*CurrentClockMS()*/, AuUInt32 reschedStepMsOrZero = 0, AuUInt32 maxIterationsOrZero = 0, bool bSingleshot = false /*cannot be changed*/); // warn: no IPC counterpart
|
||||
AUKN_SYM AuSPtr<ILSMutex> NewLSMutex();
|
||||
AUKN_SYM AuSPtr<ILSMutex> NewLSMutexSlow(); // interop-ready (usable with DbgLoopSourceToReadFd)
|
||||
AUKN_SYM AuSPtr<ILSEvent> NewLSEvent(bool bTriggered = false, bool bAtomicRelease = true, bool bPermitMultipleTriggers = false);
|
||||
AUKN_SYM AuSPtr<ILSEvent> NewLSEventSlow(bool bTriggered = false, bool bAtomicRelease = true, bool bPermitMultipleTriggers = false); // interop-ready (usable with DbgLoopSourceToReadFd)
|
||||
AUKN_SYM AuSPtr<ILSSemaphore> NewLSSemaphore(AuUInt32 uInitialCount = 0);
|
||||
AUKN_SYM AuSPtr<ILSSemaphore> NewLSSemaphoreSlow(AuUInt32 uInitialCount = 0); // interop-ready (usable with DbgLoopSourceToReadFd)
|
||||
AUKN_SYM AuSPtr<ILSSemaphore> NewLSSemaphoreEx(AuUInt32 uInitialCount = 0, AuUInt32 uMaxCount = 0); // warn: no IPC counterpart
|
||||
AUKN_SYM AuSPtr<ILoopSource> NewLSOSHandle(AuUInt);
|
||||
AUKN_SYM AuSPtr<ILoopSource> NewLSAsync(Aurora::Async::WorkerPId_t workerPid);
|
||||
AUKN_SYM AuSPtr<ILoopSource> NewLSFile(const AuSPtr<IO::IAsyncTransaction> &fileTransaction);
|
||||
AUKN_SYM AuSPtr<ILoopSource> NewLSAsync(Aurora::Async::WorkerPId_t workerPid); // warn: no IPC counterpart
|
||||
AUKN_SYM AuSPtr<ILoopSource> NewLSFile(const AuSPtr<IO::IAsyncTransaction> &fileTransaction); // warn: no IPC counterpart
|
||||
AUKN_SYM AuSPtr<ILoopSource> NewStdIn();
|
||||
AUKN_SYM AuSPtr<ILoopSource> NewLSWin32Source(bool dispatchMessages);
|
||||
AUKN_SYM AuSPtr<ILoopSource> NewLSAppleSource();
|
||||
AUKN_SYM AuSPtr<ILoopSource> NewLSIOHandle(const AuSPtr<IIOHandle> &pHandle);
|
||||
|
||||
// See: AuIO::IPC for IPC event loop objects
|
||||
|
||||
// warn: Only works on singular loop sources
|
||||
// warn: You should only use trust the interop-ready sources to serve the HANDLE/fd you expect.
|
||||
// The primary loop-source primitives are capable of bypassing the kernels io scheduler via in-process atomics.
|
||||
|
@ -21,7 +21,7 @@ namespace Aurora::IO::Loop
|
||||
|
||||
}
|
||||
|
||||
bool LSLocalSemaphore::TryInit(AuUInt32 initialCount)
|
||||
bool LSLocalSemaphore::TryInit(AuUInt32 initialCount, AuUInt32 uMaxCount)
|
||||
{
|
||||
if (!LSSemaphore::TryInit(initialCount))
|
||||
{
|
||||
@ -30,7 +30,7 @@ namespace Aurora::IO::Loop
|
||||
|
||||
this->uAtomicSemaphore = initialCount;
|
||||
this->uAtomicKernelSemaphore = initialCount;
|
||||
|
||||
this->uMaxCount = uMaxCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -81,6 +81,9 @@ namespace Aurora::IO::Loop
|
||||
{
|
||||
AuAtomicAdd(&this->uAtomicKernelSemaphore, uCount);
|
||||
LSSemaphore::AddMany(uCount);
|
||||
#if !defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
(void)LSSemaphore::OnTrigger(0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
else
|
||||
@ -102,16 +105,31 @@ namespace Aurora::IO::Loop
|
||||
|
||||
bool LSLocalSemaphore::AddOne()
|
||||
{
|
||||
auto uNext = AuAtomicAdd(&this->uAtomicSemaphore, 1u);
|
||||
AuUInt32 uNext {};
|
||||
|
||||
#if 0
|
||||
if (AuAtomicLoad(&this->uAtomicKernelSemaphore) >= uNext)
|
||||
if (auto uMaxValue = this->uMaxCount)
|
||||
{
|
||||
return true;
|
||||
while (true)
|
||||
{
|
||||
auto uCurrentValue = AuAtomicLoad(&this->uAtomicSemaphore);
|
||||
uNext = uCurrentValue + 1;
|
||||
|
||||
if (uNext > uMaxValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AuAtomicCompareExchange(&this->uAtomicSemaphore, uNext, uCurrentValue) == uCurrentValue)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uNext = AuAtomicAdd(&this->uAtomicSemaphore, 1u);
|
||||
}
|
||||
|
||||
AuAtomicAdd(&this->uAtomicKernelSemaphore, 1u);
|
||||
#else
|
||||
while (true)
|
||||
{
|
||||
auto uCurrentValue = AuAtomicLoad(&this->uAtomicKernelSemaphore);
|
||||
@ -139,15 +157,36 @@ namespace Aurora::IO::Loop
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
LSSemaphore::AddOne();
|
||||
return true;
|
||||
return LSSemaphore::AddOne();
|
||||
}
|
||||
|
||||
bool LSLocalSemaphore::AddMany(AuUInt32 uCount)
|
||||
{
|
||||
auto uNext = AuAtomicAdd(&this->uAtomicSemaphore, uCount);
|
||||
AuUInt32 uNext {};
|
||||
|
||||
if (auto uMaxValue = this->uMaxCount)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
auto uCurrentValue = AuAtomicLoad(&this->uAtomicSemaphore);
|
||||
uNext = uCurrentValue + uCount;
|
||||
|
||||
if (uNext > uMaxValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AuAtomicCompareExchange(&this->uAtomicSemaphore, uNext, uCurrentValue) == uCurrentValue)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uNext = AuAtomicAdd(&this->uAtomicSemaphore, uCount);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (AuAtomicLoad(&this->uAtomicKernelSemaphore) >= uNext)
|
||||
@ -198,8 +237,8 @@ namespace Aurora::IO::Loop
|
||||
}
|
||||
}
|
||||
#endif
|
||||
LSSemaphore::AddMany(uCount);
|
||||
return true;
|
||||
|
||||
return LSSemaphore::AddMany(uCount);
|
||||
}
|
||||
|
||||
bool LSLocalSemaphore::IsSignaled()
|
||||
@ -307,7 +346,7 @@ namespace Aurora::IO::Loop
|
||||
|
||||
}
|
||||
|
||||
AUKN_SYM AuSPtr<ILSSemaphore> NewLSSemaphore(AuUInt32 initialCount)
|
||||
AUKN_SYM AuSPtr<ILSSemaphore> NewLSSemaphore(AuUInt32 uInitialCount)
|
||||
{
|
||||
auto pMutex = AuMakeShared<LSLocalSemaphore>();
|
||||
if (!pMutex)
|
||||
@ -316,7 +355,25 @@ namespace Aurora::IO::Loop
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!pMutex->TryInit(initialCount))
|
||||
if (!pMutex->TryInit(uInitialCount))
|
||||
{
|
||||
SysPushErrorNested();
|
||||
return {};
|
||||
}
|
||||
|
||||
return pMutex;
|
||||
}
|
||||
|
||||
AUKN_SYM AuSPtr<ILSSemaphore> NewLSSemaphoreEx(AuUInt32 uInitialCount, AuUInt32 uMaxCount)
|
||||
{
|
||||
auto pMutex = AuMakeShared<LSLocalSemaphore>();
|
||||
if (!pMutex)
|
||||
{
|
||||
SysPushErrorGeneric();
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!pMutex->TryInit(uInitialCount, uMaxCount))
|
||||
{
|
||||
SysPushErrorNested();
|
||||
return {};
|
||||
|
@ -16,7 +16,7 @@ namespace Aurora::IO::Loop
|
||||
LSLocalSemaphore();
|
||||
~LSLocalSemaphore();
|
||||
|
||||
bool TryInit(AuUInt32 initialCount);
|
||||
bool TryInit(AuUInt32 initialCount, AuUInt32 uMaxCount = 0);
|
||||
|
||||
bool IsSignaled() override;
|
||||
bool WaitOn(AuUInt32 timeout) override;
|
||||
@ -40,5 +40,6 @@ namespace Aurora::IO::Loop
|
||||
|
||||
AuAUInt32 uAtomicSemaphore {};
|
||||
AuAUInt32 uAtomicKernelSemaphore {};
|
||||
AuUInt32 uMaxCount {};
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user