Use GetThreadDescription on Windows

Windows 10 introduced SetThreadDescription and GetThreadDescription, a
simpler way to set a thread's name.  This changes gdb and gdbserver to
use this convention when it is available.

This is part of PR win32/29050.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29050
This commit is contained in:
Tom Tromey 2022-04-13 08:45:34 -06:00
parent 1ea519ec19
commit 8bbdbd6985
4 changed files with 47 additions and 3 deletions

View file

@ -58,6 +58,10 @@ Wow64GetThreadSelectorEntry_ftype *Wow64GetThreadSelectorEntry;
#endif #endif
GenerateConsoleCtrlEvent_ftype *GenerateConsoleCtrlEvent; GenerateConsoleCtrlEvent_ftype *GenerateConsoleCtrlEvent;
#define GetThreadDescription dyn_GetThreadDescription
typedef HRESULT WINAPI (GetThreadDescription_ftype) (HANDLE, PWSTR *);
static GetThreadDescription_ftype *GetThreadDescription;
/* Note that 'debug_events' must be locally defined in the relevant /* Note that 'debug_events' must be locally defined in the relevant
functions. */ functions. */
#define DEBUG_EVENTS(fmt, ...) \ #define DEBUG_EVENTS(fmt, ...) \
@ -106,6 +110,29 @@ windows_thread_info::resume ()
suspended = 0; suspended = 0;
} }
const char *
windows_thread_info::thread_name ()
{
if (GetThreadDescription != nullptr)
{
PWSTR value;
HRESULT result = GetThreadDescription (h, &value);
if (SUCCEEDED (result))
{
size_t needed = wcstombs (nullptr, value, 0);
if (needed != (size_t) -1)
{
name.reset ((char *) xmalloc (needed));
if (wcstombs (name.get (), value, needed) == (size_t) -1)
name.reset ();
}
LocalFree (value);
}
}
return name.get ();
}
/* Return the name of the DLL referenced by H at ADDRESS. UNICODE /* Return the name of the DLL referenced by H at ADDRESS. UNICODE
determines what sort of string is read from the inferior. Returns determines what sort of string is read from the inferior. Returns
the name of the DLL, or NULL on error. If a name is returned, it the name of the DLL, or NULL on error. If a name is returned, it
@ -662,6 +689,7 @@ initialize_loadable ()
GPA (hm, Wow64GetThreadSelectorEntry); GPA (hm, Wow64GetThreadSelectorEntry);
#endif #endif
GPA (hm, GenerateConsoleCtrlEvent); GPA (hm, GenerateConsoleCtrlEvent);
GPA (hm, GetThreadDescription);
} }
/* Set variables to dummy versions of these processes if the function /* Set variables to dummy versions of these processes if the function
@ -718,6 +746,15 @@ initialize_loadable ()
OpenProcessToken = bad; OpenProcessToken = bad;
} }
/* On some versions of Windows, this function is only available in
KernelBase.dll, not kernel32.dll. */
if (GetThreadDescription == nullptr)
{
hm = LoadLibrary (TEXT ("KernelBase.dll"));
if (hm)
GPA (hm, GetThreadDescription);
}
#undef GPA #undef GPA
return result; return result;

View file

@ -51,6 +51,11 @@ struct windows_thread_info
/* Resume the thread if it has been suspended. */ /* Resume the thread if it has been suspended. */
void resume (); void resume ();
/* Return the thread's name, or nullptr if not known. The name is
stored in this thread and is guaranteed to live until at least
the next call. */
const char *thread_name ();
/* The Win32 thread identifier. */ /* The Win32 thread identifier. */
DWORD tid; DWORD tid;

View file

@ -2997,8 +2997,10 @@ windows_nat_target::get_ada_task_ptid (long lwp, ULONGEST thread)
const char * const char *
windows_nat_target::thread_name (struct thread_info *thr) windows_nat_target::thread_name (struct thread_info *thr)
{ {
return windows_process.thread_rec (thr->ptid, windows_thread_info *th
DONT_INVALIDATE_CONTEXT)->name.get (); = windows_process.thread_rec (thr->ptid,
DONT_INVALIDATE_CONTEXT);
return th->thread_name ();
} }

View file

@ -1508,7 +1508,7 @@ win32_process_target::thread_name (ptid_t thread)
windows_thread_info *th windows_thread_info *th
= windows_process.thread_rec (current_thread_ptid (), = windows_process.thread_rec (current_thread_ptid (),
DONT_INVALIDATE_CONTEXT); DONT_INVALIDATE_CONTEXT);
return th->name.get (); return th->thread_name ();
} }
/* The win32 target ops object. */ /* The win32 target ops object. */