[*] LSLocalSemaphore bug fix for scriptability. (TODO: reimpl like the event?)
[*] Fix: IO objects not using the explicit slow sync primitives. Dunno how these werent refactored; then again, i never properly got around to finishing the factories for fast/slow io objects. In addition, some of these arent even accessed by the ILoopSource interface, so it's not as critical of a failure.
This commit is contained in:
parent
9956f1c153
commit
5cafefae5d
@ -92,7 +92,7 @@ namespace Aurora::IO::IPC
|
|||||||
{
|
{
|
||||||
if (serverHandle != INVALID_HANDLE_VALUE)
|
if (serverHandle != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
this->hasClient_ = Loop::NewLSEvent(false, false, true);
|
this->hasClient_ = Loop::NewLSEventSlow(false, false, true);
|
||||||
if (!this->hasClient_)
|
if (!this->hasClient_)
|
||||||
{
|
{
|
||||||
this->bDead = true;
|
this->bDead = true;
|
||||||
|
@ -34,6 +34,15 @@ namespace Aurora::IO::Loop
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LSLocalSemaphore::DoParanoia()
|
||||||
|
{
|
||||||
|
if (auto uCount = AuAtomicLoad(&this->uAtomicSemaphore))
|
||||||
|
{
|
||||||
|
AuAtomicAdd(&this->uAtomicKernelSemaphore, uCount);
|
||||||
|
LSSemaphore::AddMany(uCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool LSLocalSemaphore::OnTrigger(AuUInt handle)
|
bool LSLocalSemaphore::OnTrigger(AuUInt handle)
|
||||||
{
|
{
|
||||||
auto bRet = this->TryTakeNoSpin();
|
auto bRet = this->TryTakeNoSpin();
|
||||||
@ -41,10 +50,11 @@ namespace Aurora::IO::Loop
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
auto uOld = this->uAtomicKernelSemaphore;
|
auto uOld = AuAtomicLoad(&this->uAtomicKernelSemaphore);
|
||||||
|
|
||||||
if (uOld == 0)
|
if (uOld == 0)
|
||||||
{
|
{
|
||||||
|
DoParanoia();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,11 +64,25 @@ namespace Aurora::IO::Loop
|
|||||||
|
|
||||||
if (uOld - 1 == 0)
|
if (uOld - 1 == 0)
|
||||||
{
|
{
|
||||||
|
#if defined(AURORA_PLATFORM_LINUX)
|
||||||
|
if (uCount == 1)
|
||||||
|
{
|
||||||
|
// Don't acknowledge?
|
||||||
|
// Don't write into?
|
||||||
|
// saves two syscalls for nothang
|
||||||
|
}
|
||||||
|
else if (uCount)
|
||||||
|
{
|
||||||
|
AuAtomicAdd(&this->uAtomicKernelSemaphore, uCount - 1);
|
||||||
|
LSSemaphore::AddMany(uCount - 1);
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (uCount)
|
if (uCount)
|
||||||
{
|
{
|
||||||
AuAtomicAdd(&this->uAtomicKernelSemaphore, uCount);
|
AuAtomicAdd(&this->uAtomicKernelSemaphore, uCount);
|
||||||
LSSemaphore::AddMany(uCount);
|
LSSemaphore::AddMany(uCount);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
(void)LSSemaphore::OnTrigger(0);
|
(void)LSSemaphore::OnTrigger(0);
|
||||||
@ -89,26 +113,100 @@ namespace Aurora::IO::Loop
|
|||||||
{
|
{
|
||||||
auto uNext = AuAtomicAdd(&this->uAtomicSemaphore, 1u);
|
auto uNext = AuAtomicAdd(&this->uAtomicSemaphore, 1u);
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (AuAtomicLoad(&this->uAtomicKernelSemaphore) >= uNext)
|
if (AuAtomicLoad(&this->uAtomicKernelSemaphore) >= uNext)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
AuAtomicAdd(&this->uAtomicKernelSemaphore, 1u);
|
AuAtomicAdd(&this->uAtomicKernelSemaphore, 1u);
|
||||||
|
#else
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
auto uCurrentValue = AuAtomicLoad(&this->uAtomicKernelSemaphore);
|
||||||
|
auto uNextValue = uCurrentValue;
|
||||||
|
bool bCanReturn = false;
|
||||||
|
|
||||||
|
if (uCurrentValue < uNext)
|
||||||
|
{
|
||||||
|
uNextValue = uNext;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bCanReturn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AuAtomicCompareExchange(&this->uAtomicKernelSemaphore, uNextValue, uCurrentValue) == uCurrentValue)
|
||||||
|
{
|
||||||
|
if (bCanReturn)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
LSSemaphore::AddOne();
|
LSSemaphore::AddOne();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LSLocalSemaphore::AddMany(AuUInt32 uCount)
|
bool LSLocalSemaphore::AddMany(AuUInt32 uCount)
|
||||||
{
|
{
|
||||||
auto uNext = AuAtomicAdd(&this->uAtomicSemaphore, 1u);
|
auto uNext = AuAtomicAdd(&this->uAtomicSemaphore, uCount);
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (AuAtomicLoad(&this->uAtomicKernelSemaphore) >= uNext)
|
if (AuAtomicLoad(&this->uAtomicKernelSemaphore) >= uNext)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* if AddMany add/load/kernel-wake race condition, it's the next AddMany persons problem. */
|
||||||
|
/* uAtomicKernelSemaphore cannot be lower than uAtomicSemaphore, at the epilogue of the last unlock/adds tick. */
|
||||||
|
|
||||||
|
/* If it somehow is, ::OnTrigger will check that the final kernel negative increment does not occur just before (linux) after (win32) (bool(this->uAtomicSemaphore)). */
|
||||||
|
/* Remember: this->uAtomicKernelSemaphore should only be decremented after uAtomicSemaphore and uAtomicKernelSemaphore have already been incremented together... */
|
||||||
|
/* ...therefore, the last kernel waker should always see bool(this->uAtomicSemaphore), unless stolen by another thread. */
|
||||||
|
/* if stolen, it's a race condition we dont care about; we avoided the kernel object and state entirely. We have to wait for another AddMany to wake us up. */
|
||||||
|
/* if not stolen, uAtomicSemaphore is read as non-zero, and is readded to the kernel semaphore */
|
||||||
|
|
||||||
|
/* Most users just use the IO event objects LSAsync and LSLocalEvent. These are known good. */
|
||||||
|
}
|
||||||
AuAtomicAdd(&this->uAtomicKernelSemaphore, uCount);
|
AuAtomicAdd(&this->uAtomicKernelSemaphore, uCount);
|
||||||
|
#else
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
auto uCurrentValue = AuAtomicLoad(&this->uAtomicKernelSemaphore);
|
||||||
|
auto uNextValue = uCurrentValue;
|
||||||
|
bool bCanReturn = false;
|
||||||
|
|
||||||
|
if (uCurrentValue < uNext)
|
||||||
|
{
|
||||||
|
uNextValue = uNext;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bCanReturn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AuAtomicCompareExchange(&this->uAtomicKernelSemaphore, uNextValue, uCurrentValue) == uCurrentValue)
|
||||||
|
{
|
||||||
|
if (bCanReturn)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uCount = uNext - uCurrentValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
LSSemaphore::AddMany(uCount);
|
LSSemaphore::AddMany(uCount);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,8 @@ namespace Aurora::IO::Loop
|
|||||||
void OnPresleep() override;
|
void OnPresleep() override;
|
||||||
void OnFinishSleep() override;
|
void OnFinishSleep() override;
|
||||||
|
|
||||||
|
void DoParanoia();
|
||||||
|
|
||||||
AuAUInt32 uAtomicSemaphore {};
|
AuAUInt32 uAtomicSemaphore {};
|
||||||
AuAUInt32 uAtomicKernelSemaphore {};
|
AuAUInt32 uAtomicKernelSemaphore {};
|
||||||
};
|
};
|
||||||
|
@ -17,7 +17,7 @@ namespace Aurora::IO::Net
|
|||||||
SocketOverlappedOperation::SocketOverlappedOperation(bool bMultipleTrigger) :
|
SocketOverlappedOperation::SocketOverlappedOperation(bool bMultipleTrigger) :
|
||||||
bMultipleTrigger(bMultipleTrigger)
|
bMultipleTrigger(bMultipleTrigger)
|
||||||
{
|
{
|
||||||
this->pEvent = AuLoop::NewLSEvent(false, true);
|
this->pEvent = AuLoop::NewLSEventSlow(false, true);
|
||||||
if (!this->pEvent)
|
if (!this->pEvent)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -17,7 +17,7 @@ namespace Aurora::IO::Net
|
|||||||
SocketOverlappedOperation::SocketOverlappedOperation(bool bMultipleTrigger) :
|
SocketOverlappedOperation::SocketOverlappedOperation(bool bMultipleTrigger) :
|
||||||
bMultipleTrigger(bMultipleTrigger)
|
bMultipleTrigger(bMultipleTrigger)
|
||||||
{
|
{
|
||||||
this->pEvent = AuLoop::NewLSEvent(false, true);
|
this->pEvent = AuLoop::NewLSEventSlow(false, true);
|
||||||
if (!this->pEvent)
|
if (!this->pEvent)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -508,7 +508,7 @@ namespace Aurora::IO::Net
|
|||||||
|
|
||||||
void NtAsyncNetworkTransaction::MakeSyncable()
|
void NtAsyncNetworkTransaction::MakeSyncable()
|
||||||
{
|
{
|
||||||
this->pWaitable = AuLoop::NewLSEvent(false, true);
|
this->pWaitable = AuLoop::NewLSEventSlow(false, true);
|
||||||
SysAssert(this->pWaitable);
|
SysAssert(this->pWaitable);
|
||||||
this->overlap.hEvent = (HANDLE)AuStaticCast<Loop::LSEvent>(this->pWaitable)->GetHandle();
|
this->overlap.hEvent = (HANDLE)AuStaticCast<Loop::LSEvent>(this->pWaitable)->GetHandle();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user