Daniel P. Berrangé <berra...@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. This makes the assumption that the thread
> name is set at the very start of the thread, which is the case
> when using qemu_thread_create.

What happens when the assumption is violated?

> Signed-off-by: Daniel P. Berrangé <berra...@redhat.com>
> ---
>  include/qemu/thread.h    |  1 +
>  meson.build              | 21 +++++++++++++++++
>  util/qemu-thread-posix.c | 28 ++++++++++++++++++++++-
>  util/qemu-thread-win32.c | 49 ++++++++++++++++++++++++++++++++++++----
>  4 files changed, 94 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 fa6186db33..6aa673f4b2 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -2920,6 +2920,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 275445ed94..fbb94ca97b 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,29 @@ void *qemu_thread_join(QemuThread *thread)
>      }
>      return ret;
>  }
> +
> +#ifndef PTHREAD_MAX_NAMELEN_NP
> +#define PTHREAD_MAX_NAMELEN_NP 16

Feels a bit tight.  32?

> +#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) {
> +        strlcpy(namebuf, "unnamed", G_N_ELEMENTS(namebuf));
> +    }
> +    return namebuf;
> +}
> diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
> index 7a734a7a09..e3789c20d1 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)
> @@ -326,7 +332,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;
>      }
>  
> @@ -412,3 +418,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:
> +    strlcpy(namebuf, "unnamed", G_N_ELEMENTS(namebuf));
> +    return namebuf;
> +}


Reply via email to