From 2a7cacb5e3d2643a7f2cbd6bc861374a7ee926ea Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 2 Nov 2024 11:25:23 -0700 Subject: [PATCH] QWaitCondition/Unix: do check for pthread_condattr_setclock() Instead of guessing that Apple systems don't have it. Because of this, we properly split the clockid_t constants in qcore_unix_p.h between what the std::chrono::steady_clock uses and what QWaitCondition will use. The difference is on Apple systems and on QNX. Therefore, amends 5642b999754e75a9db3585b97ffbddac761f21b3. Change-Id: Ibf5439b6cb4c332b0f24fffde43452e8ccd4e9c9 Reviewed-by: Ahmad Samir --- src/corelib/configure.cmake | 19 +++++++++++++ src/corelib/kernel/qcore_unix_p.h | 32 ++++++++++++++++------ src/corelib/thread/qthread_unix.cpp | 2 +- src/corelib/thread/qwaitcondition_unix.cpp | 8 +++--- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake index 2de00f0f38c..de42a8c03ee 100644 --- a/src/corelib/configure.cmake +++ b/src/corelib/configure.cmake @@ -446,6 +446,20 @@ int main() } ") +# pthread_condattr_setclock +qt_config_compile_test(pthread_condattr_setclock + LABEL "pthread_condattr_setclock()" + LIBRARIES Threads::Threads + CODE +"#include +#include +int main() +{ + pthread_condattr_t condattr; + return pthread_condattr_setclock(&condattr, CLOCK_REALTIME); +} +") + # pthread_timedjoin qt_config_compile_test(pthread_timedjoin LABEL "pthread_timedjoin()" @@ -730,6 +744,11 @@ qt_feature("pthread_clockjoin" PRIVATE AUTODETECT UNIX CONDITION UNIX AND QT_FEATURE_thread AND TEST_pthread_clockjoin ) +qt_feature("pthread_condattr_setclock" PRIVATE + LABEL "pthread_condattr_setclock() function" + AUTODETECT UNIX + CONDITION UNIX AND QT_FEATURE_thread AND TEST_pthread_condattr_setclock +) qt_feature("pthread_timedjoin" PRIVATE LABEL "pthread_timedjoin() function" AUTODETECT UNIX diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 1a3611e49cf..3fdd965f98b 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -75,14 +75,12 @@ static inline constexpr clockid_t SteadyClockClockId = #elif defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_CLOCK_MONOTONIC) // libstdc++ falling back to system_clock CLOCK_REALTIME -#elif defined(Q_OS_DARWIN) - // Darwin lacks pthread_condattr_setclock() - CLOCK_REALTIME -#elif defined(Q_OS_QNX) - // unknown why - CLOCK_REALTIME +#elif defined(_LIBCPP_VERSION) && defined(Q_OS_DARWIN) + // on Apple systems, libc++ uses CLOCK_MONOTONIC_RAW since LLVM 11 + // https://github.com/llvm/llvm-project/blob/llvmorg-11.0.0/libcxx/src/chrono.cpp#L117-L129 + CLOCK_MONOTONIC_RAW #elif defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) - // both libstdc++ and libc++ do use CLOCK_MONOTONIC + // both libstdc++ and libc++ otherwise use CLOCK_MONOTONIC CLOCK_MONOTONIC #else # warning "Unknown C++ Standard Library implementation - code may be sub-optimal" @@ -90,6 +88,21 @@ static inline constexpr clockid_t SteadyClockClockId = #endif ; +static inline constexpr clockid_t QWaitConditionClockId = +#if !QT_CONFIG(thread) + // bootstrap mode, there are no wait conditions + CLOCK_REALTIME +#elif !QT_CONFIG(pthread_condattr_setclock) + // OSes that lack pthread_condattr_setclock() (e.g., Darwin) + CLOCK_REALTIME +#elif defined(Q_OS_QNX) + // unknown why use of the monotonic clock causes failures + CLOCK_REALTIME +#else + SteadyClockClockId; +#endif + ; + static constexpr auto OneSecAsNsecs = std::chrono::nanoseconds(std::chrono::seconds{ 1 }).count(); inline timespec durationToTimespec(std::chrono::nanoseconds timeout) noexcept @@ -205,13 +218,14 @@ inline timespec qAbsTimespec(timespec ts) return normalizedTimespec(ts); } +template inline timespec deadlineToAbstime(QDeadlineTimer deadline) { using namespace std::chrono; using Clock = - std::conditional_t; + std::conditional_t; auto timePoint = deadline.deadline(); - if (timePoint < Clock::time_point{}) + if (timePoint < typename Clock::time_point{}) return {}; return durationToTimespec(timePoint.time_since_epoch()); } diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index d6a8c452d94..ecfe139bba2 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -95,7 +95,7 @@ enum { ThreadPriorityResetFlag = 0x80000000 }; // // To support this scenario, we start the thread in detached state. static constexpr bool UsingPThreadTimedJoin = QT_CONFIG(pthread_clockjoin) - || (QT_CONFIG(pthread_timedjoin) && SteadyClockClockId == CLOCK_REALTIME); + || (QT_CONFIG(pthread_timedjoin) && QWaitConditionClockId == CLOCK_REALTIME); #if !QT_CONFIG(pthread_clockjoin) int pthread_clockjoin_np(...) { return ENOSYS; } // pretend #endif diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp index d1387d1b4d5..264019fe745 100644 --- a/src/corelib/thread/qwaitcondition_unix.cpp +++ b/src/corelib/thread/qwaitcondition_unix.cpp @@ -30,14 +30,14 @@ static void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where) { pthread_condattr_t *attrp = nullptr; -#if defined(CLOCK_MONOTONIC) && !defined(Q_OS_DARWIN) +#if QT_CONFIG(pthread_condattr_setclock) pthread_condattr_t condattr; attrp = &condattr; pthread_condattr_init(&condattr); auto destroy = qScopeGuard([&] { pthread_condattr_destroy(&condattr); }); - if (SteadyClockClockId != CLOCK_REALTIME) - pthread_condattr_setclock(&condattr, SteadyClockClockId); + if (QWaitConditionClockId != CLOCK_REALTIME) + pthread_condattr_setclock(&condattr, QWaitConditionClockId); #endif qt_report_pthread_error(pthread_cond_init(cond, attrp), where, "cv init"); @@ -53,7 +53,7 @@ public: int wait_relative(QDeadlineTimer deadline) { - timespec ti = deadlineToAbstime(deadline); + timespec ti = deadlineToAbstime(deadline); return pthread_cond_timedwait(&cond, &mutex, &ti); }