[+] 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;
|
virtual bool Unlock() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IConditionVar : virtual ILoopSource
|
|
||||||
{
|
|
||||||
virtual bool Signal() = 0;
|
|
||||||
virtual bool Broadcast() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ITimer : virtual ILoopSource
|
struct ITimer : virtual ILoopSource
|
||||||
{
|
{
|
||||||
/* Warning: IO timers use wall time (CurrentClock[M/NS), not SteadyClock[M/N]S()).
|
/* 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;
|
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> NewLSMutex();
|
||||||
AUKN_SYM AuSPtr<ILSMutex> NewLSMutexSlow(); // interop-ready (usable with DbgLoopSourceToReadFd)
|
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> 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<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> 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> NewLSOSHandle(AuUInt);
|
||||||
AUKN_SYM AuSPtr<ILoopSource> NewLSAsync(Aurora::Async::WorkerPId_t workerPid);
|
AUKN_SYM AuSPtr<ILoopSource> NewLSAsync(Aurora::Async::WorkerPId_t workerPid); // warn: no IPC counterpart
|
||||||
AUKN_SYM AuSPtr<ILoopSource> NewLSFile(const AuSPtr<IO::IAsyncTransaction> &fileTransaction);
|
AUKN_SYM AuSPtr<ILoopSource> NewLSFile(const AuSPtr<IO::IAsyncTransaction> &fileTransaction); // warn: no IPC counterpart
|
||||||
AUKN_SYM AuSPtr<ILoopSource> NewStdIn();
|
AUKN_SYM AuSPtr<ILoopSource> NewStdIn();
|
||||||
AUKN_SYM AuSPtr<ILoopSource> NewLSWin32Source(bool dispatchMessages);
|
AUKN_SYM AuSPtr<ILoopSource> NewLSWin32Source(bool dispatchMessages);
|
||||||
AUKN_SYM AuSPtr<ILoopSource> NewLSAppleSource();
|
AUKN_SYM AuSPtr<ILoopSource> NewLSAppleSource();
|
||||||
AUKN_SYM AuSPtr<ILoopSource> NewLSIOHandle(const AuSPtr<IIOHandle> &pHandle);
|
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: Only works on singular loop sources
|
||||||
// warn: You should only use trust the interop-ready sources to serve the HANDLE/fd you expect.
|
// 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.
|
// 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))
|
if (!LSSemaphore::TryInit(initialCount))
|
||||||
{
|
{
|
||||||
@ -30,7 +30,7 @@ namespace Aurora::IO::Loop
|
|||||||
|
|
||||||
this->uAtomicSemaphore = initialCount;
|
this->uAtomicSemaphore = initialCount;
|
||||||
this->uAtomicKernelSemaphore = initialCount;
|
this->uAtomicKernelSemaphore = initialCount;
|
||||||
|
this->uMaxCount = uMaxCount;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,6 +81,9 @@ namespace Aurora::IO::Loop
|
|||||||
{
|
{
|
||||||
AuAtomicAdd(&this->uAtomicKernelSemaphore, uCount);
|
AuAtomicAdd(&this->uAtomicKernelSemaphore, uCount);
|
||||||
LSSemaphore::AddMany(uCount);
|
LSSemaphore::AddMany(uCount);
|
||||||
|
#if !defined(AURORA_IS_MODERNNT_DERIVED)
|
||||||
|
(void)LSSemaphore::OnTrigger(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
@ -102,16 +105,31 @@ namespace Aurora::IO::Loop
|
|||||||
|
|
||||||
bool LSLocalSemaphore::AddOne()
|
bool LSLocalSemaphore::AddOne()
|
||||||
{
|
{
|
||||||
auto uNext = AuAtomicAdd(&this->uAtomicSemaphore, 1u);
|
AuUInt32 uNext {};
|
||||||
|
|
||||||
#if 0
|
if (auto uMaxValue = this->uMaxCount)
|
||||||
if (AuAtomicLoad(&this->uAtomicKernelSemaphore) >= uNext)
|
|
||||||
{
|
{
|
||||||
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)
|
while (true)
|
||||||
{
|
{
|
||||||
auto uCurrentValue = AuAtomicLoad(&this->uAtomicKernelSemaphore);
|
auto uCurrentValue = AuAtomicLoad(&this->uAtomicKernelSemaphore);
|
||||||
@ -139,15 +157,36 @@ namespace Aurora::IO::Loop
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
LSSemaphore::AddOne();
|
return LSSemaphore::AddOne();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LSLocalSemaphore::AddMany(AuUInt32 uCount)
|
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 0
|
||||||
if (AuAtomicLoad(&this->uAtomicKernelSemaphore) >= uNext)
|
if (AuAtomicLoad(&this->uAtomicKernelSemaphore) >= uNext)
|
||||||
@ -198,8 +237,8 @@ namespace Aurora::IO::Loop
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
LSSemaphore::AddMany(uCount);
|
|
||||||
return true;
|
return LSSemaphore::AddMany(uCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LSLocalSemaphore::IsSignaled()
|
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>();
|
auto pMutex = AuMakeShared<LSLocalSemaphore>();
|
||||||
if (!pMutex)
|
if (!pMutex)
|
||||||
@ -316,7 +355,25 @@ namespace Aurora::IO::Loop
|
|||||||
return {};
|
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();
|
SysPushErrorNested();
|
||||||
return {};
|
return {};
|
||||||
|
@ -16,7 +16,7 @@ namespace Aurora::IO::Loop
|
|||||||
LSLocalSemaphore();
|
LSLocalSemaphore();
|
||||||
~LSLocalSemaphore();
|
~LSLocalSemaphore();
|
||||||
|
|
||||||
bool TryInit(AuUInt32 initialCount);
|
bool TryInit(AuUInt32 initialCount, AuUInt32 uMaxCount = 0);
|
||||||
|
|
||||||
bool IsSignaled() override;
|
bool IsSignaled() override;
|
||||||
bool WaitOn(AuUInt32 timeout) override;
|
bool WaitOn(AuUInt32 timeout) override;
|
||||||
@ -40,5 +40,6 @@ namespace Aurora::IO::Loop
|
|||||||
|
|
||||||
AuAUInt32 uAtomicSemaphore {};
|
AuAUInt32 uAtomicSemaphore {};
|
||||||
AuAUInt32 uAtomicKernelSemaphore {};
|
AuAUInt32 uAtomicKernelSemaphore {};
|
||||||
|
AuUInt32 uMaxCount {};
|
||||||
};
|
};
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user