diff --git a/CMakeLists.txt b/CMakeLists.txt index ed2253b05..3693b5b37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -275,6 +275,9 @@ if (DEFINED HAVE_INET_PTON) add_definitions(-DHAVE_INET_PTON=1) endif() +include(FindPThreadGetSetName) +FindPThreadGetSetName() # Defines HAVE_PTHREAD_GETNAME_* and HAVE_PTHREAD_SETNAME_* + if (ENABLE_MONOTONIC_CLOCK) if (NOT ENABLE_MONOTONIC_CLOCK_DEFAULT) message(FATAL_ERROR "Your platform does not support CLOCK_MONOTONIC. Build with -DENABLE_MONOTONIC_CLOCK=OFF.") diff --git a/scripts/FindPThreadGetSetName.cmake b/scripts/FindPThreadGetSetName.cmake new file mode 100644 index 000000000..fa818fd73 --- /dev/null +++ b/scripts/FindPThreadGetSetName.cmake @@ -0,0 +1,82 @@ +# +# SRT - Secure, Reliable, Transport +# Copyright (c) 2021 Haivision Systems Inc. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# Check for pthread_getname_np(3) and pthread_setname_np(3) +# used in srtcore/threadname.h. +# +# Some BSD distros need to include for pthread_getname_np(). +# +# TODO: Some BSD distros have pthread_get_name_np() and pthread_set_name_np() +# instead of pthread_getname_np() and pthread_setname_np(). +# +# Sets: +# HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H +# HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H +# HAVE_PTHREAD_GETNAME_NP +# HAVE_PTHREAD_SETNAME_NP +# Sets as appropriate: +# add_definitions(-DHAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H=1) +# add_definitions(-DHAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H=1) +# add_definitions(-DHAVE_PTHREAD_GETNAME_NP=1) +# add_definitions(-DHAVE_PTHREAD_SETNAME_NP=1) + +include(CheckSymbolExists) + +function(FindPThreadGetSetName) + + unset(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) + unset(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H PARENT_SCOPE) + unset(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H CACHE) + unset(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) + unset(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H PARENT_SCOPE) + unset(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H CACHE) + + unset(HAVE_PTHREAD_GETNAME_NP) + unset(HAVE_PTHREAD_GETNAME_NP PARENT_SCOPE) + unset(HAVE_PTHREAD_GETNAME_NP CACHE) + unset(HAVE_PTHREAD_SETNAME_NP) + unset(HAVE_PTHREAD_SETNAME_NP PARENT_SCOPE) + unset(HAVE_PTHREAD_SETNAME_NP CACHE) + + set(CMAKE_REQUIRED_DEFINITIONS + -D_GNU_SOURCE -D_DARWIN_C_SOURCE -D_POSIX_SOURCE=1) + set(CMAKE_REQUIRED_FLAGS "-pthread") + + message(STATUS "Checking for pthread_(g/s)etname_np in 'pthread_np.h':") + check_symbol_exists( + pthread_getname_np "pthread_np.h" HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) + if (HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) + add_definitions(-DHAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H=1) + endif() + check_symbol_exists( + pthread_setname_np "pthread_np.h" HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) + if (HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) + add_definitions(-DHAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H=1) + endif() + + message(STATUS "Checking for pthread_(g/s)etname_np in 'pthread.h':") + check_symbol_exists(pthread_getname_np "pthread.h" HAVE_PTHREAD_GETNAME_NP) + if (HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) + set(HAVE_PTHREAD_GETNAME_NP TRUE PARENT_SCOPE) + endif() + check_symbol_exists(pthread_setname_np "pthread.h" HAVE_PTHREAD_SETNAME_NP) + if (HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) + set(HAVE_PTHREAD_SETNAME_NP TRUE PARENT_SCOPE) + endif() + if (HAVE_PTHREAD_GETNAME_NP) + add_definitions(-DHAVE_PTHREAD_GETNAME_NP=1) + endif() + if (HAVE_PTHREAD_SETNAME_NP) + add_definitions(-DHAVE_PTHREAD_SETNAME_NP=1) + endif() + + unset(CMAKE_REQUIRED_DEFINITIONS) + unset(CMAKE_REQUIRED_FLAGS) + +endfunction(FindPThreadGetSetName) diff --git a/srtcore/srt_attr_defs.h b/srtcore/srt_attr_defs.h index 82e6e5e3a..00d35e069 100644 --- a/srtcore/srt_attr_defs.h +++ b/srtcore/srt_attr_defs.h @@ -116,7 +116,7 @@ used by SRT library internally. #define SRT_ATTR_NO_THREAD_SAFETY_ANALYSIS #else -#if defined(__clang__) +#if defined(__clang__) && defined(__clang_major__) && (__clang_major__ > 5) #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) #else #define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op diff --git a/srtcore/threadname.h b/srtcore/threadname.h index 2b3964276..e392f6d8e 100644 --- a/srtcore/threadname.h +++ b/srtcore/threadname.h @@ -16,24 +16,60 @@ written by #ifndef INC_SRT_THREADNAME_H #define INC_SRT_THREADNAME_H -#if defined(__APPLE__) || defined(__linux__) -#if defined(__linux__) -#include +// NOTE: +// HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H +// HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H +// HAVE_PTHREAD_GETNAME_NP +// HAVE_PTHREAD_GETNAME_NP +// Are detected and set in ../CMakeLists.txt. +// OS Availability of pthread_getname_np(..) and pthread_setname_np(..):: +// MacOS(10.6) +// iOS(3.2) +// AIX(7.1) +// FreeBSD(version?), OpenBSD(Version?) +// Linux-GLIBC(GLIBC-2.12). +// Linux-MUSL(MUSL-1.1.20 Partial Implementation. See below). +// MINGW-W64(4.0.6) + +#if defined(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) \ + || defined(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) + #include + #if defined(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) \ + && !defined(HAVE_PTHREAD_GETNAME_NP) + #define HAVE_PTHREAD_GETNAME_NP 1 + #endif + #if defined(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) \ + && !defined(HAVE_PTHREAD_SETNAME_NP) + #define HAVE_PTHREAD_SETNAME_NP 1 + #endif #endif -#include +#if (defined(HAVE_PTHREAD_GETNAME_NP) && defined(HAVE_PTHREAD_GETNAME_NP)) \ + || defined(__linux__) + // NOTE: + // Linux pthread_getname_np() and pthread_setname_np() became available + // in GLIBC-2.12 and later. + // Some Linux runtimes do not have pthread_getname_np(), but have + // pthread_setname_np(), for instance MUSL at least as of v1.1.20. + // So using the prctl() for Linux is more portable. + #if defined(__linux__) + #include + #endif + #include #endif #include #include #include +#include "common.h" #include "sync.h" class ThreadName { -#if defined(__APPLE__) || defined(__linux__) +#if (defined(HAVE_PTHREAD_GETNAME_NP) && defined(HAVE_PTHREAD_GETNAME_NP)) \ + || defined(__linux__) class ThreadNameImpl { @@ -47,8 +83,7 @@ class ThreadName // since Linux 2.6.11. The buffer should allow space for up to 16 // bytes; the returned string will be null-terminated. return prctl(PR_GET_NAME, (unsigned long)namebuf, 0, 0) != -1; -#elif defined(__APPLE__) - // since macos(10.6), ios(3.2) +#elif defined(HAVE_PTHREAD_GETNAME_NP) return pthread_getname_np(pthread_self(), namebuf, BUFSIZE) == 0; #else #error "unsupported platform" @@ -57,14 +92,18 @@ class ThreadName static bool set(const char* name) { + SRT_ASSERT(name != NULL); #if defined(__linux__) // The name can be up to 16 bytes long, including the terminating // null byte. (If the length of the string, including the terminating // null byte, exceeds 16 bytes, the string is silently truncated.) return prctl(PR_SET_NAME, (unsigned long)name, 0, 0) != -1; -#elif defined(__APPLE__) - // since macos(10.6), ios(3.2) +#elif defined(HAVE_PTHREAD_SETNAME_NP) + #if defined(__APPLE__) return pthread_setname_np(name) == 0; + #else + return pthread_setname_np(pthread_self(), name) == 0; + #endif #else #error "unsupported platform" #endif