From caa22ff8ad9ee85dadf1620a9be24c1d555c1973 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 12 Aug 2012 12:54:11 +0200 Subject: [PATCH] Use nanosleep instead of pthread_cond_timedwait for thread sleeping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's a comment saying nanosleep's availability is questionable, but the information of what systems don't have that is now lost in time. It's quite likely that they were older, Unix systems we no longer support anyway. nanosleep comes from POSIX.1b-1993, which is merged into POSIX.1-2001, so chances are that it's supported almost everywhere where Qt runs (except for Windows anyway). Change-Id: I4fd18f8715c43a42429000f3b3d2c3b7343f94b4 Reviewed-by: Lars Knoll Reviewed-by: João Abecasis --- src/corelib/kernel/qcore_unix_p.h | 1 + src/corelib/thread/qthread_unix.cpp | 48 ++++-------------------- src/corelib/tools/qelapsedtimer_mac.cpp | 13 +++++++ src/corelib/tools/qelapsedtimer_unix.cpp | 14 +++++++ 4 files changed, 36 insertions(+), 40 deletions(-) diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 957c646d80c..24c2eef399d 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 f472dee56e1..f6df15f7a71 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 2aeaaa60f04..0304c682264 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 d7419aea18b..435a797a4df 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) {