[*] Resolve WakeOnAddress emu-mode bug and a potential dead-lock
This commit is contained in:
parent
b88c61c16d
commit
63b72a9fb5
@ -32,7 +32,7 @@ namespace Aurora::Threading
|
|||||||
|
|
||||||
static ProcessWaitContainer gProcessWaitables;
|
static ProcessWaitContainer gProcessWaitables;
|
||||||
static int gShouldSpinOnlyInCPU = 1; // TODO: havent decided
|
static int gShouldSpinOnlyInCPU = 1; // TODO: havent decided
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void DoSpinLockOnVar(T *uPointer)
|
static void DoSpinLockOnVar(T *uPointer)
|
||||||
{
|
{
|
||||||
@ -95,7 +95,7 @@ namespace Aurora::Threading
|
|||||||
AuResetMember(this->uSize);
|
AuResetMember(this->uSize);
|
||||||
AuResetMember(this->pAddress);
|
AuResetMember(this->pAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitEntry::WaitEntry()
|
WaitEntry::WaitEntry()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ namespace Aurora::Threading
|
|||||||
bool WaitEntry::SleepOn(WaitState &state)
|
bool WaitEntry::SleepOn(WaitState &state)
|
||||||
{
|
{
|
||||||
AU_LOCK_GUARD(this->mutex);
|
AU_LOCK_GUARD(this->mutex);
|
||||||
|
|
||||||
if (state.qwNanosecondsAbs)
|
if (state.qwNanosecondsAbs)
|
||||||
{
|
{
|
||||||
if (!WaitBuffer::Compare(this->pAddress, this->uSize, state))
|
if (!WaitBuffer::Compare(this->pAddress, this->uSize, state))
|
||||||
@ -132,7 +132,7 @@ namespace Aurora::Threading
|
|||||||
#if defined(AURORA_PLATFORM_WIN32)
|
#if defined(AURORA_PLATFORM_WIN32)
|
||||||
Win32DropSchedulerResolution();
|
Win32DropSchedulerResolution();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
this->variable.WaitForSignalNsEx(&this->mutex, uTimeRemNS);
|
this->variable.WaitForSignalNsEx(&this->mutex, uTimeRemNS);
|
||||||
|
|
||||||
uNow = AuTime::SteadyClockNS();
|
uNow = AuTime::SteadyClockNS();
|
||||||
@ -277,8 +277,11 @@ namespace Aurora::Threading
|
|||||||
Lock();
|
Lock();
|
||||||
if (auto pLoadFromMemory = this->waitList.pHead)
|
if (auto pLoadFromMemory = this->waitList.pHead)
|
||||||
{
|
{
|
||||||
pReturn->pNext = pLoadFromMemory;
|
if (pLoadFromMemory != pReturn)
|
||||||
pLoadFromMemory->pBefore = pReturn;
|
{
|
||||||
|
pReturn->pNext = pLoadFromMemory;
|
||||||
|
pLoadFromMemory->pBefore = pReturn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -313,7 +316,7 @@ namespace Aurora::Threading
|
|||||||
{
|
{
|
||||||
pLast->pNext = pCurrentHead->pNext;
|
pLast->pNext = pCurrentHead->pNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->waitList.pHead == pCurrentHead)
|
if (this->waitList.pHead == pCurrentHead)
|
||||||
{
|
{
|
||||||
this->waitList.pHead = pCurrentHead->pNext;
|
this->waitList.pHead = pCurrentHead->pNext;
|
||||||
@ -337,6 +340,11 @@ namespace Aurora::Threading
|
|||||||
}
|
}
|
||||||
|
|
||||||
pLast = pCurrentHead;
|
pLast = pCurrentHead;
|
||||||
|
|
||||||
|
if (pCurrentHead->pBefore == pCurrentHead)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
pCurrentHead = pCurrentHead->pBefore;
|
pCurrentHead = pCurrentHead->pBefore;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -345,6 +353,53 @@ namespace Aurora::Threading
|
|||||||
return bRetStatus;
|
return bRetStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProcessWaitNodeContainer::RemoveSelf(WaitEntry *pSelf)
|
||||||
|
{
|
||||||
|
Lock();
|
||||||
|
{
|
||||||
|
auto pCurrentHead = this->waitList.pTail;
|
||||||
|
decltype(pCurrentHead) pLast {};
|
||||||
|
|
||||||
|
while (pCurrentHead)
|
||||||
|
{
|
||||||
|
if (pCurrentHead == pSelf)
|
||||||
|
{
|
||||||
|
if (pLast)
|
||||||
|
{
|
||||||
|
pLast->pNext = pCurrentHead->pNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->waitList.pHead == pCurrentHead)
|
||||||
|
{
|
||||||
|
this->waitList.pHead = pCurrentHead->pNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pCurrentHead->pNext)
|
||||||
|
{
|
||||||
|
pCurrentHead->pNext->pBefore = pCurrentHead->pBefore;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->waitList.pTail == pCurrentHead)
|
||||||
|
{
|
||||||
|
this->waitList.pTail = pCurrentHead->pBefore;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pLast = pCurrentHead;
|
||||||
|
|
||||||
|
if (pCurrentHead->pBefore == pCurrentHead)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pCurrentHead = pCurrentHead->pBefore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
void ProcessWaitNodeContainer::Lock()
|
void ProcessWaitNodeContainer::Lock()
|
||||||
{
|
{
|
||||||
DoSpinLockOnVar(&this->uAtomic);
|
DoSpinLockOnVar(&this->uAtomic);
|
||||||
@ -376,6 +431,16 @@ namespace Aurora::Threading
|
|||||||
return this->list[AuHashCode(pAddressIDC) % AuArraySize(this->list)].IterateWake(callback);
|
return this->list[AuHashCode(pAddressIDC) % AuArraySize(this->list)].IterateWake(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProcessWaitContainer::RemoveSelf(const void *pAddress, WaitEntry *pSelf)
|
||||||
|
{
|
||||||
|
#if defined(FALLBACK_WAKEONADDRESS_SUPPORTS_NONEXACT_MATCHING)
|
||||||
|
auto pAddressIDC = (void *)(AuUInt(pAddress) & ~(8 - 1));
|
||||||
|
#else
|
||||||
|
auto pAddressIDC = pAddress;
|
||||||
|
#endif
|
||||||
|
return this->list[AuHashCode(pAddressIDC) % AuArraySize(this->list)].RemoveSelf(pSelf);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsNativeWaitOnSupported()
|
bool IsNativeWaitOnSupported()
|
||||||
{
|
{
|
||||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||||
@ -450,6 +515,12 @@ namespace Aurora::Threading
|
|||||||
#if defined(HACK_NO_INVALID_ACCESS_LEAK_SHARED_REF_ON_DESTROYED_THREAD)
|
#if defined(HACK_NO_INVALID_ACCESS_LEAK_SHARED_REF_ON_DESTROYED_THREAD)
|
||||||
pTempHoldMe.reset();
|
pTempHoldMe.reset();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!bResult)
|
||||||
|
{
|
||||||
|
gProcessWaitables.RemoveSelf(pTargetAddress, pWaitEntry);
|
||||||
|
}
|
||||||
|
|
||||||
return bResult;
|
return bResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +87,8 @@ namespace Aurora::Threading
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
bool IterateWake(T callback);
|
bool IterateWake(T callback);
|
||||||
|
|
||||||
|
void RemoveSelf(WaitEntry *pSelf);
|
||||||
|
|
||||||
void Lock();
|
void Lock();
|
||||||
|
|
||||||
void Unlock();
|
void Unlock();
|
||||||
@ -100,5 +102,7 @@ namespace Aurora::Threading
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool IterateWake(const void *pAddress, T callback);
|
bool IterateWake(const void *pAddress, T callback);
|
||||||
|
|
||||||
|
void RemoveSelf(const void *pAddress, WaitEntry *pSelf);
|
||||||
};
|
};
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user