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 <a.samirh78@gmail.com>
This commit is contained in:
Thiago Macieira 2024-11-02 11:25:23 -07:00
parent b6ca35f653
commit 2a7cacb5e3
4 changed files with 47 additions and 14 deletions

View File

@ -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 <pthread.h>
#include <time.h>
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

View File

@ -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 <clockid_t ClockId = SteadyClockClockId>
inline timespec deadlineToAbstime(QDeadlineTimer deadline)
{
using namespace std::chrono;
using Clock =
std::conditional_t<SteadyClockClockId == CLOCK_REALTIME, system_clock, steady_clock>;
std::conditional_t<ClockId == CLOCK_REALTIME, system_clock, steady_clock>;
auto timePoint = deadline.deadline<Clock>();
if (timePoint < Clock::time_point{})
if (timePoint < typename Clock::time_point{})
return {};
return durationToTimespec(timePoint.time_since_epoch());
}

View File

@ -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

View File

@ -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<QWaitConditionClockId>(deadline);
return pthread_cond_timedwait(&cond, &mutex, &ti);
}