@@ -885,8 +885,62 @@ uint os::processor_id() {
885
885
return (uint)GetCurrentProcessorNumber ();
886
886
}
887
887
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
+
888
897
void os::set_native_thread_name (const char *name) {
889
898
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
+
890
944
// See: http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
891
945
//
892
946
// Note that unfortunately this only works if the process
@@ -895,6 +949,7 @@ void os::set_native_thread_name(const char *name) {
895
949
896
950
// If there is no debugger attached skip raising the exception
897
951
if (!IsDebuggerPresent ()) {
952
+ log_debug (os, thread)(" set_native_thread_name: no debugger present so unable to set thread name" );
898
953
return ;
899
954
}
900
955
@@ -4201,6 +4256,7 @@ extern "C" {
4201
4256
4202
4257
static jint initSock ();
4203
4258
4259
+
4204
4260
// this is called _after_ the global arguments have been parsed
4205
4261
jint os::init_2 (void ) {
4206
4262
@@ -4319,6 +4375,24 @@ jint os::init_2(void) {
4319
4375
jdk_misc_signal_init ();
4320
4376
}
4321
4377
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
+
4322
4396
return JNI_OK;
4323
4397
}
4324
4398
0 commit comments