mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-17 05:45:05 +00:00
8238649: Call new Win32 API SetThreadDescription in os::set_native_thread_name
Co-authored-by: Markus GaisBauer <markus.gaisbauer@dynatrace.com> Reviewed-by: stuefe, luhenry
This commit is contained in:
parent
2e70bc35df
commit
9f3c7e74ff
@ -885,8 +885,62 @@ uint os::processor_id() {
|
||||
return (uint)GetCurrentProcessorNumber();
|
||||
}
|
||||
|
||||
// For dynamic lookup of SetThreadDescription API
|
||||
typedef HRESULT (WINAPI *SetThreadDescriptionFnPtr)(HANDLE, PCWSTR);
|
||||
typedef HRESULT (WINAPI *GetThreadDescriptionFnPtr)(HANDLE, PWSTR*);
|
||||
static SetThreadDescriptionFnPtr _SetThreadDescription = NULL;
|
||||
DEBUG_ONLY(static GetThreadDescriptionFnPtr _GetThreadDescription = NULL;)
|
||||
|
||||
// forward decl.
|
||||
errno_t convert_to_unicode(char const* char_path, LPWSTR* unicode_path);
|
||||
|
||||
void os::set_native_thread_name(const char *name) {
|
||||
|
||||
// From Windows 10 and Windows 2016 server, we have a direct API
|
||||
// for setting the thread name/description:
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription
|
||||
|
||||
if (_SetThreadDescription != NULL) {
|
||||
// SetThreadDescription takes a PCWSTR but we have conversion routines that produce
|
||||
// LPWSTR. The only difference is that PCWSTR is a pointer to const WCHAR.
|
||||
LPWSTR unicode_name;
|
||||
errno_t err = convert_to_unicode(name, &unicode_name);
|
||||
if (err == ERROR_SUCCESS) {
|
||||
HANDLE current = GetCurrentThread();
|
||||
HRESULT hr = _SetThreadDescription(current, unicode_name);
|
||||
if (FAILED(hr)) {
|
||||
log_debug(os, thread)("set_native_thread_name: SetThreadDescription failed - falling back to debugger method");
|
||||
FREE_C_HEAP_ARRAY(WCHAR, unicode_name);
|
||||
} else {
|
||||
log_trace(os, thread)("set_native_thread_name: SetThreadDescription succeeded - new name: %s", name);
|
||||
|
||||
#ifdef ASSERT
|
||||
// For verification purposes in a debug build we read the thread name back and check it.
|
||||
PWSTR thread_name;
|
||||
HRESULT hr2 = _GetThreadDescription(current, &thread_name);
|
||||
if (FAILED(hr2)) {
|
||||
log_debug(os, thread)("set_native_thread_name: GetThreadDescription failed!");
|
||||
} else {
|
||||
int res = CompareStringW(LOCALE_USER_DEFAULT,
|
||||
0, // no special comparison rules
|
||||
unicode_name,
|
||||
-1, // null-terminated
|
||||
thread_name,
|
||||
-1 // null-terminated
|
||||
);
|
||||
assert(res == CSTR_EQUAL,
|
||||
"Name strings were not the same - set: %ls, but read: %ls", unicode_name, thread_name);
|
||||
LocalFree(thread_name);
|
||||
}
|
||||
#endif
|
||||
FREE_C_HEAP_ARRAY(WCHAR, unicode_name);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
log_debug(os, thread)("set_native_thread_name: convert_to_unicode failed - falling back to debugger method");
|
||||
}
|
||||
}
|
||||
|
||||
// See: http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
|
||||
//
|
||||
// Note that unfortunately this only works if the process
|
||||
@ -895,6 +949,7 @@ void os::set_native_thread_name(const char *name) {
|
||||
|
||||
// If there is no debugger attached skip raising the exception
|
||||
if (!IsDebuggerPresent()) {
|
||||
log_debug(os, thread)("set_native_thread_name: no debugger present so unable to set thread name");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4193,6 +4248,7 @@ extern "C" {
|
||||
|
||||
static jint initSock();
|
||||
|
||||
|
||||
// this is called _after_ the global arguments have been parsed
|
||||
jint os::init_2(void) {
|
||||
|
||||
@ -4311,6 +4367,24 @@ jint os::init_2(void) {
|
||||
jdk_misc_signal_init();
|
||||
}
|
||||
|
||||
// Lookup SetThreadDescription - the docs state we must use runtime-linking of
|
||||
// kernelbase.dll, so that is what we do.
|
||||
HINSTANCE _kernelbase = LoadLibrary(TEXT("kernelbase.dll"));
|
||||
if (_kernelbase != NULL) {
|
||||
_SetThreadDescription =
|
||||
reinterpret_cast<SetThreadDescriptionFnPtr>(
|
||||
GetProcAddress(_kernelbase,
|
||||
"SetThreadDescription"));
|
||||
#ifdef ASSERT
|
||||
_GetThreadDescription =
|
||||
reinterpret_cast<GetThreadDescriptionFnPtr>(
|
||||
GetProcAddress(_kernelbase,
|
||||
"GetThreadDescription"));
|
||||
#endif
|
||||
}
|
||||
log_info(os, thread)("The SetThreadDescription API is%s available.", _SetThreadDescription == NULL ? " not" : "");
|
||||
|
||||
|
||||
return JNI_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -62,7 +62,7 @@ public class ThreadLoggingTest {
|
||||
pb = ProcessTools.createJavaProcessBuilder("-Xlog:os+thread=debug", "-version");
|
||||
output = new OutputAnalyzer(pb.start());
|
||||
analyzeOutputForDebugLevel(output);
|
||||
|
||||
output.reportDiagnosticSummary();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user