diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 957c646d80..24c2eef399 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -312,6 +312,7 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options) // in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp timeval qt_gettime() Q_DECL_NOTHROW; +void qt_nanosleep(timespec amount); 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/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index f472dee56e..f6df15f7a7 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -454,59 +454,27 @@ void QThread::yieldCurrentThread() sched_yield(); } -/* - \internal - helper function to do thread sleeps, since usleep()/nanosleep() - aren't reliable enough (in terms of behavior and availability) -*/ -static void thread_sleep(struct timespec *ti) +static timespec makeTimespec(time_t secs, long nsecs) { - pthread_mutex_t mtx; - pthread_cond_t cnd; - - pthread_mutex_init(&mtx, 0); - pthread_cond_init(&cnd, 0); - - pthread_mutex_lock(&mtx); - (void) pthread_cond_timedwait(&cnd, &mtx, ti); - pthread_mutex_unlock(&mtx); - - pthread_cond_destroy(&cnd); - pthread_mutex_destroy(&mtx); + struct timespec ts; + ts.tv_sec = secs; + ts.tv_nsec = nsecs; + return ts; } void QThread::sleep(unsigned long secs) { - struct timeval tv; - gettimeofday(&tv, 0); - struct timespec ti; - ti.tv_sec = tv.tv_sec + secs; - ti.tv_nsec = (tv.tv_usec * 1000); - thread_sleep(&ti); + qt_nanosleep(makeTimespec(secs, 0)); } void QThread::msleep(unsigned long msecs) { - struct timeval tv; - gettimeofday(&tv, 0); - struct timespec ti; - - ti.tv_nsec = (tv.tv_usec + (msecs % 1000) * 1000) * 1000; - ti.tv_sec = tv.tv_sec + (msecs / 1000) + (ti.tv_nsec / 1000000000); - ti.tv_nsec %= 1000000000; - thread_sleep(&ti); + qt_nanosleep(makeTimespec(msecs / 1000, msecs % 1000 * 1000 * 1000)); } void QThread::usleep(unsigned long usecs) { - struct timeval tv; - gettimeofday(&tv, 0); - struct timespec ti; - - ti.tv_nsec = (tv.tv_usec + (usecs % 1000000)) * 1000; - ti.tv_sec = tv.tv_sec + (usecs / 1000000) + (ti.tv_nsec / 1000000000); - ti.tv_nsec %= 1000000000; - thread_sleep(&ti); + qt_nanosleep(makeTimespec(usecs / 1000 / 1000, usecs % (1000*1000) * 1000)); } #ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING diff --git a/src/corelib/tools/qelapsedtimer_mac.cpp b/src/corelib/tools/qelapsedtimer_mac.cpp index 2aeaaa60f0..0304c68226 100644 --- a/src/corelib/tools/qelapsedtimer_mac.cpp +++ b/src/corelib/tools/qelapsedtimer_mac.cpp @@ -39,8 +39,12 @@ ** ****************************************************************************/ +// ask for the latest POSIX, just in case +#define _POSIX_C_SOURCE 200809L + #include "qelapsedtimer.h" #include +#include #include #include @@ -83,6 +87,15 @@ timeval qt_gettime() Q_DECL_NOTHROW return tv; } +void qt_nanosleep(timespec amount) +{ + // Mac doesn't have clock_nanosleep, but it does have nanosleep. + // nanosleep is POSIX.1-1993 + + int r; + EINTR_LOOP(r, nanosleep(&amount, &amount)); +} + void QElapsedTimer::start() Q_DECL_NOTHROW { t1 = mach_absolute_time(); diff --git a/src/corelib/tools/qelapsedtimer_unix.cpp b/src/corelib/tools/qelapsedtimer_unix.cpp index d7419aea18..435a797a4d 100644 --- a/src/corelib/tools/qelapsedtimer_unix.cpp +++ b/src/corelib/tools/qelapsedtimer_unix.cpp @@ -144,6 +144,20 @@ timeval qt_gettime() Q_DECL_NOTHROW return tv; } +void qt_nanosleep(timespec amount) +{ + // We'd like to use clock_nanosleep. + // + // But clock_nanosleep is from POSIX.1-2001 and both are *not* + // affected by clock changes when using relative sleeps, even for + // CLOCK_REALTIME. + // + // nanosleep is POSIX.1-1993 + + int r; + EINTR_LOOP(r, nanosleep(&amount, &amount)); +} + static qint64 elapsedAndRestart(qint64 sec, qint64 frac, qint64 *nowsec, qint64 *nowfrac) {