assert(threadID >= 0 && threadID < MAX_THREADS);
+ int i;
+ bool allFinished = false;
+
while (true)
{
// Slave threads can exit as soon as AllThreadsShouldExit raises,
// instead of wasting CPU time polling for work.
while ( threadID >= ActiveThreads
|| threads[threadID].state == THREAD_INITIALIZING
- || (!sp && threads[threadID].state == THREAD_AVAILABLE))
+ || threads[threadID].state == THREAD_AVAILABLE)
{
- assert(!sp);
- assert(threadID != 0);
-
- if (AllThreadsShouldExit)
- break;
-
lock_grab(&MPLock);
- // Retest condition under lock protection
- if (!( threadID >= ActiveThreads
- || threads[threadID].state == THREAD_INITIALIZING
- || (!sp && threads[threadID].state == THREAD_AVAILABLE)))
+ // Test with lock held to avoid races with wake_sleeping_thread()
+ for (i = 0; sp && i < ActiveThreads && !sp->slaves[i]; i++) {}
+ allFinished = (i == ActiveThreads);
+
+ // Retest sleep conditions under lock protection
+ if ( AllThreadsShouldExit
+ || allFinished
+ || !( threadID >= ActiveThreads
+ || threads[threadID].state == THREAD_INITIALIZING
+ || threads[threadID].state == THREAD_AVAILABLE))
{
lock_release(&MPLock);
- continue;
+ break;
}
// Put thread to sleep
assert(threads[threadID].state == THREAD_SEARCHING);
threads[threadID].state = THREAD_AVAILABLE;
+
+ // Wake up master thread so to allow it to return from the idle loop in
+ // case we are the last slave of the split point.
+ if (threadID != tsp->master && threads[tsp->master].state == THREAD_AVAILABLE)
+ wake_sleeping_thread(tsp->master);
}
// If this thread is the master of a split point and all slaves have
// finished their work at this split point, return from the idle loop.
- int i = 0;
- for ( ; sp && i < ActiveThreads && !sp->slaves[i]; i++) {}
+ for (i = 0; sp && i < ActiveThreads && !sp->slaves[i]; i++) {}
+ allFinished = (i == ActiveThreads);
- if (i == ActiveThreads)
+ if (allFinished)
{
// Because sp->slaves[] is reset under lock protection,
// be sure sp->lock has been released before to return.
// Initialize the split point object
splitPoint.parent = masterThread.splitPoint;
+ splitPoint.master = master;
splitPoint.stopRequest = false;
splitPoint.ply = ply;
splitPoint.depth = depth;