summaryrefslogtreecommitdiffstats
path: root/tests/auto/qmutex/tst_qmutex.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qmutex/tst_qmutex.cpp')
-rw-r--r--tests/auto/qmutex/tst_qmutex.cpp111
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"