diff options
author | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-07-27 11:23:26 (GMT) |
---|---|---|
committer | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-07-27 11:32:29 (GMT) |
commit | 1edad2af19ee67c3e3504c8226fc3cfef9fd51a1 (patch) | |
tree | 79e4a017bedf38d9aa7fa9d1b3d3a417d11507a4 | |
parent | f2135cccffbef6d6accb49f404d9b23ade418641 (diff) | |
download | Qt-1edad2af19ee67c3e3504c8226fc3cfef9fd51a1.zip Qt-1edad2af19ee67c3e3504c8226fc3cfef9fd51a1.tar.gz Qt-1edad2af19ee67c3e3504c8226fc3cfef9fd51a1.tar.bz2 |
Refactor monotonic time code to avoid duplication.
Merge the monotonic clock source detection in
qeventdispatcher_unix.cpp with that in qcore_unix.cpp. As discussed
with Thiago, we're also removing older compat code at the same time
(spinning on select() when we think it woke up early).
Reviewed-by: Thiago
-rw-r--r-- | src/corelib/kernel/qcore_unix.cpp | 71 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_unix_p.h | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_unix.cpp | 97 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_unix_p.h | 4 |
4 files changed, 60 insertions, 114 deletions
diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp index c5b0fc7..6ef56fd 100644 --- a/src/corelib/kernel/qcore_unix.cpp +++ b/src/corelib/kernel/qcore_unix.cpp @@ -55,37 +55,72 @@ QT_BEGIN_NAMESPACE -static inline timeval gettime() +bool qt_gettime_is_monotonic() { - timeval tv; -#ifndef QT_NO_CLOCK_MONOTONIC - // use the monotonic clock - static volatile bool monotonicClockDisabled = false; - struct timespec ts; - if (!monotonicClockDisabled) { - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) { - monotonicClockDisabled = true; - } else { - tv.tv_sec = ts.tv_sec; - tv.tv_usec = ts.tv_nsec / 1000; - return tv; - } +#if (_POSIX_MONOTONIC_CLOCK-0 > 0) || defined(Q_OS_MAC) + return true; +#else + static int returnValue = 0; + + if (returnValue == 0) { +# if (_POSIX_MONOTONIC_CLOCK-0 < 0) + returnValue = -1; +# elif (_POSIX_MONOTONIC_CLOCK == 0) + // detect if the system support monotonic timers + long x = sysconf(_SC_MONOTONIC_CLOCK); + returnValue = (x >= 200112L) ? 1 : -1; +# endif } + + return returnValue != -1; #endif +} + +timeval qt_gettime() +{ + timeval tv; +#if defined(Q_OS_MAC) + static mach_timebase_info_data_t info = {0,0}; + if (info.denom == 0) + mach_timebase_info(&info); + + uint64_t cpu_time = mach_absolute_time(); + uint64_t nsecs = cpu_time * (info.numer / info.denom); + tv.tv_sec = nsecs * 1e-9; + tv.tv_usec = nsecs * 1e-3 - (t.tv_sec * 1e6); + return tv; +#elif (_POSIX_MONOTONIC_CLOCK-0 > 0) + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return tv; +#else +# if !defined(QT_NO_CLOCK_MONOTONIC) && !defined(QT_BOOTSTRAPPED) + if (qt_gettime_is_monotonic()) { + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return tv; + } +# endif // use gettimeofday ::gettimeofday(&tv, 0); return tv; +#endif } static inline bool time_update(struct timeval *tv, const struct timeval &start, const struct timeval &timeout) { - struct timeval now = gettime(); - if (now < start) { - // clock reset, give up + if (!qt_gettime_is_monotonic()) { + // we cannot recalculate the timeout without a monotonic clock as the time may have changed return false; } + // clock source is monotonic, so we can recalculate how much timeout is left + struct timeval now = qt_gettime(); *tv = timeout + start - now; return true; } @@ -100,7 +135,7 @@ int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, return ret; } - timeval start = gettime(); + timeval start = qt_gettime(); timeval timeout = *orig_timeout; // loop and recalculate the timeout as needed diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index dd97841..bffd670 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -267,6 +267,8 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options) return ret; } +bool qt_gettime_is_monotonic(); +timeval qt_gettime(); Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, const struct timeval *tv); diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index 2139545..6f1256b 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -67,25 +67,6 @@ QT_BEGIN_NAMESPACE Q_CORE_EXPORT bool qt_disable_lowpriority_timers=false; -// check for _POSIX_MONOTONIC_CLOCK support -static bool supportsMonotonicClock() -{ - bool returnValue; - -#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) - returnValue = false; -# if (_POSIX_MONOTONIC_CLOCK == 0) - // detect if the system support monotonic timers - long x = sysconf(_SC_MONOTONIC_CLOCK); - returnValue = x >= 200112L; -# endif -#else - returnValue = true; -#endif - - return returnValue; -} - /***************************************************************************** UNIX signal handling *****************************************************************************/ @@ -281,12 +262,11 @@ int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, */ QTimerInfoList::QTimerInfoList() - : useMonotonicTimers(supportsMonotonicClock()) { - getTime(currentTime); + currentTime = qt_gettime(); #if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) - if (!useMonotonicTimers) { + if (!qt_gettime_is_monotonic()) { // not using monotonic timers, initialize the timeChanged() machinery previousTime = currentTime; @@ -309,8 +289,7 @@ QTimerInfoList::QTimerInfoList() timeval QTimerInfoList::updateCurrentTime() { - getTime(currentTime); - return currentTime; + return (currentTime = qt_gettime()); } #if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC)) || defined(QT_BOOTSTRAPPED) @@ -364,38 +343,9 @@ bool QTimerInfoList::timeChanged(timeval *delta) return elapsedTimeTicks < ((qAbs(*delta) - tickGranularity) * 10); } -void QTimerInfoList::getTime(timeval &t) -{ -#if !defined(QT_NO_CLOCK_MONOTONIC) && !defined(QT_BOOTSTRAPPED) - if (useMonotonicTimers) { - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - t.tv_sec = ts.tv_sec; - t.tv_usec = ts.tv_nsec / 1000; - return; - } -#endif - - gettimeofday(&t, 0); - // NTP-related fix - while (t.tv_usec >= 1000000l) { - t.tv_usec -= 1000000l; - ++t.tv_sec; - } - while (t.tv_usec < 0l) { - if (t.tv_sec > 0l) { - t.tv_usec += 1000000l; - --t.tv_sec; - } else { - t.tv_usec = 0l; - break; - } - } -} - void QTimerInfoList::repairTimersIfNeeded() { - if (useMonotonicTimers) + if (qt_gettime_is_monotonic()) return; timeval delta; if (timeChanged(&delta)) @@ -404,25 +354,6 @@ void QTimerInfoList::repairTimersIfNeeded() #else // !(_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(QT_BOOTSTRAPPED) -void QTimerInfoList::getTime(timeval &t) -{ -#if defined(Q_OS_MAC) - static mach_timebase_info_data_t info = {0,0}; - if (info.denom == 0) - mach_timebase_info(&info); - - uint64_t cpu_time = mach_absolute_time(); - uint64_t nsecs = cpu_time * (info.numer / info.denom); - t.tv_sec = nsecs * 1e-9; - t.tv_usec = nsecs * 1e-3 - (t.tv_sec * 1e6); -#else - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - t.tv_sec = ts.tv_sec; - t.tv_usec = ts.tv_nsec / 1000; -#endif -} - void QTimerInfoList::repairTimersIfNeeded() { } @@ -648,25 +579,7 @@ QEventDispatcherUNIX::~QEventDispatcherUNIX() int QEventDispatcherUNIX::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timeval *timeout) { - Q_D(QEventDispatcherUNIX); - if (timeout && d->timerList.useMonotonicTimers) { - // handle the case where select returns with a timeout, too - // soon. - timeval tvStart = d->timerList.currentTime; - timeval tvCurrent = tvStart; - timeval originalTimeout = *timeout; - - int nsel; - do { - timeval tvRest = originalTimeout + tvStart - tvCurrent; - nsel = ::select(nfds, readfds, writefds, exceptfds, &tvRest); - d->timerList.getTime(tvCurrent); - } while (nsel == 0 && (tvCurrent - tvStart) < originalTimeout); - - return nsel; - } - - return ::select(nfds, readfds, writefds, exceptfds, timeout); + return ::qt_safe_select(nfds, readfds, writefds, exceptfds, timeout); } /*! diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index 28e7f9b..61d94c9 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -141,10 +141,6 @@ class QTimerInfoList : public QList<QTimerInfo*> public: QTimerInfoList(); - const bool useMonotonicTimers; - - void getTime(timeval &t); - timeval currentTime; timeval updateCurrentTime(); |