mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-14 19:15:05 -05:00
add api for getting/setting thread names
This commit is contained in:
parent
5498ecb015
commit
ce53fb3135
8 changed files with 120 additions and 2 deletions
|
@ -141,3 +141,9 @@ namespace geode::utils::game {
|
|||
GEODE_DLL void restart();
|
||||
GEODE_DLL void launchLoaderUninstaller(bool deleteSaveData);
|
||||
}
|
||||
|
||||
namespace geode::utils::thread {
|
||||
GEODE_DLL std::string getName();
|
||||
GEODE_DLL void setName(std::string const& name);
|
||||
GEODE_DLL void setName(std::wstring const& wName);
|
||||
}
|
||||
|
|
|
@ -94,6 +94,7 @@ void tryShowForwardCompat() {
|
|||
}
|
||||
|
||||
int geodeEntry(void* platformData) {
|
||||
thread::setName("Main Thread");
|
||||
log::Logger::get()->setup();
|
||||
|
||||
std::string forwardCompatSuffix;
|
||||
|
|
|
@ -363,3 +363,7 @@ void geode::utils::permission::requestPermission(Permission permission, utils::M
|
|||
clearJNIException();
|
||||
}
|
||||
}
|
||||
|
||||
#include "../../utils/thread.hpp"
|
||||
void geode::utils::thread::platformSetNameOrdinary(std::string const& name) { }
|
||||
void geode::utils::thread::platformSetNameWide(std::wstring const& wName) { }
|
||||
|
|
|
@ -309,3 +309,7 @@ bool geode::utils::permission::getPermissionStatus(Permission permission) {
|
|||
void geode::utils::permission::requestPermission(Permission permission, utils::MiniFunction<void(bool)> callback) {
|
||||
callback(true); // unimplemented
|
||||
}
|
||||
|
||||
#include "../../utils/thread.hpp"
|
||||
void geode::utils::thread::platformSetNameOrdinary(std::string const& name) { }
|
||||
void geode::utils::thread::platformSetNameWide(std::wstring const& wName) { }
|
||||
|
|
|
@ -10,6 +10,8 @@ using namespace geode::prelude;
|
|||
static constexpr auto IPC_BUFFER_SIZE = 512;
|
||||
|
||||
void ipcPipeThread(HANDLE pipe) {
|
||||
thread::setName("Geode IPC Pipe");
|
||||
|
||||
char buffer[IPC_BUFFER_SIZE * sizeof(TCHAR)];
|
||||
DWORD read;
|
||||
|
||||
|
@ -35,6 +37,7 @@ void ipcPipeThread(HANDLE pipe) {
|
|||
|
||||
void ipc::setup() {
|
||||
std::thread ipcThread([]() {
|
||||
thread::setName("Geode Main IPC");
|
||||
while (true) {
|
||||
auto pipe = CreateNamedPipeA(
|
||||
ipc::IPC_PIPE_NAME,
|
||||
|
@ -59,7 +62,6 @@ void ipc::setup() {
|
|||
if (ConnectNamedPipe(pipe, nullptr)) {
|
||||
// log::debug("Got connection, creating thread");
|
||||
std::thread pipeThread(&ipcPipeThread, pipe);
|
||||
// SetThreadDescription(pipeThread.native_handle(), L"Geode IPC Pipe");
|
||||
pipeThread.detach();
|
||||
}
|
||||
else {
|
||||
|
@ -68,7 +70,6 @@ void ipc::setup() {
|
|||
}
|
||||
}
|
||||
});
|
||||
// SetThreadDescription(ipcThread.native_handle(), L"Geode Main IPC");
|
||||
ipcThread.detach();
|
||||
|
||||
log::debug("IPC set up");
|
||||
|
|
|
@ -6,6 +6,7 @@ using namespace geode::prelude;
|
|||
#include "nfdwin.hpp"
|
||||
#include <ghc/fs_fwd.hpp>
|
||||
#include <Windows.h>
|
||||
#include <processthreadsapi.h>
|
||||
#include <iostream>
|
||||
#include <ShlObj.h>
|
||||
#include <shlwapi.h>
|
||||
|
@ -277,3 +278,42 @@ bool geode::utils::permission::getPermissionStatus(Permission permission) {
|
|||
void geode::utils::permission::requestPermission(Permission permission, utils::MiniFunction<void(bool)> callback) {
|
||||
callback(true); // unimplemented
|
||||
}
|
||||
|
||||
#include "../../utils/thread.hpp"
|
||||
|
||||
// https://learn.microsoft.com/en-us/visualstudio/debugger/how-to-set-a-thread-name-in-native-code?view=vs-2022
|
||||
#pragma pack(push,8)
|
||||
typedef struct tagTHREADNAME_INFO {
|
||||
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;
|
||||
#pragma pack(pop)
|
||||
|
||||
// the SetThreadDescription and exception methods are needed for the thread names to show up
|
||||
// in places like task managers and debuggers
|
||||
auto setThreadDesc = reinterpret_cast<decltype(&SetThreadDescription)>(GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetThreadDescription"));
|
||||
void geode::utils::thread::platformSetNameWide(std::wstring const& wName) {
|
||||
// SetThreadDescription
|
||||
if (!setThreadDesc)
|
||||
return;
|
||||
auto res = setThreadDesc(GetCurrentThread(), wName.c_str());
|
||||
if (FAILED(res))
|
||||
log::warn("Native method to set thread name failed ({}), using only fallback methods.", res);
|
||||
}
|
||||
void geode::utils::thread::platformSetNameOrdinary(std::string const& name) {
|
||||
// exception
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = name.c_str();
|
||||
info.dwThreadID = GetCurrentThreadId();
|
||||
info.dwFlags = 0;
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 6320 6322)
|
||||
__try {
|
||||
RaiseException(0x406d1388, 0, sizeof(info) / sizeof(ULONG_PTR), reinterpret_cast<ULONG_PTR*>(&info));
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) { }
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
|
54
loader/src/utils/thread.cpp
Normal file
54
loader/src/utils/thread.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include <Geode/DefaultInclude.hpp>
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
||||
#include <Geode/Utils.hpp>
|
||||
#include "thread.hpp"
|
||||
|
||||
static thread_local std::string s_threadName;
|
||||
|
||||
std::string geode::utils::thread::getName() {
|
||||
// only use the thread-local variable here, no need for platform get methods
|
||||
if (s_threadName.empty())
|
||||
return fmt::format("Thread #{}", GetThreadId(GetCurrentThread()));
|
||||
return s_threadName;
|
||||
}
|
||||
|
||||
void geode::utils::thread::setName(std::string const& name) {
|
||||
std::wstring wName(name.size(), L' ');
|
||||
size_t numConv;
|
||||
auto res = mbstowcs_s(&numConv, wName.data(), sizeof(wchar_t) * wName.size(), name.data(), wName.size());
|
||||
if (res == EINVAL) {
|
||||
log::warn(
|
||||
"Native method to set thread name failed (EINVAL), using only fallback methods.");
|
||||
}
|
||||
else if (res == ERANGE) {
|
||||
log::warn(
|
||||
"Native method to set thread name failed (ERANGE), using only fallback methods.");
|
||||
}
|
||||
else {
|
||||
platformSetNameWide(wName);
|
||||
}
|
||||
|
||||
platformSetNameOrdinary(name);
|
||||
s_threadName = name;
|
||||
}
|
||||
|
||||
void geode::utils::thread::setName(std::wstring const& wName) {
|
||||
platformSetNameWide(wName);
|
||||
|
||||
std::string name(wName.size(), ' ');
|
||||
size_t numConv;
|
||||
auto res = wcstombs_s(&numConv, name.data(), name.size(), wName.data(), name.size());
|
||||
if (res == EINVAL) {
|
||||
log::warn("Fallback method to set thread name failed (EINVAL).");
|
||||
return;
|
||||
}
|
||||
if (res == ERANGE) {
|
||||
log::warn("Fallback method to set thread name failed (ERANGE).");
|
||||
return;
|
||||
}
|
||||
|
||||
platformSetNameOrdinary(name);
|
||||
s_threadName = name;
|
||||
}
|
8
loader/src/utils/thread.hpp
Normal file
8
loader/src/utils/thread.hpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace geode::utils::thread {
|
||||
void platformSetNameOrdinary(std::string const& name);
|
||||
void platformSetNameWide(std::wstring const& wName);
|
||||
}
|
Loading…
Reference in a new issue