diff --git a/CMakeLists.txt b/CMakeLists.txt index 626368d01..d82c1185d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -271,6 +271,14 @@ if (HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME) add_compile_definitions($<$:_GNU_SOURCE=1>) endif() check_symbol_exists(__printflike "bsd/sys/cdefs.h" HAVE_PRINTFLIKE) +if(UNIX) + list(APPEND CMAKE_REQUIRED_LIBRARIES Threads::Threads) + check_symbol_exists(pthread_setname_np "pthread.h;pthread_np.h" HAVE_PTHREAD_SETNAME_NP) + check_symbol_exists(pthread_getname_np "pthread.h;pthread_np.h" HAVE_PTHREAD_GETNAME_NP) + check_symbol_exists(pthread_get_name_np "pthread.h;pthread_np.h" HAVE_PTHREAD_GET_NAME_NP) + check_symbol_exists(pthread_set_name_np "pthread.h;pthread_np.h" HAVE_PTHREAD_SET_NAME_NP) + list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES Threads::Threads) +endif() if(CMAKE_SYSTEM_NAME STREQUAL Android) set(ENABLE_DTRACE_DEFAULT OFF) diff --git a/cmake/config.h.in b/cmake/config.h.in index 27737c991..f4ccf5314 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -208,6 +208,18 @@ /* Define to 1 if you have the `_pthread_workqueue_init' function. */ #cmakedefine HAVE__PTHREAD_WORKQUEUE_INIT +/* Define to 1 if you have the `pthread_setname_np' function. */ +#cmakedefine01 HAVE_PTHREAD_SETNAME_NP + +/* Define to 1 if you have the `pthread_getname_np' function. */ +#cmakedefine01 HAVE_PTHREAD_GETNAME_NP + +/* Define to 1 if you have the `pthread_set_name_np' function. */ +#cmakedefine01 HAVE_PTHREAD_SET_NAME_NP + +/* Define to 1 if you have the `pthread_get_name_np' function. */ +#cmakedefine01 HAVE_PTHREAD_GET_NAME_NP + /* Define to use non-portable pthread TSD optimizations for Mac OS X) */ #cmakedefine USE_APPLE_TSD_OPTIMIZATIONS diff --git a/src/queue.c b/src/queue.c index 40f059c7a..5791457e2 100644 --- a/src/queue.c +++ b/src/queue.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2013 Apple Inc. All rights reserved. + * Copyright (c) 2008-2026 Apple Inc. All rights reserved. * * @APPLE_APACHE_LICENSE_HEADER_START@ * @@ -6217,6 +6217,12 @@ _dispatch_worker_thread(void *context) #endif _dispatch_introspection_thread_add(); +#if HAVE_PTHREAD_SETNAME_NP + pthread_setname_np(pthread_self(), "DispatchWorker"); +#elif HAVE_PTHREAD_SET_NAME_NP + pthread_set_name_np(pthread_self(), "DispatchWorker"); +#endif // HAVE_PTHREAD_SETNAME_NP + const int64_t timeout = 5ull * NSEC_PER_SEC; pthread_priority_t pp = _dispatch_get_priority(); dispatch_priority_t pri = dq->dq_priority; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0176a062b..add0de736 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -162,6 +162,10 @@ if(EXTENDED_TEST_SUITE) endif() # add C tests for platform-specific functionality when applicable +if(UNIX AND (HAVE_PTHREAD_SETNAME_NP OR HAVE_PTHREAD_SET_NAME_NP)) + list(APPEND DISPATCH_C_TESTS + thread_name) +endif() if(CMAKE_SYSTEM_NAME STREQUAL Darwin) list(APPEND DISPATCH_C_TESTS deadname diff --git a/tests/dispatch_thread_name.c b/tests/dispatch_thread_name.c new file mode 100644 index 000000000..b671c652a --- /dev/null +++ b/tests/dispatch_thread_name.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2026 Apple Inc. All rights reserved. + * + * @APPLE_APACHE_LICENSE_HEADER_START@ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @APPLE_APACHE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include + +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#include +#include +#endif +#if defined(__OpenBSD__) || defined(__FreeBSD__) +#include +#endif + +#include + +#if HAVE_PTHREAD_SET_NAME_NP && !HAVE_PTHREAD_SETNAME_NP +#define pthread_setname_np pthread_set_name_np +#endif +#if HAVE_PTHREAD_GET_NAME_NP && !HAVE_PTHREAD_GETNAME_NP +#define pthread_getname_np pthread_get_name_np +#endif + +#include +#include "dispatch_test.h" + +#define ITERATIONS 10 + +static void +set_current_thread_name(const char *name) +{ +#if defined(__APPLE__) + pthread_setname_np(name); +#else + pthread_setname_np(pthread_self(), name); +#endif +} + +int +main(void) +{ + dispatch_test_start("Dispatch Thread Name"); + + const char *parent_name = "TestParentName"; + set_current_thread_name(parent_name); + + dispatch_group_t group = dispatch_group_create(); + assert(group); + + dispatch_queue_t q = dispatch_get_global_queue(0, 0); + + for (int i = 0; i < ITERATIONS; i++) { + dispatch_group_async(group, q, ^{ + char thread_name[64] = {0}; + pthread_getname_np(pthread_self(), thread_name, sizeof(thread_name)); + fprintf(stderr, "Worker thread name: '%s'\n", thread_name); + test_long("worker thread name must not be empty", + strlen(thread_name) > 0, 1); + test_long("worker thread must not inherit parent name", + strcmp(thread_name, parent_name) != 0, 1); + }); + } + + test_group_wait(group); + dispatch_release(group); + + test_stop(); + return 0; +}