From: Narcisa Vasile <navas...@microsoft.com> Implement function that sets the name of a thread. On Windows, SetThreadDescription() is used. Use GetProcAddress() to obtain the address of the function for MinGW compatibility.
Depends-on: series-17402 ("eal: Add EAL API for threading") Signed-off-by: Narcisa Vasile <navas...@microsoft.com> --- lib/eal/common/rte_thread.c | 17 ++++++++++ lib/eal/include/rte_thread.h | 18 +++++++++++ lib/eal/version.map | 1 + lib/eal/windows/rte_thread.c | 60 ++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+) diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c index 3fdb267337..fbff1168e5 100644 --- a/lib/eal/common/rte_thread.c +++ b/lib/eal/common/rte_thread.c @@ -373,6 +373,23 @@ rte_thread_barrier_destroy(rte_thread_barrier *barrier) return ret; } +int +rte_thread_name_set(rte_thread_t thread_id, const char *name) +{ + int ret = ENOSYS; +#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +#if __GLIBC_PREREQ(2, 12) + char truncated[RTE_THREAD_MAX_DESCRIPTION_LENGTH]; + + memcpy(truncated, name, sizeof(truncated)); + ret = pthread_setname_np((pthread_t)thread_id.opaque_id, truncated); +#endif +#endif + RTE_SET_USED(thread_id); + RTE_SET_USED(name); + return ret; +} + int rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *)) { diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h index 40da83467b..c65cfd8c9e 100644 --- a/lib/eal/include/rte_thread.h +++ b/lib/eal/include/rte_thread.h @@ -24,6 +24,8 @@ extern "C" { #include <sched.h> +#define RTE_THREAD_MAX_DESCRIPTION_LENGTH 16 + /** * Thread id descriptor. */ @@ -439,6 +441,22 @@ int rte_thread_barrier_wait(rte_thread_barrier *barrier); __rte_experimental int rte_thread_barrier_destroy(rte_thread_barrier *barrier); +/** + * Set the name of the thread represented by 'thread_id'. + * + * @param thread_id + * The id of the thread. + * + * @param name + * Thread name to set. + * + * @return + * On success, return 0. + * On failure, return a positive errno-style error number. + */ +__rte_experimental +int rte_thread_name_set(rte_thread_t thread_id, const char *name); + /** * Create a TLS data key visible to all threads in the process. * the created key is later used to get/set a value. diff --git a/lib/eal/version.map b/lib/eal/version.map index 6645f60a78..2a566c04af 100644 --- a/lib/eal/version.map +++ b/lib/eal/version.map @@ -443,6 +443,7 @@ EXPERIMENTAL { rte_thread_barrier_init; rte_thread_barrier_wait; rte_thread_barrier_destroy; + rte_thread_name_set; }; INTERNAL { diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c index b2ff16f51f..995ae2491d 100644 --- a/lib/eal/windows/rte_thread.c +++ b/lib/eal/windows/rte_thread.c @@ -556,6 +556,66 @@ rte_thread_barrier_destroy(rte_thread_barrier *barrier) return 0; } +typedef HRESULT +(*SetThreadDescription_type)(HANDLE thread_handle, PCWSTR thread_description); + +int +rte_thread_name_set(rte_thread_t thread_id, const char *name) +{ + int ret = 0; + size_t count; + HRESULT hr; + HANDLE thread_handle = NULL; + WCHAR w_name[RTE_THREAD_MAX_DESCRIPTION_LENGTH]; + HMODULE kernel_lib = NULL; + SetThreadDescription_type SetThreadDescription_ptr; + + static const char library_name[] = "kernel32.dll"; + static const char function[] = "SetThreadDescription"; + + kernel_lib = LoadLibraryA(library_name); + if (kernel_lib == NULL) { + ret = thread_log_last_error("LoadLibraryA(\"kernel32.dll\")"); + goto cleanup; + } + + SetThreadDescription_ptr = (SetThreadDescription_type)( + (void *)GetProcAddress(kernel_lib, function)); + if (SetThreadDescription_ptr == NULL) { + ret = thread_log_last_error("GetProcAddress(\"kernel32.dll\", \"SetThreadDescription\")"); + goto cleanup; + } + + thread_handle = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, + thread_id.opaque_id); + if (thread_handle == NULL) { + ret = thread_log_last_error("OpenThread()"); + goto cleanup; + } + + count = mbstowcs(w_name, name, RTE_THREAD_MAX_DESCRIPTION_LENGTH); + if (count < 0) { + RTE_LOG(DEBUG, EAL, "Invalid thread name!\n"); + ret = EINVAL; + goto cleanup; + } + + hr = SetThreadDescription_ptr(thread_handle, w_name); + if (FAILED(hr)) { + ret = thread_log_last_error("SetThreadDescription()"); + goto cleanup; + } + +cleanup: + if (kernel_lib != NULL) + FreeLibrary(kernel_lib); + if (thread_handle != NULL) { + CloseHandle(thread_handle); + thread_handle = NULL; + } + return ret; +} + int rte_thread_key_create(rte_thread_key *key, __rte_unused void (*destructor)(void *)) -- 2.31.0.vfs.0.1