Pump the event loop when waiting for a lock on the GUI thread
This solves a potential deadlock with DotX64dbg
This commit is contained in:
parent
d1f384e5bf
commit
becfa86ac6
|
@ -57,9 +57,12 @@ SectionLockerGlobal::owner_info SectionLockerGlobal::m_owner[SectionLock::LockLa
|
|||
CRITICAL_SECTION SectionLockerGlobal::m_crLocks[SectionLock::LockLast];
|
||||
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_InitializeSRWLock;
|
||||
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_AcquireSRWLockShared;
|
||||
SectionLockerGlobal::TRYSRWLOCKFUNCTION SectionLockerGlobal::m_TryAcquireSRWLockShared;
|
||||
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_AcquireSRWLockExclusive;
|
||||
SectionLockerGlobal::TRYSRWLOCKFUNCTION SectionLockerGlobal::m_TryAcquireSRWLockExclusive;
|
||||
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_ReleaseSRWLockShared;
|
||||
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_ReleaseSRWLockExclusive;
|
||||
DWORD SectionLockerGlobal::m_guiMainThreadId;
|
||||
|
||||
void SectionLockerGlobal::Initialize()
|
||||
{
|
||||
|
@ -68,17 +71,24 @@ void SectionLockerGlobal::Initialize()
|
|||
if(m_Initialized)
|
||||
return;
|
||||
|
||||
// This gets called on the same thread as the GUI
|
||||
m_guiMainThreadId = GetCurrentThreadId();
|
||||
|
||||
// Attempt to read the SRWLock API
|
||||
HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||
m_InitializeSRWLock = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "InitializeSRWLock");
|
||||
m_AcquireSRWLockShared = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "AcquireSRWLockShared");
|
||||
m_TryAcquireSRWLockShared = (TRYSRWLOCKFUNCTION)GetProcAddress(hKernel32, "TryAcquireSRWLockShared");
|
||||
m_AcquireSRWLockExclusive = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "AcquireSRWLockExclusive");
|
||||
m_TryAcquireSRWLockExclusive = (TRYSRWLOCKFUNCTION)GetProcAddress(hKernel32, "TryAcquireSRWLockExclusive");
|
||||
m_ReleaseSRWLockShared = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "ReleaseSRWLockShared");
|
||||
m_ReleaseSRWLockExclusive = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "ReleaseSRWLockExclusive");
|
||||
|
||||
m_SRWLocks = m_InitializeSRWLock &&
|
||||
m_AcquireSRWLockShared &&
|
||||
m_TryAcquireSRWLockShared &&
|
||||
m_AcquireSRWLockExclusive &&
|
||||
m_TryAcquireSRWLockExclusive &&
|
||||
m_ReleaseSRWLockShared &&
|
||||
m_ReleaseSRWLockExclusive;
|
||||
|
||||
|
|
|
@ -90,33 +90,63 @@ public:
|
|||
private:
|
||||
static inline void AcquireLock(SectionLock LockIndex, bool Shared)
|
||||
{
|
||||
auto threadId = GetCurrentThreadId();
|
||||
if(m_SRWLocks)
|
||||
{
|
||||
auto srwLock = &m_srwLocks[LockIndex];
|
||||
|
||||
if(Shared)
|
||||
{
|
||||
if(m_owner[LockIndex].thread == GetCurrentThreadId())
|
||||
if(m_owner[LockIndex].thread == threadId)
|
||||
return;
|
||||
|
||||
m_AcquireSRWLockShared(&m_srwLocks[LockIndex]);
|
||||
if(threadId == m_guiMainThreadId)
|
||||
{
|
||||
while(!m_TryAcquireSRWLockShared(srwLock))
|
||||
GuiProcessEvents();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_AcquireSRWLockShared(srwLock);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_owner[LockIndex].thread == GetCurrentThreadId())
|
||||
if(m_owner[LockIndex].thread == threadId)
|
||||
{
|
||||
assert(m_owner[LockIndex].count > 0);
|
||||
m_owner[LockIndex].count++;
|
||||
return;
|
||||
}
|
||||
|
||||
m_AcquireSRWLockExclusive(&m_srwLocks[LockIndex]);
|
||||
if(threadId == m_guiMainThreadId)
|
||||
{
|
||||
while(!m_TryAcquireSRWLockExclusive(srwLock))
|
||||
GuiProcessEvents();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_AcquireSRWLockExclusive(srwLock);
|
||||
}
|
||||
|
||||
assert(m_owner[LockIndex].thread == 0);
|
||||
assert(m_owner[LockIndex].count == 0);
|
||||
m_owner[LockIndex].thread = GetCurrentThreadId();
|
||||
m_owner[LockIndex].thread = threadId;
|
||||
m_owner[LockIndex].count = 1;
|
||||
}
|
||||
else
|
||||
EnterCriticalSection(&m_crLocks[LockIndex]);
|
||||
{
|
||||
auto cr = &m_crLocks[LockIndex];
|
||||
if(threadId == m_guiMainThreadId)
|
||||
{
|
||||
while(!TryEnterCriticalSection(cr))
|
||||
GuiProcessEvents();
|
||||
}
|
||||
else
|
||||
{
|
||||
EnterCriticalSection(cr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ReleaseLock(SectionLock LockIndex, bool Shared)
|
||||
|
@ -146,6 +176,7 @@ private:
|
|||
}
|
||||
|
||||
typedef void (WINAPI* SRWLOCKFUNCTION)(PSRWLOCK SWRLock);
|
||||
typedef BOOLEAN(WINAPI* TRYSRWLOCKFUNCTION)(PSRWLOCK SWRLock);
|
||||
|
||||
static bool m_Initialized;
|
||||
static bool m_SRWLocks;
|
||||
|
@ -155,9 +186,12 @@ private:
|
|||
static CRITICAL_SECTION m_crLocks[SectionLock::LockLast];
|
||||
static SRWLOCKFUNCTION m_InitializeSRWLock;
|
||||
static SRWLOCKFUNCTION m_AcquireSRWLockShared;
|
||||
static TRYSRWLOCKFUNCTION m_TryAcquireSRWLockShared;
|
||||
static SRWLOCKFUNCTION m_AcquireSRWLockExclusive;
|
||||
static TRYSRWLOCKFUNCTION m_TryAcquireSRWLockExclusive;
|
||||
static SRWLOCKFUNCTION m_ReleaseSRWLockShared;
|
||||
static SRWLOCKFUNCTION m_ReleaseSRWLockExclusive;
|
||||
static DWORD m_guiMainThreadId;
|
||||
};
|
||||
|
||||
template<SectionLock LockIndex, bool Shared>
|
||||
|
|
Loading…
Reference in New Issue