#pragma once #include "_global.h" enum WAIT_ID { WAITID_RUN, WAITID_STOP, WAITID_LAST }; //functions void waitclear(); void wait(WAIT_ID id); void lock(WAIT_ID id); void unlock(WAIT_ID id); bool waitislocked(WAIT_ID id); void waitinitialize(); void waitdeinitialize(); // // THREAD SYNCHRONIZATION // // Better, but requires VISTA+ // https://msdn.microsoft.com/en-us/library/windows/desktop/aa904937%28v=vs.85%29.aspx // #define EXCLUSIVE_ACQUIRE(Index) SectionLocker __ThreadLock; #define EXCLUSIVE_REACQUIRE() __ThreadLock.Lock(); #define EXCLUSIVE_RELEASE() __ThreadLock.Unlock(); #define SHARED_ACQUIRE(Index) SectionLocker __SThreadLock; #define SHARED_REACQUIRE() __SThreadLock.Lock(); #define SHARED_RELEASE() __SThreadLock.Unlock(); enum SectionLock { LockMemoryPages, LockVariables, LockModules, LockComments, LockLabels, LockBookmarks, LockFunctions, LockLoops, LockBreakpoints, LockPatches, LockThreads, LockDprintf, LockSym, // This is defined because of a bug in the Windows 8.1 kernel; // Calling VirtualQuery/VirtualProtect/ReadProcessMemory can and will cause // a deadlock. // https://bitbucket.org/mrexodia/x64_dbg/issue/247/x64-dbg-bug-string-references-function LockWin8Workaround, LockPluginList, LockPluginCallbackList, LockPluginCommandList, LockPluginMenuList, LockLast, }; class SectionLockerGlobal { template friend class SectionLocker; public: static void Initialize(); static void Deinitialize(); static inline void AcquireLock(SectionLock LockIndex, bool Shared) { Initialize(); // Locks can be accessed before we know when to initialize if(m_SRWLocks) { if(Shared) m_AcquireSRWLockShared(&m_srwLocks[LockIndex]); else m_AcquireSRWLockExclusive(&m_srwLocks[LockIndex]); } else EnterCriticalSection(&m_crLocks[LockIndex]); } static inline void ReleaseLock(SectionLock LockIndex, bool Shared) { if(m_SRWLocks) { if(Shared) m_ReleaseSRWLockShared(&m_srwLocks[LockIndex]); else m_ReleaseSRWLockExclusive(&m_srwLocks[LockIndex]); } else LeaveCriticalSection(&m_crLocks[LockIndex]); } private: typedef void (WINAPI* SRWLOCKFUNCTION)(PSRWLOCK SWRLock); static bool m_Initialized; static bool m_SRWLocks; 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 class SectionLocker { public: SectionLocker() { m_LockCount = 0; Lock(); } ~SectionLocker() { if(m_LockCount > 0) Unlock(); #ifdef _DEBUG // TODO: Assert that the lock count is zero on destructor if(m_LockCount > 0) __debugbreak(); #endif } inline void Lock() { Internal::AcquireLock(LockIndex, Shared); m_LockCount++; } inline void Unlock() { m_LockCount--; Internal::ReleaseLock(LockIndex, Shared); } private: using Internal = SectionLockerGlobal; protected: BYTE m_LockCount; };