diff options
author | Ahmad Samir <a.samirh78@gmail.com> | 2022-10-31 12:50:39 +0200 |
---|---|---|
committer | Ahmad Samir <a.samirh78@gmail.com> | 2023-06-09 17:45:14 +0300 |
commit | 3e7d68a6f429b7cbac4e0ae41c7ad7d4747fb2c2 (patch) | |
tree | f889b256f5c878dae4f5e70a9272c635fceb2f6e | |
parent | 71c9b9f05b9e3d0d655db33e75207a90509849e1 (diff) |
QtLinuxFutex, QBasicMutex, QSemaphore: use chrono for time arithmetic
Done-With: Thiago Macieira <thiago.macieira@intel.com>
Change-Id: I7c696d58ee596254f91bcd131fe884b6e6ef0852
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/thread/qfutex_p.h | 18 | ||||
-rw-r--r-- | src/corelib/thread/qmutex.cpp | 19 | ||||
-rw-r--r-- | src/corelib/thread/qsemaphore.cpp | 9 |
3 files changed, 26 insertions, 20 deletions
diff --git a/src/corelib/thread/qfutex_p.h b/src/corelib/thread/qfutex_p.h index 48f03f5ed0..2037c8ee23 100644 --- a/src/corelib/thread/qfutex_p.h +++ b/src/corelib/thread/qfutex_p.h @@ -18,12 +18,14 @@ #include <private/qglobal_p.h> #include <QtCore/qtsan_impl.h> +#include <chrono> + QT_BEGIN_NAMESPACE namespace QtDummyFutex { constexpr inline bool futexAvailable() { return false; } template <typename Atomic> - inline bool futexWait(Atomic &, typename Atomic::Type, int = 0) + inline bool futexWait(Atomic &, typename Atomic::Type, std::chrono::nanoseconds = {}) { Q_UNREACHABLE_RETURN(false); } template <typename Atomic> inline void futexWakeOne(Atomic &) { Q_UNREACHABLE(); } @@ -34,6 +36,7 @@ namespace QtDummyFutex { QT_END_NAMESPACE #if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE) +# include <private/qcore_unix_p.h> // use Linux mutexes everywhere except for LSB builds # include <sys/syscall.h> # include <errno.h> @@ -83,11 +86,9 @@ namespace QtLinuxFutex { _q_futex(addr(&futex), FUTEX_WAIT, qintptr(expectedValue)); } template <typename Atomic> - inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, qint64 nstimeout) + inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, std::chrono::nanoseconds timeout) { - struct timespec ts; - ts.tv_sec = nstimeout / 1000 / 1000 / 1000; - ts.tv_nsec = nstimeout % (1000 * 1000 * 1000); + struct timespec ts= durationToTimespec(timeout); int r = _q_futex(addr(&futex), FUTEX_WAIT, qintptr(expectedValue), quintptr(&ts)); return r == 0 || errno != ETIMEDOUT; } @@ -124,9 +125,12 @@ inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue) QtTsan::futexAcquire(&futex); } template <typename Atomic> -inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, qint64 nstimeout) +inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, std::chrono::nanoseconds timeout) { - BOOL r = WaitOnAddress(&futex, &expectedValue, sizeof(expectedValue), DWORD(nstimeout / 1000 / 1000)); + using namespace std::chrono; + // Using ceil so that any non-zero timeout doesn't get trunated to 0ms + auto msecs = ceil<milliseconds>(timeout); + BOOL r = WaitOnAddress(&futex, &expectedValue, sizeof(expectedValue), DWORD(msecs.count())); return r || GetLastError() != ERROR_TIMEOUT; } template <typename Atomic> inline void futexWakeAll(Atomic &futex) diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index b794d79e23..7058e890e0 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -673,12 +673,13 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT */ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXCEPT { - qint64 remainingTime = deadlineTimer.remainingTimeNSecs(); - if (remainingTime == 0) + using namespace std::chrono; + nanoseconds remainingTime = deadlineTimer.remainingTimeAsDuration(); + if (remainingTime == 0ns) return false; if (futexAvailable()) { - if (Q_UNLIKELY(remainingTime < 0)) { // deadlineTimer.isForever() + if (Q_UNLIKELY(deadlineTimer.isForever())) { lockInternal(); return true; } @@ -689,7 +690,7 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr) return true; - Q_FOREVER { + for (;;) { if (!futexWait(d_ptr, dummyFutexValue(), remainingTime)) return false; @@ -700,8 +701,8 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC return true; // calculate the remaining time - remainingTime = deadlineTimer.remainingTimeNSecs(); - if (remainingTime <= 0) + remainingTime = deadlineTimer.remainingTimeAsDuration(); + if (remainingTime == 0ns) return false; } } @@ -713,7 +714,7 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC continue; if (copy == dummyLocked()) { - if (remainingTime == 0) + if (remainingTime == 0ns) return false; // The mutex is locked but does not have a QMutexPrivate yet. // we need to allocate a QMutexPrivate @@ -728,7 +729,7 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC } QMutexPrivate *d = static_cast<QMutexPrivate *>(copy); - if (remainingTime == 0 && !d->possiblyUnlocked.loadRelaxed()) + if (remainingTime == 0ns && !d->possiblyUnlocked.loadRelaxed()) return false; // At this point we have a pointer to a QMutexPrivate. But the other thread @@ -790,7 +791,7 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC Q_ASSERT(d == d_ptr.loadRelaxed()); return true; } else { - Q_ASSERT(remainingTime >= 0); + Q_ASSERT(remainingTime >= 0ns); // timed out d->derefWaiters(1); //There may be a race in which the mutex is unlocked right after we timed out, diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp index a7b423e4e7..95893d731e 100644 --- a/src/corelib/thread/qsemaphore.cpp +++ b/src/corelib/thread/qsemaphore.cpp @@ -148,7 +148,8 @@ template <bool IsTimed> bool futexSemaphoreTryAcquire_loop(QBasicAtomicInteger<quintptr> &u, quintptr curValue, quintptr nn, QDeadlineTimer timer) { - qint64 remainingTime = IsTimed ? timer.remainingTimeNSecs() : -1; + using namespace std::chrono; + nanoseconds remainingTime = IsTimed ? timer.remainingTimeAsDuration() : -1ns; int n = int(unsigned(nn)); // we're called after one testAndSet, so start by waiting first @@ -165,7 +166,7 @@ futexSemaphoreTryAcquire_loop(QBasicAtomicInteger<quintptr> &u, quintptr curValu } } - if (IsTimed && remainingTime > 0) { + if (IsTimed && remainingTime > 0ns) { bool timedout = !futexWait(*ptr, curValue, remainingTime); if (timedout) return false; @@ -175,7 +176,7 @@ futexSemaphoreTryAcquire_loop(QBasicAtomicInteger<quintptr> &u, quintptr curValu curValue = u.loadAcquire(); if (IsTimed) - remainingTime = timer.remainingTimeNSecs(); + remainingTime = timer.remainingTimeAsDuration(); // try to acquire while (futexAvailCounter(curValue) >= n) { @@ -185,7 +186,7 @@ futexSemaphoreTryAcquire_loop(QBasicAtomicInteger<quintptr> &u, quintptr curValu } // not enough tokens available, put us to wait - if (remainingTime == 0) + if (IsTimed && remainingTime == 0ns) return false; } } |