diff options
Diffstat (limited to 'src/corelib/kernel/qcore_unix.cpp')
-rw-r--r-- | src/corelib/kernel/qcore_unix.cpp | 84 |
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 |