Begin using shared locks
This commit is contained in:
parent
ff52bc2321
commit
0a69aa95e9
|
@ -1,7 +1,7 @@
|
|||
#ifndef _GLOBAL_H
|
||||
#define _GLOBAL_H
|
||||
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#define WINVER 0x0501
|
||||
#define _WIN32_IE 0x0500
|
||||
|
||||
|
|
|
@ -2197,6 +2197,7 @@ void errorinit()
|
|||
const char* errornamefromcode(unsigned int ErrorCode)
|
||||
{
|
||||
if(!errorNames.count(ErrorCode))
|
||||
return 0;
|
||||
return nullptr;
|
||||
|
||||
return errorNames[ErrorCode];
|
||||
}
|
|
@ -77,10 +77,12 @@ bool modload(uint base, uint size, const char* fullpath)
|
|||
|
||||
bool modunload(uint base)
|
||||
{
|
||||
CriticalSectionLocker locker(LockModules);
|
||||
EXCLUSIVE_ACQUIRE(LockModules);
|
||||
|
||||
const ModulesInfo::iterator found = modinfo.find(Range(base, base));
|
||||
if(found == modinfo.end()) //not found
|
||||
return false;
|
||||
|
||||
modinfo.erase(found);
|
||||
symupdatemodulelist();
|
||||
return true;
|
||||
|
@ -88,8 +90,12 @@ bool modunload(uint base)
|
|||
|
||||
void modclear()
|
||||
{
|
||||
CriticalSectionLocker locker(LockModules);
|
||||
ModulesInfo().swap(modinfo);
|
||||
EXCLUSIVE_ACQUIRE(LockModules);
|
||||
|
||||
// Remove all modules in the list
|
||||
modinfo.clear();
|
||||
|
||||
// Tell the symbol updater
|
||||
symupdatemodulelist();
|
||||
}
|
||||
|
||||
|
@ -97,98 +103,143 @@ bool modnamefromaddr(uint addr, char* modname, bool extension)
|
|||
{
|
||||
if(!modname)
|
||||
return false;
|
||||
*modname = '\0';
|
||||
CriticalSectionLocker locker(LockModules);
|
||||
const ModulesInfo::iterator found = modinfo.find(Range(addr, addr));
|
||||
if(found == modinfo.end()) //not found
|
||||
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
|
||||
// Was the module found with this address?
|
||||
auto found = modinfo.find(Range(addr, addr));
|
||||
|
||||
if(found == modinfo.end())
|
||||
return false;
|
||||
String mod = found->second.name;
|
||||
|
||||
// Zero buffer first
|
||||
memset(modname, 0, MAX_MODULE_SIZE);
|
||||
|
||||
// Append the module path/name
|
||||
strcat_s(modname, MAX_MODULE_SIZE, found->second.name);
|
||||
|
||||
// Append the extension
|
||||
if(extension)
|
||||
mod += found->second.extension;
|
||||
strcpy_s(modname, MAX_MODULE_SIZE, mod.c_str());
|
||||
strcat_s(modname, MAX_MODULE_SIZE, found->second.extension);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint modbasefromaddr(uint addr)
|
||||
{
|
||||
CriticalSectionLocker locker(LockModules);
|
||||
const ModulesInfo::iterator found = modinfo.find(Range(addr, addr));
|
||||
if(found == modinfo.end()) //not found
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
|
||||
// Was the module found with this address?
|
||||
auto found = modinfo.find(Range(addr, addr));
|
||||
|
||||
if(found == modinfo.end())
|
||||
return 0;
|
||||
|
||||
return found->second.base;
|
||||
}
|
||||
|
||||
uint modhashfromva(uint va) //return a unique hash from a VA
|
||||
uint modhashfromva(uint va)
|
||||
{
|
||||
CriticalSectionLocker locker(LockModules);
|
||||
const ModulesInfo::iterator found = modinfo.find(Range(va, va));
|
||||
if(found == modinfo.end()) //not found
|
||||
//
|
||||
// Returns a unique hash from a virtual address
|
||||
//
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
|
||||
// Was the module found with this address?
|
||||
auto found = modinfo.find(Range(va, va));
|
||||
|
||||
if(found == modinfo.end())
|
||||
return va;
|
||||
|
||||
return found->second.hash + (va - found->second.base);
|
||||
}
|
||||
|
||||
uint modhashfromname(const char* mod) //return MODINFO.hash
|
||||
uint modhashfromname(const char* mod)
|
||||
{
|
||||
if(!mod or !*mod)
|
||||
//
|
||||
// return MODINFO.hash (based on the name)
|
||||
//
|
||||
if(!mod || !mod[0])
|
||||
return 0;
|
||||
int len = (int)strlen(mod);
|
||||
return murmurhash(mod, len);
|
||||
|
||||
return murmurhash(mod, (int)strlen(mod));
|
||||
}
|
||||
|
||||
uint modbasefromname(const char* modname)
|
||||
{
|
||||
if(!modname or strlen(modname) >= MAX_MODULE_SIZE)
|
||||
if(!modname || strlen(modname) >= MAX_MODULE_SIZE)
|
||||
return 0;
|
||||
CriticalSectionLocker locker(LockModules);
|
||||
for(ModulesInfo::iterator i = modinfo.begin(); i != modinfo.end(); ++i)
|
||||
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
|
||||
for(auto itr = modinfo.begin(); itr != modinfo.end(); itr++)
|
||||
{
|
||||
MODINFO* curMod = &i->second;
|
||||
char curmodname[MAX_MODULE_SIZE] = "";
|
||||
sprintf(curmodname, "%s%s", curMod->name, curMod->extension);
|
||||
if(!_stricmp(curmodname, modname)) //with extension
|
||||
return curMod->base;
|
||||
if(!_stricmp(curMod->name, modname)) //without extension
|
||||
return curMod->base;
|
||||
char curmodname[MAX_MODULE_SIZE];
|
||||
sprintf(curmodname, "%s%s", itr->second.name, itr->second.extension);
|
||||
|
||||
// Test with extension
|
||||
if(!_stricmp(curmodname, modname))
|
||||
return itr->second.base;
|
||||
|
||||
// Test without extension
|
||||
if(!_stricmp(itr->second.name, modname))
|
||||
return itr->second.base;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint modsizefromaddr(uint addr)
|
||||
{
|
||||
CriticalSectionLocker locker(LockModules);
|
||||
const ModulesInfo::iterator found = modinfo.find(Range(addr, addr));
|
||||
if(found == modinfo.end()) //not found
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
|
||||
// Was the module found with this address?
|
||||
auto found = modinfo.find(Range(addr, addr));
|
||||
|
||||
if(found == modinfo.end())
|
||||
return 0;
|
||||
|
||||
return found->second.size;
|
||||
}
|
||||
|
||||
bool modsectionsfromaddr(uint addr, std::vector<MODSECTIONINFO>* sections)
|
||||
{
|
||||
CriticalSectionLocker locker(LockModules);
|
||||
const ModulesInfo::iterator found = modinfo.find(Range(addr, addr));
|
||||
if(found == modinfo.end()) //not found
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
|
||||
// Was the module found with this address?
|
||||
auto found = modinfo.find(Range(addr, addr));
|
||||
|
||||
if(found == modinfo.end())
|
||||
return false;
|
||||
|
||||
// Copy vector <-> vector
|
||||
*sections = found->second.sections;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint modentryfromaddr(uint addr)
|
||||
{
|
||||
CriticalSectionLocker locker(LockModules);
|
||||
const ModulesInfo::iterator found = modinfo.find(Range(addr, addr));
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
|
||||
// Was the module found with this address?
|
||||
auto found = modinfo.find(Range(addr, addr));
|
||||
|
||||
if(found == modinfo.end()) //not found
|
||||
return 0;
|
||||
|
||||
return found->second.entry;
|
||||
}
|
||||
|
||||
int modpathfromaddr(duint addr, char* path, int size)
|
||||
{
|
||||
Memory<wchar_t*> wszModPath(size * sizeof(wchar_t), "modpathfromaddr:wszModPath");
|
||||
|
||||
if(!GetModuleFileNameExW(fdProcessInfo->hProcess, (HMODULE)modbasefromaddr(addr), wszModPath, size))
|
||||
{
|
||||
*path = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy_s(path, size, StringUtils::Utf16ToUtf8(wszModPath()).c_str());
|
||||
return (int)strlen(path);
|
||||
}
|
||||
|
@ -196,4 +247,4 @@ int modpathfromaddr(duint addr, char* path, int size)
|
|||
int modpathfromname(const char* modname, char* path, int size)
|
||||
{
|
||||
return modpathfromaddr(modbasefromname(modname), path, size);
|
||||
}
|
||||
}
|
|
@ -65,7 +65,7 @@ void threadclear()
|
|||
bool ThreadGetTeb(uint TEBAddress, TEB* Teb)
|
||||
{
|
||||
//
|
||||
// TODO: Keep a cached copy of this inside of the vector
|
||||
// TODO: Keep a cached copy inside the vector
|
||||
//
|
||||
memset(Teb, 0, sizeof(TEB));
|
||||
|
||||
|
@ -107,7 +107,7 @@ DWORD ThreadGetLastError(uint tebAddress)
|
|||
TEB teb;
|
||||
if(!ThreadGetTeb(tebAddress, &teb))
|
||||
{
|
||||
// TODO: Assert
|
||||
// TODO: Assert (Why would the TEB fail?)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ DWORD ThreadGetLastError(uint tebAddress)
|
|||
|
||||
void ThreadGetList(THREADLIST* list)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockThreads);
|
||||
SHARED_ACQUIRE(LockThreads);
|
||||
|
||||
//
|
||||
// This function converts a C++ std::vector to a C-style THREADLIST[]
|
||||
|
@ -151,7 +151,7 @@ void ThreadGetList(THREADLIST* list)
|
|||
|
||||
bool ThreadIsValid(DWORD dwThreadId)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockThreads);
|
||||
SHARED_ACQUIRE(LockThreads);
|
||||
|
||||
for(auto itr = threadList.begin(); itr != threadList.end(); itr++)
|
||||
{
|
||||
|
@ -166,6 +166,7 @@ bool ThreadSetName(DWORD dwThreadId, const char* name)
|
|||
{
|
||||
EXCLUSIVE_ACQUIRE(LockThreads);
|
||||
|
||||
// This modifies a variable (name), so an exclusive lock is required
|
||||
for(auto itr = threadList.begin(); itr != threadList.end(); itr++)
|
||||
{
|
||||
if(itr->ThreadId == dwThreadId)
|
||||
|
@ -182,7 +183,7 @@ bool ThreadSetName(DWORD dwThreadId, const char* name)
|
|||
|
||||
HANDLE ThreadGetHandle(DWORD dwThreadId)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockThreads);
|
||||
SHARED_ACQUIRE(LockThreads);
|
||||
|
||||
for(auto itr = threadList.begin(); itr != threadList.end(); itr++)
|
||||
{
|
||||
|
@ -197,16 +198,24 @@ HANDLE ThreadGetHandle(DWORD dwThreadId)
|
|||
|
||||
DWORD ThreadGetId(HANDLE hThread)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockThreads);
|
||||
SHARED_ACQUIRE(LockThreads);
|
||||
|
||||
// Search for the ID in the local list
|
||||
for(auto itr = threadList.begin(); itr != threadList.end(); itr++)
|
||||
{
|
||||
if(itr->Handle == hThread)
|
||||
return itr->ThreadId;
|
||||
}
|
||||
|
||||
// Wasn't found, check with Windows
|
||||
// This also returns 0 on error
|
||||
/*
|
||||
REQUIRES VISTA+
|
||||
|
||||
return GetThreadId(hThread);
|
||||
*/
|
||||
|
||||
// TODO: Same problem with threadgethandle()
|
||||
// TODO: Different handles can map to the same thread
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -217,7 +226,10 @@ int ThreadGetCount()
|
|||
|
||||
int ThreadSuspendAll()
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockThreads);
|
||||
//
|
||||
// SuspendThread does not modify any internal variables
|
||||
//
|
||||
SHARED_ACQUIRE(LockThreads);
|
||||
|
||||
int count = 0;
|
||||
for(auto itr = threadList.begin(); itr != threadList.end(); itr++)
|
||||
|
@ -231,6 +243,9 @@ int ThreadSuspendAll()
|
|||
|
||||
int ThreadResumeAll()
|
||||
{
|
||||
//
|
||||
// ResumeThread does not modify any internal variables
|
||||
//
|
||||
EXCLUSIVE_ACQUIRE(LockThreads);
|
||||
|
||||
int count = 0;
|
||||
|
|
|
@ -29,7 +29,7 @@ bool waitislocked(WAIT_ID id)
|
|||
}
|
||||
|
||||
bool CriticalSectionLocker::m_Initialized = false;
|
||||
CRITICAL_SECTION CriticalSectionLocker::m_Locks[LockLast];
|
||||
SRWLOCK CriticalSectionLocker::m_Locks[LockLast];
|
||||
|
||||
void CriticalSectionLocker::Initialize()
|
||||
{
|
||||
|
@ -40,7 +40,7 @@ void CriticalSectionLocker::Initialize()
|
|||
memset(m_Locks, 0, sizeof(m_Locks));
|
||||
|
||||
for(int i = 0; i < LockLast; i++)
|
||||
InitializeCriticalSection(&m_Locks[i]);
|
||||
InitializeSRWLock(&m_Locks[i]);
|
||||
|
||||
m_Initialized = true;
|
||||
}
|
||||
|
@ -53,28 +53,28 @@ void CriticalSectionLocker::Deinitialize()
|
|||
for(int i = 0; i < LockLast; i++)
|
||||
{
|
||||
// Wait for the lock's ownership to be released
|
||||
EnterCriticalSection(&m_Locks[i]);
|
||||
LeaveCriticalSection(&m_Locks[i]);
|
||||
AcquireSRWLockExclusive(&m_Locks[i]);
|
||||
ReleaseSRWLockExclusive(&m_Locks[i]);
|
||||
|
||||
// Render the lock data invalid
|
||||
DeleteCriticalSection(&m_Locks[i]);
|
||||
// Invalidate data
|
||||
memset(&m_Locks[i], 0, sizeof(SRWLOCK));
|
||||
}
|
||||
|
||||
m_Initialized = false;
|
||||
}
|
||||
|
||||
CriticalSectionLocker::CriticalSectionLocker(CriticalSectionLock LockIndex)
|
||||
CriticalSectionLocker::CriticalSectionLocker(CriticalSectionLock LockIndex, bool Shared)
|
||||
{
|
||||
m_Section = &m_Locks[LockIndex];
|
||||
m_Lock = &m_Locks[LockIndex];
|
||||
m_LockCount = 0;
|
||||
|
||||
Lock();
|
||||
Lock(Shared);
|
||||
}
|
||||
|
||||
CriticalSectionLocker::~CriticalSectionLocker()
|
||||
{
|
||||
if(m_LockCount > 0)
|
||||
LeaveCriticalSection(m_Section);
|
||||
Unlock();
|
||||
|
||||
// TODO: Assert that the lock count is zero on destructor
|
||||
}
|
||||
|
@ -82,24 +82,20 @@ CriticalSectionLocker::~CriticalSectionLocker()
|
|||
void CriticalSectionLocker::Unlock()
|
||||
{
|
||||
m_LockCount--;
|
||||
LeaveCriticalSection(m_Section);
|
||||
|
||||
if(m_Shared)
|
||||
ReleaseSRWLockShared(m_Lock);
|
||||
else
|
||||
ReleaseSRWLockExclusive(m_Lock);
|
||||
}
|
||||
|
||||
void CriticalSectionLocker::Lock()
|
||||
void CriticalSectionLocker::Lock(bool Shared)
|
||||
{
|
||||
EnterCriticalSection(m_Section);
|
||||
if(Shared)
|
||||
AcquireSRWLockShared(m_Lock);
|
||||
else
|
||||
AcquireSRWLockExclusive(m_Lock);
|
||||
|
||||
m_Shared = Shared;
|
||||
m_LockCount++;
|
||||
}
|
||||
|
||||
bool CriticalSectionLocker::TryLock()
|
||||
{
|
||||
// Only enter the critical section if it's currently owned by the
|
||||
// thread, or if it is not being used at all
|
||||
if(TryEnterCriticalSection(m_Section))
|
||||
{
|
||||
Lock();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -18,9 +18,19 @@ void lock(WAIT_ID id);
|
|||
void unlock(WAIT_ID id);
|
||||
bool waitislocked(WAIT_ID id);
|
||||
|
||||
#define EXCLUSIVE_ACQUIRE(Index) CriticalSectionLocker __ThreadLock(Index);
|
||||
//
|
||||
// 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) CriticalSectionLocker __ThreadLock(Index, false);
|
||||
#define EXCLUSIVE_RELEASE() __ThreadLock.Unlock();
|
||||
|
||||
#define SHARED_ACQUIRE(Index) CriticalSectionLocker __SThreadLock(Index, true);
|
||||
#define SHARED_RELEASE() __SThreadLock.Unlock();
|
||||
|
||||
enum CriticalSectionLock
|
||||
{
|
||||
LockMemoryPages,
|
||||
|
@ -44,18 +54,18 @@ public:
|
|||
static void Initialize();
|
||||
static void Deinitialize();
|
||||
|
||||
CriticalSectionLocker(CriticalSectionLock LockIndex);
|
||||
CriticalSectionLocker(CriticalSectionLock LockIndex, bool Shared);
|
||||
~CriticalSectionLocker();
|
||||
|
||||
void Unlock();
|
||||
void Lock();
|
||||
bool TryLock();
|
||||
void Lock(bool Shared);
|
||||
|
||||
private:
|
||||
static bool m_Initialized;
|
||||
static CRITICAL_SECTION m_Locks[LockLast];
|
||||
static SRWLOCK m_Locks[LockLast];
|
||||
|
||||
CRITICAL_SECTION* m_Section;
|
||||
SRWLOCK* m_Lock;
|
||||
bool m_Shared;
|
||||
BYTE m_LockCount;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue