-
- // Pick the next available split point object from the split point stack
- SplitPoint& splitPoint = masterThread.splitPoints[masterThread.activeSplitPoints++];
-
- // Initialize the split point object
- splitPoint.parent = masterThread.splitPoint;
- splitPoint.master = master;
- splitPoint.betaCutoff = false;
- splitPoint.ply = ply;
- splitPoint.depth = depth;
- splitPoint.threatMove = threatMove;
- splitPoint.mateThreat = mateThreat;
- splitPoint.alpha = *alpha;
- splitPoint.beta = beta;
- splitPoint.pvNode = pvNode;
- splitPoint.bestValue = *bestValue;
- splitPoint.mp = mp;
- splitPoint.moveCount = moveCount;
- splitPoint.pos = &pos;
- splitPoint.nodes = 0;
- splitPoint.parentSstack = ss;
- for (i = 0; i < activeThreads; i++)
- splitPoint.slaves[i] = 0;
-
- masterThread.splitPoint = &splitPoint;
-
- // If we are here it means we are not available
- assert(masterThread.state != THREAD_AVAILABLE);
-
- int workersCnt = 1; // At least the master is included
-
- // Allocate available threads setting state to THREAD_BOOKED
- for (i = 0; !Fake && i < activeThreads && workersCnt < maxThreadsPerSplitPoint; i++)
- if (thread_is_available(i, master))
- {
- threads[i].state = THREAD_BOOKED;
- threads[i].splitPoint = &splitPoint;
- splitPoint.slaves[i] = 1;
- workersCnt++;
- }
-
- assert(Fake || workersCnt > 1);
-
- // We can release the lock because slave threads are already booked and master is not available
- lock_release(&mpLock);
-
- // Tell the threads that they have work to do. This will make them leave
- // their idle loop. But before copy search stack tail for each thread.
- for (i = 0; i < activeThreads; i++)
- if (i == master || splitPoint.slaves[i])
- {
- memcpy(splitPoint.sstack[i], ss - 1, 4 * sizeof(SearchStack));
-
- assert(i == master || threads[i].state == THREAD_BOOKED);
-
- threads[i].state = THREAD_WORKISWAITING; // This makes the slave to exit from idle_loop()
-
- if (useSleepingThreads && i != master)
- wake_sleeping_thread(i);
- }
-
- // Everything is set up. The master thread enters the idle loop, from
- // which it will instantly launch a search, because its state is
- // THREAD_WORKISWAITING. We send the split point as a second parameter to the
- // idle loop, which means that the main thread will return from the idle
- // loop when all threads have finished their work at this split point.
- idle_loop(master, &splitPoint);
-
- // We have returned from the idle loop, which means that all threads are
- // finished. Update alpha and bestValue, and return.
- lock_grab(&mpLock);
-
- *alpha = splitPoint.alpha;
- *bestValue = splitPoint.bestValue;
- masterThread.activeSplitPoints--;
- masterThread.splitPoint = splitPoint.parent;
- pos.set_nodes_searched(pos.nodes_searched() + splitPoint.nodes);
-
- lock_release(&mpLock);
- }
-
-
- // wake_sleeping_thread() wakes up the thread with the given threadID
- // when it is time to start a new search.
-
- void ThreadsManager::wake_sleeping_thread(int threadID) {
-
- lock_grab(&sleepLock[threadID]);
- cond_signal(&sleepCond[threadID]);
- lock_release(&sleepLock[threadID]);