Simplify the detection for the monotonic clock in qelapsedtimer_unix.cpp

Unlike the previous code, we now entrust the compiler to properly
implement thread-safe statics for this code. That was the main reason
why the old code was confusing, trying to determine if the clock IDs
were positive or negative.

Instead, simply make a call to clock_getres(CLOCK_MONOTONIC) and that
will tell us if the monotonic clock is supported.

Change-Id: I0031aa609e714ae983c3fffd1469522a68fa3b66
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Thiago Macieira 2016-08-09 19:44:55 -07:00 committed by Marcel Krems
parent 7c3208c97d
commit 8c8cbd1508

View File

@ -101,55 +101,49 @@ static inline void qt_clock_gettime(int, struct timespec *ts)
ts->tv_nsec = tv.tv_usec * 1000;
}
# ifdef _POSIX_MONOTONIC_CLOCK
# undef _POSIX_MONOTONIC_CLOCK
# define _POSIX_MONOTONIC_CLOCK -1
# endif
static inline int regularClock()
{
return 0;
}
#else
static inline void qt_clock_gettime(clockid_t clock, struct timespec *ts)
{
clock_gettime(clock, ts);
}
#endif
static int unixCheckClockType()
static inline clock_t regularClockCheck()
{
#ifdef Q_OS_LINUX
struct timespec regular_clock_resolution;
int r = -1;
# ifdef CLOCK_MONOTONIC
// try the monotonic clock
r = clock_getres(CLOCK_MONOTONIC, &regular_clock_resolution);
# ifdef Q_OS_LINUX
// Despite glibc claiming that we should check at runtime, the Linux kernel
// always supports the monotonic clock
Q_ASSERT(r == 0);
return CLOCK_MONOTONIC;
#elif (_POSIX_MONOTONIC_CLOCK-0 == 0) && defined(_SC_MONOTONIC_CLOCK)
// we need a value we can store in a clockid_t that isn't a valid clock
// check if the valid ones are both non-negative or both non-positive
# if CLOCK_MONOTONIC >= 0 && CLOCK_REALTIME >= 0
# define IS_VALID_CLOCK(clock) (clock >= 0)
# define INVALID_CLOCK -1
# elif CLOCK_MONOTONIC <= 0 && CLOCK_REALTIME <= 0
# define IS_VALID_CLOCK(clock) (clock <= 0)
# define INVALID_CLOCK 1
# else
# error "Sorry, your system has weird values for CLOCK_MONOTONIC and CLOCK_REALTIME"
# endif
if (r == 0)
return CLOCK_MONOTONIC;
# endif
static QBasicAtomicInt clockToUse = Q_BASIC_ATOMIC_INITIALIZER(INVALID_CLOCK);
int clock = clockToUse.loadAcquire();
if (Q_LIKELY(IS_VALID_CLOCK(clock)))
return clock;
// detect if the system supports monotonic timers
clock = sysconf(_SC_MONOTONIC_CLOCK) > 0 ? CLOCK_MONOTONIC : CLOCK_REALTIME;
clockToUse.storeRelease(clock);
return clock;
# undef INVALID_CLOCK
# undef IS_VALID_CLOCK
#elif (_POSIX_MONOTONIC_CLOCK-0) > 0
return CLOCK_MONOTONIC;
#else
// no monotonic, try the realtime clock
r = clock_getres(CLOCK_REALTIME, &regular_clock_resolution);
Q_ASSERT(r == 0);
return CLOCK_REALTIME;
#endif
}
static inline clock_t regularClock()
{
static const clock_t clock = regularClockCheck();
return clock;
}
#endif
bool QElapsedTimer::isMonotonic() noexcept
{
return clockType() == MonotonicClock;
@ -157,13 +151,13 @@ bool QElapsedTimer::isMonotonic() noexcept
QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept
{
return unixCheckClockType() == CLOCK_REALTIME ? SystemTime : MonotonicClock;
return regularClock() == CLOCK_REALTIME ? SystemTime : MonotonicClock;
}
static inline void do_gettime(qint64 *sec, qint64 *frac)
{
timespec ts;
qt_clock_gettime(unixCheckClockType(), &ts);
qt_clock_gettime(regularClock(), &ts);
*sec = ts.tv_sec;
*frac = ts.tv_nsec;
}