summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qcore_unix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qcore_unix.cpp')
-rw-r--r--src/corelib/kernel/qcore_unix.cpp84
1 files changed, 63 insertions, 21 deletions
diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp
index c5b0fc760..b57d385bc 100644
--- a/src/corelib/kernel/qcore_unix.cpp
+++ b/src/corelib/kernel/qcore_unix.cpp
@@ -41,11 +41,18 @@
#include "qcore_unix_p.h"
-#include <sys/select.h>
-#include <sys/time.h>
+#ifndef Q_OS_VXWORKS
+# include <sys/select.h>
+# include <sys/time.h>
+#else
+# include <selectLib.h>
+#endif
+
#include <stdlib.h>
-#include "qeventdispatcher_unix_p.h" // for the timeval operators
+#ifdef Q_OS_MAC
+#include <mach/mach_time.h>
+#endif
#if !defined(QT_NO_CLOCK_MONOTONIC)
# if defined(QT_BOOTSTRAPPED)
@@ -55,37 +62,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 / 1000000000ull;
+ tv.tv_usec = (nsecs / 1000) - (tv.tv_sec * 1000000);
+ 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 +142,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