[PATCH v5 08/24] util: add API to fetch the current thread name

Daniel P. Berrangé posted 24 patches 3 weeks, 3 days ago
There is a newer version of this series
[PATCH v5 08/24] util: add API to fetch the current thread name
Posted by Daniel P. Berrangé 3 weeks, 3 days ago
This will be used to include the thread name in error reports
in a later patch. It returns a const string stored in a thread
local to avoid memory allocation when it is called repeatedly
in a single thread. The thread name should be set at the very
start of the thread execution, which is the case when using
qemu_thread_create.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 include/qemu/thread.h    |  1 +
 meson.build              | 21 +++++++++++++++++
 util/qemu-thread-posix.c | 33 ++++++++++++++++++++++++++-
 util/qemu-thread-win32.c | 49 ++++++++++++++++++++++++++++++++++++----
 4 files changed, 99 insertions(+), 5 deletions(-)

diff --git a/include/qemu/thread.h b/include/qemu/thread.h
index 27b888ab0a..98cc5c41ac 100644
--- a/include/qemu/thread.h
+++ b/include/qemu/thread.h
@@ -216,6 +216,7 @@ void qemu_thread_get_self(QemuThread *thread);
 bool qemu_thread_is_self(QemuThread *thread);
 G_NORETURN void qemu_thread_exit(void *retval);
 void qemu_thread_set_name(const char *name);
+const char *qemu_thread_get_name(void);
 
 struct Notifier;
 /**
diff --git a/meson.build b/meson.build
index db87358d62..eb27aca329 100644
--- a/meson.build
+++ b/meson.build
@@ -2874,6 +2874,27 @@ config_host_data.set('CONFIG_PTHREAD_SET_NAME_NP', cc.links(osdep_prefix + '''
     pthread_set_name_np(thread, "QEMU");
     return 0;
   }''', dependencies: threads))
+
+config_host_data.set('CONFIG_PTHREAD_GETNAME_NP', cc.links(osdep_prefix + '''
+  #include <pthread.h>
+
+  int main(void)
+  {
+    char buf[16];
+    pthread_getname_np(pthread_self(), buf, sizeof(buf));
+    return 0;
+  }''', dependencies: threads))
+config_host_data.set('CONFIG_PTHREAD_GET_NAME_NP', cc.links(osdep_prefix + '''
+  #include <pthread.h>
+  #include <pthread_np.h>
+
+  int main(void)
+  {
+    char buf[16];
+    pthread_get_name_np(pthread_self(), buf, sizeof(buf));
+    return 0;
+  }''', dependencies: threads))
+
 config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(osdep_prefix + '''
   #include <pthread.h>
 
diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
index afeac9ecad..47156b60ce 100644
--- a/util/qemu-thread-posix.c
+++ b/util/qemu-thread-posix.c
@@ -18,7 +18,7 @@
 #include "qemu/tsan.h"
 #include "qemu/bitmap.h"
 
-#ifdef CONFIG_PTHREAD_SET_NAME_NP
+#if defined(CONFIG_PTHREAD_SET_NAME_NP) || defined(CONFIG_PTHREAD_GET_NAME_NP)
 #include <pthread_np.h>
 #endif
 
@@ -532,3 +532,34 @@ void *qemu_thread_join(QemuThread *thread)
     }
     return ret;
 }
+
+/*
+ * This is not defined on Linux, but the man page indicates
+ * the buffer must be at least 16 bytes, including the NUL
+ * terminator
+ */
+#ifndef PTHREAD_MAX_NAMELEN_NP
+#define PTHREAD_MAX_NAMELEN_NP 16
+#endif
+
+static __thread char namebuf[PTHREAD_MAX_NAMELEN_NP];
+
+const char *qemu_thread_get_name(void)
+{
+    int rv;
+    if (namebuf[0] != '\0') {
+        return namebuf;
+    }
+
+# if defined(CONFIG_PTHREAD_GETNAME_NP)
+    rv = pthread_getname_np(pthread_self(), namebuf, sizeof(namebuf));
+# elif defined(CONFIG_PTHREAD_GET_NAME_NP)
+    rv = pthread_get_name_np(pthread_self(), namebuf, sizeof(namebuf));
+# else
+    rv = -1;
+# endif
+    if (rv != 0) {
+        g_strlcpy(namebuf, "unnamed", G_N_ELEMENTS(namebuf));
+    }
+    return namebuf;
+}
diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
index 8ca6429ad3..082a38c7d5 100644
--- a/util/qemu-thread-win32.c
+++ b/util/qemu-thread-win32.c
@@ -19,7 +19,10 @@
 
 typedef HRESULT (WINAPI *pSetThreadDescription) (HANDLE hThread,
                                                  PCWSTR lpThreadDescription);
+typedef HRESULT (WINAPI *pGetThreadDescription) (HANDLE hThread,
+                                                 PWSTR *lpThreadDescription);
 static pSetThreadDescription SetThreadDescriptionFunc;
+static pGetThreadDescription GetThreadDescriptionFunc;
 static HMODULE kernel32_module;
 
 static void __attribute__((__constructor__(QEMU_CONSTRUCTOR_EARLY)))
@@ -28,7 +31,7 @@ qemu_thread_init(void)
     qemu_thread_set_name("main");
 }
 
-static bool load_set_thread_description(void)
+static bool load_thread_description(void)
 {
     static gsize _init_once = 0;
 
@@ -38,14 +41,17 @@ static bool load_set_thread_description(void)
             SetThreadDescriptionFunc =
                 (pSetThreadDescription)GetProcAddress(kernel32_module,
                                                       "SetThreadDescription");
-            if (!SetThreadDescriptionFunc) {
+            GetThreadDescriptionFunc =
+                (pGetThreadDescription)GetProcAddress(kernel32_module,
+                                                      "GetThreadDescription");
+            if (!SetThreadDescriptionFunc || !GetThreadDescriptionFunc) {
                 FreeLibrary(kernel32_module);
             }
         }
         g_once_init_leave(&_init_once, 1);
     }
 
-    return !!SetThreadDescriptionFunc;
+    return (SetThreadDescriptionFunc && GetThreadDescriptionFunc);
 }
 
 static void error_exit(int err, const char *msg)
@@ -331,7 +337,7 @@ void qemu_thread_set_name(const char *name)
 {
     g_autofree wchar_t *namew = NULL;
 
-    if (!load_set_thread_description()) {
+    if (!load_thread_description()) {
         return;
     }
 
@@ -415,3 +421,38 @@ bool qemu_thread_is_self(QemuThread *thread)
 {
     return GetCurrentThreadId() == thread->tid;
 }
+
+static __thread char namebuf[64];
+
+const char *qemu_thread_get_name(void)
+{
+    HRESULT hr;
+    wchar_t *namew = NULL;
+    g_autofree char *name = NULL;
+
+    if (namebuf[0] != '\0') {
+        return namebuf;
+    }
+
+    if (!load_thread_description()) {
+        goto error;
+    }
+
+    hr = GetThreadDescriptionFunc(GetCurrentThread(), &namew);
+    if (!SUCCEEDED(hr)) {
+        goto error;
+    }
+
+    name = g_utf16_to_utf8(namew, -1, NULL, NULL, NULL);
+    LocalFree(namew);
+    if (!name) {
+        goto error;
+    }
+
+    g_strlcpy(namebuf, name, G_N_ELEMENTS(namebuf));
+    return namebuf;
+
+ error:
+    g_strlcpy(namebuf, "unnamed", G_N_ELEMENTS(namebuf));
+    return namebuf;
+}
-- 
2.52.0


Re: [PATCH v5 08/24] util: add API to fetch the current thread name
Posted by Markus Armbruster via Devel 2 weeks, 5 days ago
Daniel P. Berrangé <berrange@redhat.com> writes:

> This will be used to include the thread name in error reports
> in a later patch. It returns a const string stored in a thread
> local to avoid memory allocation when it is called repeatedly
> in a single thread. The thread name should be set at the very
> start of the thread execution, which is the case when using
> qemu_thread_create.
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  include/qemu/thread.h    |  1 +
>  meson.build              | 21 +++++++++++++++++
>  util/qemu-thread-posix.c | 33 ++++++++++++++++++++++++++-
>  util/qemu-thread-win32.c | 49 ++++++++++++++++++++++++++++++++++++----
>  4 files changed, 99 insertions(+), 5 deletions(-)

Tempted to store the thread name in TLS and call it a day.
Re: [PATCH v5 08/24] util: add API to fetch the current thread name
Posted by Daniel P. Berrangé via Devel 2 weeks, 5 days ago
On Tue, Jan 13, 2026 at 10:27:04AM +0100, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > This will be used to include the thread name in error reports
> > in a later patch. It returns a const string stored in a thread
> > local to avoid memory allocation when it is called repeatedly
> > in a single thread. The thread name should be set at the very
> > start of the thread execution, which is the case when using
> > qemu_thread_create.
> >
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > ---
> >  include/qemu/thread.h    |  1 +
> >  meson.build              | 21 +++++++++++++++++
> >  util/qemu-thread-posix.c | 33 ++++++++++++++++++++++++++-
> >  util/qemu-thread-win32.c | 49 ++++++++++++++++++++++++++++++++++++----
> >  4 files changed, 99 insertions(+), 5 deletions(-)
> 
> Tempted to store the thread name in TLS and call it a day.

Using the official APIs in this way ensures that the thread name is
visible outside QEMU. For example when debugging in GDB, which IMHO
is an important benefit.

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

Re: [PATCH v5 08/24] util: add API to fetch the current thread name
Posted by Markus Armbruster 2 weeks, 5 days ago
Daniel P. Berrangé <berrange@redhat.com> writes:

> On Tue, Jan 13, 2026 at 10:27:04AM +0100, Markus Armbruster wrote:
>> Daniel P. Berrangé <berrange@redhat.com> writes:
>> 
>> > This will be used to include the thread name in error reports
>> > in a later patch. It returns a const string stored in a thread
>> > local to avoid memory allocation when it is called repeatedly
>> > in a single thread. The thread name should be set at the very
>> > start of the thread execution, which is the case when using
>> > qemu_thread_create.
>> >
>> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
>> > ---
>> >  include/qemu/thread.h    |  1 +
>> >  meson.build              | 21 +++++++++++++++++
>> >  util/qemu-thread-posix.c | 33 ++++++++++++++++++++++++++-
>> >  util/qemu-thread-win32.c | 49 ++++++++++++++++++++++++++++++++++++----
>> >  4 files changed, 99 insertions(+), 5 deletions(-)
>> 
>> Tempted to store the thread name in TLS and call it a day.
>
> Using the official APIs in this way ensures that the thread name is
> visible outside QEMU. For example when debugging in GDB, which IMHO
> is an important benefit.

I didn't mean to suggest not to set the "official" thread name.

This patch retrieves the "official" thread name back.  Takes a bit of
system-specific code, including Meson magic.  We could instead hold on
to our own copy, and just use that.
Re: [PATCH v5 08/24] util: add API to fetch the current thread name
Posted by Daniel P. Berrangé via Devel 2 weeks, 4 days ago
On Tue, Jan 13, 2026 at 02:00:35PM +0100, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > On Tue, Jan 13, 2026 at 10:27:04AM +0100, Markus Armbruster wrote:
> >> Daniel P. Berrangé <berrange@redhat.com> writes:
> >> 
> >> > This will be used to include the thread name in error reports
> >> > in a later patch. It returns a const string stored in a thread
> >> > local to avoid memory allocation when it is called repeatedly
> >> > in a single thread. The thread name should be set at the very
> >> > start of the thread execution, which is the case when using
> >> > qemu_thread_create.
> >> >
> >> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> >> > ---
> >> >  include/qemu/thread.h    |  1 +
> >> >  meson.build              | 21 +++++++++++++++++
> >> >  util/qemu-thread-posix.c | 33 ++++++++++++++++++++++++++-
> >> >  util/qemu-thread-win32.c | 49 ++++++++++++++++++++++++++++++++++++----
> >> >  4 files changed, 99 insertions(+), 5 deletions(-)
> >> 
> >> Tempted to store the thread name in TLS and call it a day.
> >
> > Using the official APIs in this way ensures that the thread name is
> > visible outside QEMU. For example when debugging in GDB, which IMHO
> > is an important benefit.
> 
> I didn't mean to suggest not to set the "official" thread name.
> 
> This patch retrieves the "official" thread name back.  Takes a bit of
> system-specific code, including Meson magic.  We could instead hold on
> to our own copy, and just use that.

That would mean we don't get any names for threads which are spawned
indirectly.  There are quite a lot of libraries that QEMU can use,
which can spawn threads behind QEMU's back, and these threads can
still be running QEMU code through callbacks. spice, gstreamer,
jack and librbd are some I know that spawn threads, but there are
likely quite a few more. In the the jack case we hook into its thread
creation to set a name ourselves, but we can't rely on that in general,
and these libraries may well have set thread names we should use. 

I want to maximise the cases where we can retrieve a thread name.
While the code is more verbose than I'd like, it exists now so I
don't think its good to throw it away to put into a worse solution.

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

Re: [PATCH v5 08/24] util: add API to fetch the current thread name
Posted by Paolo Bonzini 2 weeks, 5 days ago
On Tue, Jan 13, 2026 at 2:00 PM Markus Armbruster <armbru@redhat.com> wrote:
> > > Tempted to store the thread name in TLS and call it a day.
> >
> > Using the official APIs in this way ensures that the thread name is
> > visible outside QEMU. For example when debugging in GDB, which IMHO
> > is an important benefit.
>
> I didn't mean to suggest not to set the "official" thread name.
>
> This patch retrieves the "official" thread name back.  Takes a bit of
> system-specific code, including Meson magic.  We could instead hold on
> to our own copy, and just use that.

Yes, I think that's what we're going to do anyway due to my remark on
patch 7/24.

Paolo
Re: [PATCH v5 08/24] util: add API to fetch the current thread name
Posted by Daniel P. Berrangé via Devel 2 weeks, 4 days ago
On Tue, Jan 13, 2026 at 04:49:53PM +0100, Paolo Bonzini wrote:
> On Tue, Jan 13, 2026 at 2:00 PM Markus Armbruster <armbru@redhat.com> wrote:
> > > > Tempted to store the thread name in TLS and call it a day.
> > >
> > > Using the official APIs in this way ensures that the thread name is
> > > visible outside QEMU. For example when debugging in GDB, which IMHO
> > > is an important benefit.
> >
> > I didn't mean to suggest not to set the "official" thread name.
> >
> > This patch retrieves the "official" thread name back.  Takes a bit of
> > system-specific code, including Meson magic.  We could instead hold on
> > to our own copy, and just use that.
> 
> Yes, I think that's what we're going to do anyway due to my remark on
> patch 7/24.

That doesn't alter things. The constructor merely initialzies the name
for the main thread. We'll still use pthread APIs for all other threads.


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

Re: [PATCH v5 08/24] util: add API to fetch the current thread name
Posted by Paolo Bonzini 3 weeks, 2 days ago
On 1/8/26 18:03, Daniel P. Berrangé wrote:
> +static __thread char namebuf[PTHREAD_MAX_NAMELEN_NP];

... you can instead of the previous patch, add a constructor here that 
just sets namebuf to "main" with strcpy.

For Windows on the other hand it should be okay to call 
SetThreadDescription if available.

Paolo


Re: [PATCH v5 08/24] util: add API to fetch the current thread name
Posted by Daniel P. Berrangé 3 weeks, 2 days ago
On Fri, Jan 09, 2026 at 12:49:20PM +0100, Paolo Bonzini wrote:
> On 1/8/26 18:03, Daniel P. Berrangé wrote:
> > +static __thread char namebuf[PTHREAD_MAX_NAMELEN_NP];
> 
> ... you can instead of the previous patch, add a constructor here that just
> sets namebuf to "main" with strcpy.

How about just a static initializer

  static __thread char namebuf[PTHREAD_MAX_NAMELEN_NP] = { 'm', 'a', 'i', 'n', '\0' };

or is there some interaction with __thread that makes that undesirable ?

The downside is that I wanted the nice thread names to appear in GDB
too, but I guess we can live with the main thread being unnamed in
GDB.

> 
> For Windows on the other hand it should be okay to call SetThreadDescription
> if available.
> 
> Paolo
> 

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|


Re: [PATCH v5 08/24] util: add API to fetch the current thread name
Posted by Paolo Bonzini 3 weeks, 2 days ago
On 1/9/26 12:56, Daniel P. Berrangé wrote:
> On Fri, Jan 09, 2026 at 12:49:20PM +0100, Paolo Bonzini wrote:
>> On 1/8/26 18:03, Daniel P. Berrangé wrote:
>>> +static __thread char namebuf[PTHREAD_MAX_NAMELEN_NP];
>>
>> ... you can instead of the previous patch, add a constructor here that just
>> sets namebuf to "main" with strcpy.
> 
> How about just a static initializer
> 
>    static __thread char namebuf[PTHREAD_MAX_NAMELEN_NP] = { 'm', 'a', 'i', 'n', '\0' };
> 
> or is there some interaction with __thread that makes that undesirable ?

This would break here:

     if (namebuf[0] != '\0') {
         return namebuf;
     }

and every thread would have "main" as the name, because static 
initializers for __thread apply to all threads.

Thanks,

Paolo