summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp75
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h46
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;