summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorOlivier Goffart <olivier.goffart@nokia.com>2011-07-02 15:13:12 +0200
committerQt by Nokia <qt-info@nokia.com>2011-07-29 10:32:07 +0200
commit86a237929e2b67ce333b635b760e78c628effb60 (patch)
tree290ad9a01a9bcf19ef02f4455728823d136b7193 /tests
parent487583459ea7958f24cd579888a662bcce26caf3 (diff)
QMutex is now just a pointer
And added a POD QBasicMutex. (QBasicMutex* can safely be static_cast'ed to QMutex*) The d pointer is not anymore always a QMutexPrivate. If d == 0x0: the mutex is unlocked If d == 0x1: the mutex is locked, uncontended On linux: if d == 0x3: the mutex is locked contended, waiting on a futex If d is a pointer, it is a recursive mutex. On non-linux platforms: When a thread tries to lock a mutex for which d == 0x1, it will try to assing it a QMutexPrivated (allocated from a freelist) in order to wait for it. Change-Id: Ie1431cd9402a576fdd9a693cfd747166eebf5622 Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com> Reviewed-on: http://codereview.qt.nokia.com/2116 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Olivier Goffart <olivier.goffart@nokia.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/qmutex/tst_qmutex.cpp111
-rw-r--r--tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp11
2 files changed, 90 insertions, 32 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"
diff --git a/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp b/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp
index 05a15750c1..05e184d0c2 100644
--- a/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp
+++ b/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp
@@ -151,7 +151,6 @@ void tst_QMutex::noThread_data()
QTest::addColumn<int>("t");
QTest::newRow("noLock") << 1;
- QTest::newRow("QMutexInline") << 2;
QTest::newRow("QMutex") << 3;
QTest::newRow("QMutexLocker") << 4;
}
@@ -172,16 +171,6 @@ void tst_QMutex::noThread()
}
}
break;
- case 2:
- QBENCHMARK {
- count = 0;
- for (int i = 0; i < N; i++) {
- mtx.lockInline();
- count++;
- mtx.unlockInline();
- }
- }
- break;
case 3:
QBENCHMARK {
count = 0;