diff options
Diffstat (limited to 'tests/auto/qmutex/tst_qmutex.cpp')
-rw-r--r-- | tests/auto/qmutex/tst_qmutex.cpp | 111 |
1 files changed, 90 insertions, 21 deletions
diff --git a/tests/auto/qmutex/tst_qmutex.cpp b/tests/auto/qmutex/tst_qmutex.cpp index 5fed6bb44e..7ad6a98a4d 100644 --- a/tests/auto/qmutex/tst_qmutex.cpp +++ b/tests/auto/qmutex/tst_qmutex.cpp @@ -65,6 +65,7 @@ private slots: void stressTest(); void tryLockRace(); void qtbug16115_trylock(); + void moreStress(); }; static const int iterations = 100; @@ -83,6 +84,8 @@ QMutex normalMutex, recursiveMutex(QMutex::Recursive); QSemaphore testsTurn; QSemaphore threadsTurn; +enum { waitTime = 100 }; + void tst_QMutex::tryLock() { // test non-recursive mutex @@ -109,18 +112,18 @@ void tst_QMutex::tryLock() threadsTurn.acquire(); QTime timer; timer.start(); - QVERIFY(!normalMutex.tryLock(1000)); - QVERIFY(timer.elapsed() >= 1000); + QVERIFY(!normalMutex.tryLock(waitTime)); + QVERIFY(timer.elapsed() >= waitTime); testsTurn.release(); threadsTurn.acquire(); timer.start(); - QVERIFY(normalMutex.tryLock(1000)); - QVERIFY(timer.elapsed() <= 1000); + QVERIFY(normalMutex.tryLock(waitTime)); + QVERIFY(timer.elapsed() <= waitTime); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); timer.start(); - QVERIFY(!normalMutex.tryLock(1000)); - QVERIFY(timer.elapsed() >= 1000); + QVERIFY(!normalMutex.tryLock(waitTime)); + QVERIFY(timer.elapsed() >= waitTime); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); normalMutex.unlock(); testsTurn.release(); @@ -132,7 +135,7 @@ void tst_QMutex::tryLock() threadsTurn.acquire(); timer.start(); QVERIFY(normalMutex.tryLock(0)); - QVERIFY(timer.elapsed() < 1000); + QVERIFY(timer.elapsed() < waitTime); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); QVERIFY(!normalMutex.tryLock(0)); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); @@ -158,13 +161,13 @@ void tst_QMutex::tryLock() normalMutex.unlock(); threadsTurn.release(); - // thread can't acquire lock, timeout = 1000 + // thread can't acquire lock, timeout = waitTime testsTurn.acquire(); normalMutex.lock(); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); threadsTurn.release(); - // thread can acquire lock, timeout = 1000 + // thread can acquire lock, timeout = waitTime testsTurn.acquire(); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); normalMutex.unlock(); @@ -215,17 +218,17 @@ void tst_QMutex::tryLock() threadsTurn.acquire(); QTime timer; timer.start(); - QVERIFY(!recursiveMutex.tryLock(1000)); - QVERIFY(timer.elapsed() >= 1000); + QVERIFY(!recursiveMutex.tryLock(waitTime)); + QVERIFY(timer.elapsed() >= waitTime); QVERIFY(!recursiveMutex.tryLock(0)); testsTurn.release(); threadsTurn.acquire(); timer.start(); - QVERIFY(recursiveMutex.tryLock(1000)); - QVERIFY(timer.elapsed() <= 1000); + QVERIFY(recursiveMutex.tryLock(waitTime)); + QVERIFY(timer.elapsed() <= waitTime); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); - QVERIFY(recursiveMutex.tryLock(1000)); + QVERIFY(recursiveMutex.tryLock(waitTime)); QVERIFY(lockCount.testAndSetRelaxed(1, 2)); QVERIFY(lockCount.testAndSetRelaxed(2, 1)); recursiveMutex.unlock(); @@ -241,7 +244,7 @@ void tst_QMutex::tryLock() threadsTurn.acquire(); timer.start(); QVERIFY(recursiveMutex.tryLock(0)); - QVERIFY(timer.elapsed() < 1000); + QVERIFY(timer.elapsed() < waitTime); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); QVERIFY(recursiveMutex.tryLock(0)); QVERIFY(lockCount.testAndSetRelaxed(1, 2)); @@ -274,7 +277,7 @@ void tst_QMutex::tryLock() recursiveMutex.unlock(); threadsTurn.release(); - // thread can't acquire lock, timeout = 1000 + // thread can't acquire lock, timeout = waitTime testsTurn.acquire(); recursiveMutex.lock(); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); @@ -282,7 +285,7 @@ void tst_QMutex::tryLock() QVERIFY(lockCount.testAndSetRelaxed(1, 2)); threadsTurn.release(); - // thread can acquire lock, timeout = 1000 + // thread can acquire lock, timeout = waitTime testsTurn.acquire(); QVERIFY(lockCount.testAndSetRelaxed(2, 1)); recursiveMutex.unlock(); @@ -436,7 +439,8 @@ void tst_QMutex::lock_unlock_locked_tryLock() } } -enum { one_minute = 60 * 1000, threadCount = 10 }; +enum { one_minute = 6 * 1000, //not really one minute, but else it is too long. + threadCount = 10 }; class StressTestThread : public QThread { @@ -497,7 +501,7 @@ public: do { if (mutex.tryLock()) mutex.unlock(); - } while (t.elapsed() < 20000); + } while (t.elapsed() < one_minute/2); } }; QMutex TryLockRaceThread::mutex; @@ -534,7 +538,7 @@ void tst_QMutex::qtbug16115_trylock() TrylockThread(QMutex &mut) : mut(mut) {} QMutex &mut; void run() { - for (int i = 0; i < 1000000; ++i) { + for (int i = 0; i < 100000; ++i) { if (mut.tryLock(0)) { if ((++qtbug16115_trylock_counter) != 1) ++qtbug16115_failure_count; @@ -553,7 +557,7 @@ void tst_QMutex::qtbug16115_trylock() t2.start(); t3.start(); - for (int i = 0; i < 1000000; ++i) { + for (int i = 0; i < 100000; ++i) { mut.lock(); if ((++qtbug16115_trylock_counter) != 1) ++qtbug16115_failure_count; @@ -567,5 +571,70 @@ void tst_QMutex::qtbug16115_trylock() QCOMPARE(qtbug16115_failure_count, 0); } + +class MoreStressTestThread : public QThread +{ + QTime t; +public: + static QAtomicInt lockCount; + static QAtomicInt sentinel[threadCount]; + static QMutex mutex[threadCount]; + static QAtomicInt errorCount; + void start() + { + t.start(); + QThread::start(); + } + void run() + { + quint64 i = 0; + while (t.elapsed() < one_minute) { + i++; + uint nb = (i * 9 + lockCount * 13) % threadCount; + QMutexLocker locker(&mutex[nb]); + if (sentinel[nb]) errorCount.ref(); + if (sentinel[nb].fetchAndAddRelaxed(5)) errorCount.ref(); + if (!sentinel[nb].testAndSetRelaxed(5, 0)) errorCount.ref(); + if (sentinel[nb]) errorCount.ref(); + lockCount.ref(); + nb = (nb * 17 + i * 5 + lockCount * 3) % threadCount; + if (mutex[nb].tryLock()) { + if (sentinel[nb]) errorCount.ref(); + if (sentinel[nb].fetchAndAddRelaxed(16)) errorCount.ref(); + if (!sentinel[nb].testAndSetRelaxed(16, 0)) errorCount.ref(); + if (sentinel[nb]) errorCount.ref(); + lockCount.ref(); + mutex[nb].unlock(); + } + nb = (nb * 15 + i * 47 + lockCount * 31) % threadCount; + if (mutex[nb].tryLock(2)) { + if (sentinel[nb]) errorCount.ref(); + if (sentinel[nb].fetchAndAddRelaxed(53)) errorCount.ref(); + if (!sentinel[nb].testAndSetRelaxed(53, 0)) errorCount.ref(); + if (sentinel[nb]) errorCount.ref(); + lockCount.ref(); + mutex[nb].unlock(); + } + } + } +}; +QMutex MoreStressTestThread::mutex[threadCount]; +QAtomicInt MoreStressTestThread::lockCount; +QAtomicInt MoreStressTestThread::sentinel[threadCount]; +QAtomicInt MoreStressTestThread::errorCount = 0; + +void tst_QMutex::moreStress() +{ + MoreStressTestThread threads[threadCount]; + for (int i = 0; i < threadCount; ++i) + threads[i].start(); + QVERIFY(threads[0].wait(one_minute + 10000)); + for (int i = 1; i < threadCount; ++i) + QVERIFY(threads[i].wait(10000)); + qDebug("locked %d times", int(MoreStressTestThread::lockCount)); + QCOMPARE(int(MoreStressTestThread::errorCount), 0); +} + + QTEST_MAIN(tst_QMutex) #include "tst_qmutex.moc" |