1
0
Fork 0

Begin using shared locks

This commit is contained in:
Nukem 2015-03-11 18:14:25 -04:00
parent ff52bc2321
commit 0a69aa95e9
6 changed files with 155 additions and 82 deletions

View File

@ -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

View File

@ -2197,6 +2197,7 @@ void errorinit()
const char* errornamefromcode(unsigned int ErrorCode)
{
if(!errorNames.count(ErrorCode))
return 0;
return nullptr;
return errorNames[ErrorCode];
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
};