1
0
Fork 0
x64dbg/src/dbg/threading.h

210 lines
5.2 KiB
C++

#ifndef _THREADING_H
#define _THREADING_H
#include "_global.h"
enum WAIT_ID
{
WAITID_RUN,
WAITID_LAST
};
//functions
void waitclear();
void wait(WAIT_ID id);
bool waitfor(WAIT_ID id, unsigned int Milliseconds);
void lock(WAIT_ID id);
void unlock(WAIT_ID id);
bool waitislocked(WAIT_ID id);
void waitinitialize();
void waitdeinitialize();
//
// THREAD SYNCHRONIZATION
//
// Win Vista and newer: (Faster) SRW locks used
// Win 2003 and older: (Slower) Critical sections used
//
#define EXCLUSIVE_ACQUIRE(Index) SectionLocker<Index, false> __ThreadLock
#define EXCLUSIVE_REACQUIRE() __ThreadLock.Lock()
#define EXCLUSIVE_RELEASE() __ThreadLock.Unlock()
#define SHARED_ACQUIRE(Index) SectionLocker<Index, true> __SThreadLock
#define SHARED_REACQUIRE() __SThreadLock.Lock()
#define SHARED_RELEASE() __SThreadLock.Unlock()
enum SectionLock
{
LockMemoryPages,
LockVariables,
LockModules,
LockComments,
LockLabels,
LockBookmarks,
LockFunctions,
LockLoops,
LockBreakpoints,
LockPatches,
LockThreads,
LockSym,
LockCmdLine,
LockDatabase,
LockPluginList,
LockPluginCallbackList,
LockPluginCommandList,
LockPluginMenuList,
LockPluginExprfunctionList,
LockPluginFormatfunctionList,
LockSehCache,
LockMnemonicHelp,
LockTraceRecord,
LockCrossReferences,
LockDebugStartStop,
LockArguments,
LockEncodeMaps,
LockCallstackCache,
LockRunToUserCode,
LockWatch,
LockExpressionFunctions,
LockHistory,
LockSymbolCache,
LockLineCache,
LockTypeManager,
LockModuleHashes,
LockFormatFunctions,
LockDllBreakpoints,
// Number of elements in this enumeration. Must always be the last index.
LockLast
};
class SectionLockerGlobal
{
template<SectionLock LockIndex, bool Shared>
friend class SectionLocker;
public:
static void Initialize();
static void Deinitialize();
private:
static inline void AcquireLock(SectionLock LockIndex, bool Shared)
{
if(m_SRWLocks)
{
if(Shared)
{
if(m_owner[LockIndex].thread == GetCurrentThreadId())
return;
m_AcquireSRWLockShared(&m_srwLocks[LockIndex]);
return;
}
if(m_owner[LockIndex].thread == GetCurrentThreadId())
{
assert(m_owner[LockIndex].count > 0);
m_owner[LockIndex].count++;
return;
}
m_AcquireSRWLockExclusive(&m_srwLocks[LockIndex]);
assert(m_owner[LockIndex].thread == 0);
assert(m_owner[LockIndex].count == 0);
m_owner[LockIndex].thread = GetCurrentThreadId();
m_owner[LockIndex].count = 1;
}
else
EnterCriticalSection(&m_crLocks[LockIndex]);
}
static inline void ReleaseLock(SectionLock LockIndex, bool Shared)
{
if(m_SRWLocks)
{
if(Shared)
{
if(m_owner[LockIndex].thread == GetCurrentThreadId())
return;
m_ReleaseSRWLockShared(&m_srwLocks[LockIndex]);
return;
}
assert(m_owner[LockIndex].count && m_owner[LockIndex].thread);
m_owner[LockIndex].count--;
if(m_owner[LockIndex].count == 0)
{
m_owner[LockIndex].thread = 0;
m_ReleaseSRWLockExclusive(&m_srwLocks[LockIndex]);
}
}
else
LeaveCriticalSection(&m_crLocks[LockIndex]);
}
typedef void (WINAPI* SRWLOCKFUNCTION)(PSRWLOCK SWRLock);
static bool m_Initialized;
static bool m_SRWLocks;
struct owner_info { DWORD thread; size_t count; };
static owner_info m_owner[SectionLock::LockLast];
static SRWLOCK m_srwLocks[SectionLock::LockLast];
static CRITICAL_SECTION m_crLocks[SectionLock::LockLast];
static SRWLOCKFUNCTION m_InitializeSRWLock;
static SRWLOCKFUNCTION m_AcquireSRWLockShared;
static SRWLOCKFUNCTION m_AcquireSRWLockExclusive;
static SRWLOCKFUNCTION m_ReleaseSRWLockShared;
static SRWLOCKFUNCTION m_ReleaseSRWLockExclusive;
};
template<SectionLock LockIndex, bool Shared>
class SectionLocker
{
public:
SectionLocker()
{
m_LockCount = 0;
Lock();
}
~SectionLocker()
{
if(m_LockCount > 0)
Unlock();
// The lock count should be zero after destruction.
assert(m_LockCount == 0);
}
inline void Lock()
{
Internal::AcquireLock(LockIndex, Shared);
// We cannot recursively lock more than 255 times.
assert(m_LockCount < 255);
m_LockCount++;
}
inline void Unlock()
{
// Unlocking twice will cause undefined behaviour.
assert(m_LockCount != 0);
m_LockCount--;
Internal::ReleaseLock(LockIndex, Shared);
}
protected:
BYTE m_LockCount;
private:
using Internal = SectionLockerGlobal;
};
#endif // _THREADING_H