Skip to content

Commit 7aaad16

Browse files
committed
8238649: Call new Win32 API SetThreadDescription in os::set_native_thread_name
Backport-of: 9f3c7e74ff00a7550742ed8b9d6671c2d4bb6041
1 parent 16a191c commit 7aaad16

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

src/hotspot/os/windows/os_windows.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,8 +885,62 @@ uint os::processor_id() {
885885
return (uint)GetCurrentProcessorNumber();
886886
}
887887

888+
// For dynamic lookup of SetThreadDescription API
889+
typedef HRESULT (WINAPI *SetThreadDescriptionFnPtr)(HANDLE, PCWSTR);
890+
typedef HRESULT (WINAPI *GetThreadDescriptionFnPtr)(HANDLE, PWSTR*);
891+
static SetThreadDescriptionFnPtr _SetThreadDescription = NULL;
892+
DEBUG_ONLY(static GetThreadDescriptionFnPtr _GetThreadDescription = NULL;)
893+
894+
// forward decl.
895+
errno_t convert_to_unicode(char const* char_path, LPWSTR* unicode_path);
896+
888897
void os::set_native_thread_name(const char *name) {
889898

899+
// From Windows 10 and Windows 2016 server, we have a direct API
900+
// for setting the thread name/description:
901+
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription
902+
903+
if (_SetThreadDescription != NULL) {
904+
// SetThreadDescription takes a PCWSTR but we have conversion routines that produce
905+
// LPWSTR. The only difference is that PCWSTR is a pointer to const WCHAR.
906+
LPWSTR unicode_name;
907+
errno_t err = convert_to_unicode(name, &unicode_name);
908+
if (err == ERROR_SUCCESS) {
909+
HANDLE current = GetCurrentThread();
910+
HRESULT hr = _SetThreadDescription(current, unicode_name);
911+
if (FAILED(hr)) {
912+
log_debug(os, thread)("set_native_thread_name: SetThreadDescription failed - falling back to debugger method");
913+
FREE_C_HEAP_ARRAY(WCHAR, unicode_name);
914+
} else {
915+
log_trace(os, thread)("set_native_thread_name: SetThreadDescription succeeded - new name: %s", name);
916+
917+
#ifdef ASSERT
918+
// For verification purposes in a debug build we read the thread name back and check it.
919+
PWSTR thread_name;
920+
HRESULT hr2 = _GetThreadDescription(current, &thread_name);
921+
if (FAILED(hr2)) {
922+
log_debug(os, thread)("set_native_thread_name: GetThreadDescription failed!");
923+
} else {
924+
int res = CompareStringW(LOCALE_USER_DEFAULT,
925+
0, // no special comparison rules
926+
unicode_name,
927+
-1, // null-terminated
928+
thread_name,
929+
-1 // null-terminated
930+
);
931+
assert(res == CSTR_EQUAL,
932+
"Name strings were not the same - set: %ls, but read: %ls", unicode_name, thread_name);
933+
LocalFree(thread_name);
934+
}
935+
#endif
936+
FREE_C_HEAP_ARRAY(WCHAR, unicode_name);
937+
return;
938+
}
939+
} else {
940+
log_debug(os, thread)("set_native_thread_name: convert_to_unicode failed - falling back to debugger method");
941+
}
942+
}
943+
890944
// See: http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
891945
//
892946
// Note that unfortunately this only works if the process
@@ -895,6 +949,7 @@ void os::set_native_thread_name(const char *name) {
895949

896950
// If there is no debugger attached skip raising the exception
897951
if (!IsDebuggerPresent()) {
952+
log_debug(os, thread)("set_native_thread_name: no debugger present so unable to set thread name");
898953
return;
899954
}
900955

@@ -4201,6 +4256,7 @@ extern "C" {
42014256

42024257
static jint initSock();
42034258

4259+
42044260
// this is called _after_ the global arguments have been parsed
42054261
jint os::init_2(void) {
42064262

@@ -4319,6 +4375,24 @@ jint os::init_2(void) {
43194375
jdk_misc_signal_init();
43204376
}
43214377

4378+
// Lookup SetThreadDescription - the docs state we must use runtime-linking of
4379+
// kernelbase.dll, so that is what we do.
4380+
HINSTANCE _kernelbase = LoadLibrary(TEXT("kernelbase.dll"));
4381+
if (_kernelbase != NULL) {
4382+
_SetThreadDescription =
4383+
reinterpret_cast<SetThreadDescriptionFnPtr>(
4384+
GetProcAddress(_kernelbase,
4385+
"SetThreadDescription"));
4386+
#ifdef ASSERT
4387+
_GetThreadDescription =
4388+
reinterpret_cast<GetThreadDescriptionFnPtr>(
4389+
GetProcAddress(_kernelbase,
4390+
"GetThreadDescription"));
4391+
#endif
4392+
}
4393+
log_info(os, thread)("The SetThreadDescription API is%s available.", _SetThreadDescription == NULL ? " not" : "");
4394+
4395+
43224396
return JNI_OK;
43234397
}
43244398

test/hotspot/jtreg/runtime/logging/ThreadLoggingTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public static void main(String[] args) throws Exception {
6262
pb = ProcessTools.createJavaProcessBuilder("-Xlog:os+thread=debug", "-version");
6363
output = new OutputAnalyzer(pb.start());
6464
analyzeOutputForDebugLevel(output);
65-
65+
output.reportDiagnosticSummary();
6666
}
6767

6868
}

0 commit comments

Comments
 (0)