Skip to content

Commit

Permalink
Merge "[client] Implement thread functions for windows" into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Etienne Pierre-doray authored and Gerrit Code Review committed Oct 18, 2023
2 parents 7f27bc0 + 8f48e34 commit d20d938
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 1 deletion.
5 changes: 5 additions & 0 deletions include/perfetto/ext/base/string_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ std::string ReplaceAll(std::string str,
const std::string& to_replace,
const std::string& replacement);

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
bool WideToUTF8(const std::wstring& source, std::string& output);
bool UTF8ToWide(const std::string& source, std::wstring& output);
#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)

// A BSD-style strlcpy without the return value.
// Copies at most |dst_size|-1 characters. Unlike strncpy, it always \0
// terminates |dst|, as long as |dst_size| is not 0.
Expand Down
6 changes: 6 additions & 0 deletions include/perfetto/ext/base/thread_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/base/export.h"

#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
Expand Down Expand Up @@ -69,6 +70,11 @@ inline bool GetThreadName(std::string& out_result) {
return true;
}

#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)

PERFETTO_EXPORT_COMPONENT bool MaybeSetThreadName(const std::string& name);
PERFETTO_EXPORT_COMPONENT bool GetThreadName(std::string& out_result);

#else
inline bool MaybeSetThreadName(const std::string&) {
return false;
Expand Down
37 changes: 37 additions & 0 deletions src/base/string_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
#include <xlocale.h>
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <windows.h>
#endif

#include <cinttypes>
Expand Down Expand Up @@ -217,6 +219,41 @@ std::string ReplaceAll(std::string str,
return str;
}

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
bool WideToUTF8(const std::wstring& source, std::string& output) {
if (source.empty() ||
static_cast<int>(source.size()) > std::numeric_limits<int>::max()) {
return false;
}
int size = ::WideCharToMultiByte(CP_UTF8, 0, &source[0],
static_cast<int>(source.size()), nullptr, 0,
nullptr, nullptr);
output.assign(size, '\0');
if (::WideCharToMultiByte(CP_UTF8, 0, &source[0],
static_cast<int>(source.size()), &output[0], size,
nullptr, nullptr) != size) {
return false;
}
return true;
}

bool UTF8ToWide(const std::string& source, std::wstring& output) {
if (source.empty() ||
static_cast<int>(source.size()) > std::numeric_limits<int>::max()) {
return false;
}
int size = ::MultiByteToWideChar(CP_UTF8, 0, &source[0],
static_cast<int>(source.size()), nullptr, 0);
output.assign(size, L'\0');
if (::MultiByteToWideChar(CP_UTF8, 0, &source[0],
static_cast<int>(source.size()), &output[0],
size) != size) {
return false;
}
return true;
}
#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)

size_t SprintfTrunc(char* dst, size_t dst_size, const char* fmt, ...) {
if (PERFETTO_UNLIKELY(dst_size) == 0)
return 0;
Expand Down
51 changes: 50 additions & 1 deletion src/base/thread_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@
*/

#include "perfetto/base/thread_utils.h"
#include "perfetto/ext/base/thread_utils.h"

#include "perfetto/base/build_config.h"

#if PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>
#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <windows.h>
#endif

namespace perfetto {
namespace base {
Expand All @@ -39,6 +42,52 @@ PlatformThreadId GetThreadId() {
thread_local static PlatformThreadId thread_id = ResolveThreadId();
return thread_id;
}

#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)

// The SetThreadDescription API was brought in version 1607 of Windows 10.
typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread,
PCWSTR lpThreadDescription);

// The SetThreadDescription API was brought in version 1607 of Windows 10.
typedef HRESULT(WINAPI* GetThreadDescription)(HANDLE hThread,
PWSTR* ppszThreadDescription);

bool MaybeSetThreadName(const std::string& name) {
// The SetThreadDescription API works even if no debugger is attached.
static auto set_thread_description_func =
reinterpret_cast<SetThreadDescription>(::GetProcAddress(
::GetModuleHandle(L"Kernel32.dll"), "SetThreadDescription"));
if (!set_thread_description_func) {
return false;
}
std::wstring wide_thread_name;
if (!UTF8ToWide(name, wide_thread_name)) {
return false;
}
HRESULT result = set_thread_description_func(::GetCurrentThread(),
wide_thread_name.c_str());
return !FAILED(result);
}

bool GetThreadName(std::string& out_result) {
static auto get_thread_description_func =
reinterpret_cast<GetThreadDescription>(::GetProcAddress(
::GetModuleHandle(L"Kernel32.dll"), "GetThreadDescription"));
if (!get_thread_description_func) {
return false;
}
wchar_t* wide_thread_name;
HRESULT result =
get_thread_description_func(::GetCurrentThread(), &wide_thread_name);
if (SUCCEEDED(result)) {
bool success = WideToUTF8(std::wstring(wide_thread_name), out_result);
LocalFree(wide_thread_name);
return success;
}
return false;
}

#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)

} // namespace base
Expand Down

0 comments on commit d20d938

Please sign in to comment.