diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2014-01-23 16:01:25 -0800 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2015-01-23 19:12:53 +0100 |
commit | c8849dd8d587eca7aa59c5c865986f326c1e7c39 (patch) | |
tree | a5003eca7193a3f32dc427ebb241cd8869069b8c /tests/auto/corelib | |
parent | 39482e6e0faebcbf7018f65ff050191ccd5c5823 (diff) |
Use waitid with WNOWAIT in forkfd
The previous implementation required one syscall per child we're waiting
on to see which one exited. That means the algorithm was O(n).
This implementation uses WNOWAIT to find out which child exited and then
goes straight to that one. So it's O(1) on the number of children, but
runs 2 * number_of_children_that_exited + 1 syscalls, assuming there are
no race conditions with other threads. If there are or if a child not
started by forkfd exits, we'll still iterate over each child we're
managing to see which one exited.
It modifies the existing code so that it will do a waitid() with WNOWAIT
to check on the status of the child: if the child has exited, we'll try
to lock the entry so only one thread will do the final wait(). In the
case we read the PID, then the child exited, was reaped by another
thread, the PID got recycled and that child exited again, we'll fail to
lock the ProcessInfo entry so no harm comes. If by an absurd coincidence
this other child was started by forkfd() and its ProcessInfo is exactly
the one we are looking at, then we'll succeed in locking but that's a
benign race: we'll do what the other thread was trying to do and the
other thread will give up.
Future improvements to the algorithm are discussed in the Gerrit change.
Change-Id: Ie74836dbc388cd9b3fa375a41a8d944602a32df1
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests/auto/corelib')
-rw-r--r-- | tests/auto/corelib/io/qprocess/tst_qprocess.cpp | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index 59042f6498..c8ba69c0fb 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -1223,21 +1223,24 @@ void tst_QProcess::processInAThread() void tst_QProcess::processesInMultipleThreads() { for (int i = 0; i < 10; ++i) { - TestThread thread1; - TestThread thread2; - TestThread thread3; - - thread1.start(); - thread2.start(); - thread3.start(); - - QVERIFY(thread2.wait(10000)); - QVERIFY(thread3.wait(10000)); - QVERIFY(thread1.wait(10000)); - - QCOMPARE(thread1.code(), 0); - QCOMPARE(thread2.code(), 0); - QCOMPARE(thread3.code(), 0); + // run from 1 to 10 threads, but run at least some tests + // with more threads than the ideal + int threadCount = i; + if (i > 7) + threadCount = qMax(threadCount, QThread::idealThreadCount() + 2); + + QVector<TestThread *> threads(threadCount); + for (int j = 0; j < threadCount; ++j) + threads[j] = new TestThread; + for (int j = 0; j < threadCount; ++j) + threads[j]->start(); + for (int j = 0; j < threadCount; ++j) { + QVERIFY(threads[j]->wait(10000)); + } + for (int j = 0; j < threadCount; ++j) { + QCOMPARE(threads[j]->code(), 0); + } + qDeleteAll(threads); } } |