diff options
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_unix.cpp | 75 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_unix_p.h | 46 |
2 files changed, 79 insertions, 42 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index fac8a28..2139545 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -67,6 +67,25 @@ 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 *****************************************************************************/ @@ -262,18 +281,11 @@ int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, */ QTimerInfoList::QTimerInfoList() + : useMonotonicTimers(supportsMonotonicClock()) { -#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) - useMonotonicTimers = false; - -# if (_POSIX_MONOTONIC_CLOCK == 0) - // detect if the system support monotonic timers - long x = sysconf(_SC_MONOTONIC_CLOCK); - useMonotonicTimers = x != -1; -# endif - getTime(currentTime); +#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) if (!useMonotonicTimers) { // not using monotonic timers, initialize the timeChanged() machinery previousTime = currentTime; @@ -290,9 +302,6 @@ QTimerInfoList::QTimerInfoList() ticksPerSecond = 0; msPerTick = 0; } -#else - // using monotonic timers unconditionally - getTime(currentTime); #endif firstTimerInfo = currentTimerInfo = 0; @@ -306,6 +315,20 @@ timeval QTimerInfoList::updateCurrentTime() #if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC)) || defined(QT_BOOTSTRAPPED) +template <> +timeval qAbs(const timeval &t) +{ + timeval tmp = t; + if (tmp.tv_sec < 0) { + tmp.tv_sec = -tmp.tv_sec - 1; + tmp.tv_usec -= 1000000; + } + if (tmp.tv_sec == 0 && tmp.tv_usec < 0) { + tmp.tv_usec = -tmp.tv_usec; + } + return normalizedTimeval(tmp); +} + /* Returns true if the real time clock has changed by more than 10% relative to the processor time since the last time this function was @@ -318,23 +341,27 @@ bool QTimerInfoList::timeChanged(timeval *delta) tms unused; clock_t currentTicks = times(&unused); - int elapsedTicks = currentTicks - previousTicks; + clock_t elapsedTicks = currentTicks - previousTicks; timeval elapsedTime = currentTime - previousTime; - int elapsedMsecTicks = (elapsedTicks * 1000) / ticksPerSecond; - int deltaMsecs = (elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000) - - elapsedMsecTicks; - if (delta) { - delta->tv_sec = deltaMsecs / 1000; - delta->tv_usec = (deltaMsecs % 1000) * 1000; - } + timeval elapsedTimeTicks; + elapsedTimeTicks.tv_sec = elapsedTicks / ticksPerSecond; + elapsedTimeTicks.tv_usec = (((elapsedTicks * 1000) / ticksPerSecond) % 1000) * 1000; + + timeval dummy; + if (!delta) + delta = &dummy; + *delta = elapsedTime - elapsedTimeTicks; + previousTicks = currentTicks; previousTime = currentTime; // If tick drift is more than 10% off compared to realtime, we assume that the clock has // been set. Of course, we have to allow for the tick granularity as well. - - return (qAbs(deltaMsecs) - msPerTick) * 10 > elapsedMsecTicks; + timeval tickGranularity; + tickGranularity.tv_sec = 0; + tickGranularity.tv_usec = msPerTick * 1000; + return elapsedTimeTicks < ((qAbs(*delta) - tickGranularity) * 10); } void QTimerInfoList::getTime(timeval &t) @@ -424,7 +451,7 @@ void QTimerInfoList::timerRepair(const timeval &diff) // repair all timers for (int i = 0; i < size(); ++i) { register QTimerInfo *t = at(i); - t->timeout = t->timeout - diff; + t->timeout = t->timeout + diff; } } @@ -622,7 +649,7 @@ int QEventDispatcherUNIX::select(int nfds, fd_set *readfds, fd_set *writefds, fd timeval *timeout) { Q_D(QEventDispatcherUNIX); - if (timeout) { + if (timeout && d->timerList.useMonotonicTimers) { // handle the case where select returns with a timeout, too // soon. timeval tvStart = d->timerList.currentTime; diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index ebba21b..28e7f9b 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -71,6 +71,18 @@ QT_BEGIN_NAMESPACE #endif // Internal operator functions for timevals +inline timeval &normalizedTimeval(timeval &t) +{ + while (t.tv_usec > 1000000l) { + ++t.tv_sec; + t.tv_usec -= 1000000l; + } + while (t.tv_usec < 0l) { + --t.tv_sec; + t.tv_usec += 1000000l; + } + return t; +} inline bool operator<(const timeval &t1, const timeval &t2) { return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec); } inline bool operator==(const timeval &t1, const timeval &t2) @@ -78,31 +90,29 @@ inline bool operator==(const timeval &t1, const timeval &t2) inline timeval &operator+=(timeval &t1, const timeval &t2) { t1.tv_sec += t2.tv_sec; - if ((t1.tv_usec += t2.tv_usec) >= 1000000l) { - ++t1.tv_sec; - t1.tv_usec -= 1000000l; - } - return t1; + t1.tv_usec += t2.tv_usec; + return normalizedTimeval(t1); } inline timeval operator+(const timeval &t1, const timeval &t2) { timeval tmp; tmp.tv_sec = t1.tv_sec + t2.tv_sec; - if ((tmp.tv_usec = t1.tv_usec + t2.tv_usec) >= 1000000l) { - ++tmp.tv_sec; - tmp.tv_usec -= 1000000l; - } - return tmp; + tmp.tv_usec = t1.tv_usec + t2.tv_usec; + return normalizedTimeval(tmp); } inline timeval operator-(const timeval &t1, const timeval &t2) { timeval tmp; - tmp.tv_sec = t1.tv_sec - t2.tv_sec; - if ((tmp.tv_usec = t1.tv_usec - t2.tv_usec) < 0l) { - --tmp.tv_sec; - tmp.tv_usec += 1000000l; - } - return tmp; + tmp.tv_sec = t1.tv_sec - (t2.tv_sec - 1); + tmp.tv_usec = t1.tv_usec - (t2.tv_usec + 1000000); + return normalizedTimeval(tmp); +} +inline timeval operator*(const timeval &t1, int mul) +{ + timeval tmp; + tmp.tv_sec = t1.tv_sec * mul; + tmp.tv_usec = t1.tv_usec * mul; + return normalizedTimeval(tmp); } // internal timer info @@ -117,8 +127,6 @@ struct QTimerInfo { class QTimerInfoList : public QList<QTimerInfo*> { #if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC)) || defined(QT_BOOTSTRAPPED) - bool useMonotonicTimers; - timeval previousTime; clock_t previousTicks; int ticksPerSecond; @@ -133,6 +141,8 @@ class QTimerInfoList : public QList<QTimerInfo*> public: QTimerInfoList(); + const bool useMonotonicTimers; + void getTime(timeval &t); timeval currentTime; |