Stop trying to discover the system timer resolution on Windows
Let's take the beginning of the description: WaitForSingleObjectEx can be up to 16 milliseconds early. This is proven by the fact that there are tests doing: wait(waitTime); QVERIFY(timer.elapsed() >= waitTime - systemTimersResolution); and failing. Task-number: QTBUG-59337 Change-Id: Iae839f6a131a4f0784bffffd14a9a79523d69d94 Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
parent
2d81968c3b
commit
3a1f4b186d
@ -36,11 +36,6 @@
|
|||||||
#include <qthread.h>
|
#include <qthread.h>
|
||||||
#include <qwaitcondition.h>
|
#include <qwaitcondition.h>
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
#include <private/qsystemlibrary_p.h>
|
|
||||||
#include <cmath>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class tst_QMutex : public QObject
|
class tst_QMutex : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -54,7 +49,6 @@ public:
|
|||||||
Q_ENUM(TimeUnit);
|
Q_ENUM(TimeUnit);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void initTestCase();
|
|
||||||
void convertToMilliseconds_data();
|
void convertToMilliseconds_data();
|
||||||
void convertToMilliseconds();
|
void convertToMilliseconds();
|
||||||
void tryLock_non_recursive();
|
void tryLock_non_recursive();
|
||||||
@ -70,8 +64,6 @@ private slots:
|
|||||||
void tryLockNegative_data();
|
void tryLockNegative_data();
|
||||||
void tryLockNegative();
|
void tryLockNegative();
|
||||||
void moreStress();
|
void moreStress();
|
||||||
private:
|
|
||||||
void initializeSystemTimersResolution();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int iterations = 100;
|
static const int iterations = 100;
|
||||||
@ -81,57 +73,24 @@ QMutex normalMutex, recursiveMutex(QMutex::Recursive);
|
|||||||
QSemaphore testsTurn;
|
QSemaphore testsTurn;
|
||||||
QSemaphore threadsTurn;
|
QSemaphore threadsTurn;
|
||||||
|
|
||||||
enum { waitTime = 100 };
|
|
||||||
uint systemTimersResolution = 1;
|
|
||||||
|
|
||||||
#if QT_HAS_INCLUDE(<chrono>)
|
|
||||||
static Q_CONSTEXPR std::chrono::milliseconds waitTimeAsDuration(waitTime);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Depending on the OS, tryWaits may return early than expected because of the
|
Depending on the OS, tryWaits may return early than expected because of the
|
||||||
resolution of the underlying timer is too coarse. E.g.: on Windows
|
resolution of the underlying timer is too coarse. E.g.: on Windows
|
||||||
WaitForSingleObjectEx does *not* use high resolution multimedia timers, and
|
WaitForSingleObjectEx does *not* use high resolution multimedia timers, and
|
||||||
it's actually very coarse, about 16msec by default.
|
it's actually very coarse, about 16msec by default.
|
||||||
|
|
||||||
Try to find out the timer resolution in here, so that the tryLock tests can
|
|
||||||
actually take into account early wakes.
|
|
||||||
*/
|
*/
|
||||||
void tst_QMutex::initializeSystemTimersResolution()
|
enum {
|
||||||
{
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
// according to MSDN, Windows can default up to this
|
systemTimersResolution = 16,
|
||||||
systemTimersResolution = 16;
|
#else
|
||||||
|
systemTimersResolution = 1,
|
||||||
|
#endif
|
||||||
|
waitTime = 100
|
||||||
|
};
|
||||||
|
|
||||||
// private API. There's no way on Windows to otherwise know the
|
#if QT_HAS_INCLUDE(<chrono>)
|
||||||
// actual resolution of the application's timers (you can only set it)
|
static Q_CONSTEXPR std::chrono::milliseconds waitTimeAsDuration(waitTime);
|
||||||
// cf. https://stackoverflow.com/questions/7685762/windows-7-timing-functions-how-to-use-getsystemtimeadjustment-correctly/11743614#11743614
|
#endif
|
||||||
typedef NTSTATUS (NTAPI *NtQueryTimerResolutionType)(OUT PULONG MinimumResolution,
|
|
||||||
OUT PULONG MaximumResolution,
|
|
||||||
OUT PULONG ActualResolution);
|
|
||||||
|
|
||||||
const NtQueryTimerResolutionType NtQueryTimerResolutionPtr =
|
|
||||||
reinterpret_cast<NtQueryTimerResolutionType>(QSystemLibrary::resolve(QStringLiteral("ntdll"), "NtQueryTimerResolution"));
|
|
||||||
|
|
||||||
if (!NtQueryTimerResolutionPtr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ULONG minimumResolution;
|
|
||||||
ULONG maximumResolution;
|
|
||||||
ULONG actualResolution;
|
|
||||||
|
|
||||||
if (!NtQueryTimerResolutionPtr(&minimumResolution, &maximumResolution, &actualResolution)) {
|
|
||||||
// the result is in 100ns units => adjust to msec
|
|
||||||
const double actualResolutionMsec = actualResolution / 10000.0;
|
|
||||||
systemTimersResolution = static_cast<int>(std::ceil(actualResolutionMsec));
|
|
||||||
}
|
|
||||||
#endif // Q_OS_WIN
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_QMutex::initTestCase()
|
|
||||||
{
|
|
||||||
initializeSystemTimersResolution();
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_QMutex::convertToMilliseconds_data()
|
void tst_QMutex::convertToMilliseconds_data()
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user