Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ check_function_exists(pthread_attr_setcpupercent_np HAVE_PTHREAD_ATTR_SETCPUPERC
check_function_exists(pthread_yield_np HAVE_PTHREAD_YIELD_NP)
check_function_exists(pthread_main_np HAVE_PTHREAD_MAIN_NP)
check_function_exists(pthread_workqueue_setdispatch_np HAVE_PTHREAD_WORKQUEUE_SETDISPATCH_NP)
check_function_exists(pthread_setname_np HAVE_PTHREAD_SETNAME_NP)
check_function_exists(strlcpy HAVE_STRLCPY)
check_function_exists(sysconf HAVE_SYSCONF)
check_function_exists(arc4random HAVE_ARC4RANDOM)
Expand Down Expand Up @@ -270,6 +269,14 @@ if (HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME)
add_compile_definitions($<$<COMPILE_LANGUAGE:C,CXX>:_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(ANDROID)
set(ENABLE_DTRACE_DEFAULT OFF)
Expand Down
9 changes: 9 additions & 0 deletions cmake/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,15 @@
/* 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

Expand Down
23 changes: 7 additions & 16 deletions src/queue.c
Original file line number Diff line number Diff line change
@@ -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@
*
Expand Down Expand Up @@ -6246,6 +6246,12 @@ _dispatch_worker_thread(void *context)
dispatch_priority_t pri = dq->dq_priority;
pthread_priority_t pp = _dispatch_get_priority();

#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

#if defined(__linux__)
// The Linux kernel does not have a direct analogue to the QoS-based
// thread policy engine found in XNU.
Expand All @@ -6263,21 +6269,6 @@ _dispatch_worker_thread(void *context)
pp = _dispatch_priority_to_pp_strip_flags(pri);
int nice = _dispatch_pp_to_nice(pp);

#if HAVE_PTHREAD_SETNAME_NP
// pthread thread names are restricted to just 16 characters
// including NUL. Truncate the label name from the beginning as it tends
// to be more unique at the end.
size_t label_length = strlen(dq->dq_label);
const char * thread_name = dq->dq_label;
if (label_length > 0) {
const size_t max_thread_name_length = 16 - 1; // minus the NUL byte;
thread_name = thread_name + (label_length - max_thread_name_length);
} else {
thread_name = "DispatchWorker";
}
pthread_setname_np(pthread_self(), thread_name);
#endif // HAVE_PTHREAD_SETNAME_NP

errno = 0;
int rc = setpriority(PRIO_PROCESS, 0, nice);
if (rc != -1 || errno == 0) {
Expand Down
4 changes: 4 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,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(APPLE)
list(APPEND DISPATCH_C_TESTS
deadname
Expand Down
88 changes: 88 additions & 0 deletions tests/dispatch_thread_name.c
Original file line number Diff line number Diff line change
@@ -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 <dispatch/dispatch.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <pthread.h>
#include <unistd.h>
#endif
#if defined(__OpenBSD__) || defined(__FreeBSD__)
#include <pthread_np.h>
#endif

#include <bsdtests.h>

#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 <bsdtests.h>
#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;
}