summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAhmad Samir <a.samirh78@gmail.com>2022-10-31 12:50:39 +0200
committerAhmad Samir <a.samirh78@gmail.com>2023-06-09 17:45:14 +0300
commit3e7d68a6f429b7cbac4e0ae41c7ad7d4747fb2c2 (patch)
treef889b256f5c878dae4f5e70a9272c635fceb2f6e
parent71c9b9f05b9e3d0d655db33e75207a90509849e1 (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.h18
-rw-r--r--src/corelib/thread/qmutex.cpp19
-rw-r--r--src/corelib/thread/qsemaphore.cpp9
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;
}
}