Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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" HAVE_PTHREAD_SETNAME_NP)
Comment thread
KushalP marked this conversation as resolved.
Outdated
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;
}