-
Notifications
You must be signed in to change notification settings - Fork 226
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(threading): Name all game threads & own threads.
- Loading branch information
Showing
14 changed files
with
230 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
|
||
#include "ThreadUtils.h" | ||
|
||
namespace | ||
{ | ||
// as defined in sentry-native/src/sentry_sync.h | ||
#ifdef _WIN32 | ||
#include <Windows.h> | ||
using sentry_threadid_t = HANDLE; | ||
|
||
sentry_threadid_t GetCurrentThreadHandle() | ||
{ | ||
return ::GetCurrentThread(); | ||
} | ||
#else | ||
#include <pthread.h> | ||
using sentry_threadid_t = pthread_t; | ||
|
||
sentry_threadid_t GetCurrentThreadHandle() | ||
{ | ||
return ::pthread_self(); | ||
} | ||
#endif | ||
|
||
} // namespace | ||
|
||
// we use the sentry impl here, as it covers all bases, e.g linux & windows support, plus additional windows 10+ | ||
// features | ||
extern "C" | ||
{ | ||
int sentry__thread_setname(sentry_threadid_t aThreadHandle, const char* apThreadName); | ||
} | ||
|
||
namespace base | ||
{ | ||
bool SetThreadName(void* apThreadHandle, const char* apThreadName) | ||
{ | ||
return sentry__thread_setname(reinterpret_cast<sentry_threadid_t>(apThreadHandle), apThreadName) == 0; | ||
} | ||
|
||
bool SetCurrentThreadName(const char* apThreadName) | ||
{ | ||
return sentry__thread_setname(GetCurrentThreadHandle(), apThreadName) == 0; | ||
} | ||
|
||
} // namespace base |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#pragma once | ||
|
||
namespace base | ||
{ | ||
// set to thread handle | ||
bool SetThreadName(void* apThreadHandle, const char* apThreadName); | ||
|
||
// call this on current thread | ||
bool SetCurrentThreadName(const char* apThreadName); | ||
} // namespace base |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
|
||
#include <base/threading/ThreadUtils.h> | ||
|
||
namespace | ||
{ | ||
struct BSTaskletManager | ||
{ | ||
char pad0[0x30]; | ||
void* threadHandles[6]; | ||
}; | ||
|
||
static void (*Construct_TaskletManager)(BSTaskletManager*); | ||
|
||
static void Hook_Construct_TaskletManager(BSTaskletManager* apSelf) | ||
{ | ||
Construct_TaskletManager(apSelf); | ||
|
||
for (int i = 0; i < 6; i++) | ||
{ | ||
if (!apSelf->threadHandles[i]) | ||
continue; | ||
|
||
auto name = fmt::format("TaskletThread{}", i); | ||
base::SetThreadName(apSelf->threadHandles[i], name.c_str()); | ||
} | ||
} | ||
} // namespace | ||
|
||
static TiltedPhoques::Initializer s_BSThreadInit([]() { | ||
const VersionDbPtr<uint8_t> getTaskletManagerInstance(69554); | ||
|
||
// tasklet naming | ||
TiltedPhoques::SwapCall(getTaskletManagerInstance.Get() + 0x63, Construct_TaskletManager, | ||
&Hook_Construct_TaskletManager); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
|
||
#include <Games/Skyrim/BSSystem/BSThread.h> | ||
#include <base/threading/ThreadUtils.h> | ||
|
||
namespace | ||
{ | ||
void (*BSThread_Initialize)(BSThread*, int, const char*){nullptr}; | ||
|
||
void Hook_BSThread_Initialize(BSThread* apThis, int aStackSize, const char* apName) | ||
{ | ||
BSThread_Initialize(apThis, aStackSize, apName); | ||
|
||
if (!apName && apThis->m_ThreadHandle) | ||
spdlog::warn("Unnamed thread started: {}", apThis->m_ThreadID); | ||
|
||
// this means the thread was successfully created | ||
if (apThis->m_ThreadHandle) | ||
{ | ||
bool result = base::SetThreadName(apThis->m_ThreadHandle, apName); | ||
if (!result) | ||
{ | ||
spdlog::warn("Failed to set thread name for tid {} to {}", apThis->m_ThreadID, apName); | ||
} | ||
} | ||
} | ||
|
||
// bsthreadutils | ||
// hook this in order to redirect the game to use the new naming apis (windows 10+) | ||
void Hook_SetThreadName(uint32_t aThreadId, const char* apThreadName) | ||
{ | ||
// query thread handle | ||
if (auto hThread = ::OpenThread(THREAD_QUERY_INFORMATION, FALSE, aThreadId)) | ||
{ | ||
base::SetThreadName(hThread, apThreadName); | ||
|
||
::CloseHandle(hThread); | ||
} | ||
else | ||
spdlog::warn("Hook_SetThreadName(): Unable to query thread handle :("); | ||
} | ||
|
||
// experimental stuff.. | ||
#if 0 | ||
typedef struct | ||
{ | ||
DWORD dwType; // Must be 0x1000. | ||
LPCSTR szName; // Pointer to name (in user addr space). | ||
DWORD dwThreadID; // Thread ID (-1=caller thread). | ||
DWORD dwFlags; // Reserved for future use, must be zero. | ||
} THREADNAME_INFO; | ||
|
||
void Hook_RaiseException(DWORD, DWORD, DWORD, const THREADNAME_INFO* lpArguments) | ||
{ | ||
base::SetCurrentThreadName(lpArguments->szName); | ||
} | ||
|
||
HANDLE WINAPI Hook_CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, | ||
LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, | ||
LPDWORD lpThreadId) | ||
{ | ||
auto hThread = | ||
CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId); | ||
|
||
if (hThread && lpThreadId) | ||
{ | ||
auto name = fmt::format("BNetThread{}", *lpThreadId); | ||
base::SetThreadName(hThread, name.c_str()); | ||
} | ||
|
||
return hThread; | ||
} | ||
#endif | ||
} // namespace | ||
|
||
static TiltedPhoques::Initializer s_BSThreadInit([]() { | ||
const VersionDbPtr<uint8_t> threadInit(68261); | ||
BSThread_Initialize = static_cast<decltype(BSThread_Initialize)>(threadInit.GetPtr()); | ||
// need to detour this for now :/ | ||
TP_HOOK_IMMEDIATE(&BSThread_Initialize, &Hook_BSThread_Initialize); | ||
|
||
const VersionDbPtr<uint8_t> setThreadName(69066); | ||
TiltedPhoques::Jump(setThreadName.Get(), &Hook_SetThreadName); | ||
|
||
#if 0 | ||
const VersionDbPtr<uint8_t> createHavokThread(57704); | ||
// relatively safe to do, since this is unlikely to ever change, as beth wont update havok | ||
TiltedPhoques::Nop(createHavokThread.Get() + 0x81, 6); | ||
|
||
TiltedPhoques::PutCall(createHavokThread.Get() + 0x81, &Hook_RaiseException); | ||
|
||
|
||
TiltedPhoques::Nop(0x1411F0FD4, 6); | ||
TiltedPhoques::PutCall(0x1411F0FD4, &Hook_CreateThread); | ||
#endif | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#pragma once | ||
|
||
class BSThread | ||
{ | ||
public: | ||
virtual ~BSThread() = 0; | ||
// runner | ||
virtual uint32_t ThreadProc() = 0; | ||
// probably release | ||
virtual bool Release() = 0; | ||
|
||
//private: | ||
CRITICAL_SECTION lock; // in reality a BSCriticalSection | ||
void* m_ThreadHandle; | ||
void* m_ParentHandle; | ||
uint32_t m_ThreadID; | ||
uint32_t m_ParentID; | ||
bool bThreadIsActive; | ||
}; | ||
static_assert(sizeof(BSThread) == 0x50, "BSThread size mismatch"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters