- // init_thread() is the function which is called when a new thread is
- // launched. It simply calls the idle_loop() function with the supplied
- // threadID. There are two versions of this function; one for POSIX
- // threads and one for Windows threads.
-
-#if !defined(_MSC_VER)
-
- void* init_thread(void* threadID) {
-
- ThreadsMgr.idle_loop(*(int*)threadID, NULL);
- return NULL;
- }
-
-#else
-
- DWORD WINAPI init_thread(LPVOID threadID) {
-
- ThreadsMgr.idle_loop(*(int*)threadID, NULL);
- return 0;
- }
-
-#endif
-
-
- /// The ThreadsManager class
-
-
- // read_uci_options() updates number of active threads and other internal
- // parameters according to the UCI options values. It is called before
- // to start a new search.
-
- void ThreadsManager::read_uci_options() {
-
- maxThreadsPerSplitPoint = Options["Maximum Number of Threads per Split Point"].value<int>();
- minimumSplitDepth = Options["Minimum Split Depth"].value<int>() * ONE_PLY;
- useSleepingThreads = Options["Use Sleeping Threads"].value<bool>();
- activeThreads = Options["Threads"].value<int>();
- }
-
-
- // idle_loop() is where the threads are parked when they have no work to do.
- // The parameter 'sp', if non-NULL, is a pointer to an active SplitPoint
- // object for which the current thread is the master.
-
- void ThreadsManager::idle_loop(int threadID, SplitPoint* sp) {
-
- assert(threadID >= 0 && threadID < MAX_THREADS);
-
- int i;
- bool allFinished;
-
- while (true)
- {
- // Slave threads can exit as soon as AllThreadsShouldExit raises,
- // master should exit as last one.
- if (allThreadsShouldExit)
- {
- assert(!sp);
- threads[threadID].state = THREAD_TERMINATED;
- return;
- }
-
- // If we are not thinking, wait for a condition to be signaled
- // instead of wasting CPU time polling for work.
- while ( threadID >= activeThreads
- || threads[threadID].state == THREAD_INITIALIZING
- || (useSleepingThreads && threads[threadID].state == THREAD_AVAILABLE))
- {
- assert(!sp || useSleepingThreads);
- assert(threadID != 0 || useSleepingThreads);
-
- if (threads[threadID].state == THREAD_INITIALIZING)
- threads[threadID].state = THREAD_AVAILABLE;
-
- // Grab the lock to avoid races with Thread::wake_up()
- lock_grab(&threads[threadID].sleepLock);
-
- // If we are master and all slaves have finished do not go to sleep
- for (i = 0; sp && i < activeThreads && !sp->slaves[i]; i++) {}
- allFinished = (i == activeThreads);
-
- if (allFinished || allThreadsShouldExit)
- {
- lock_release(&threads[threadID].sleepLock);
- break;
- }
-
- // Do sleep here after retesting sleep conditions
- if (threadID >= activeThreads || threads[threadID].state == THREAD_AVAILABLE)
- cond_wait(&threads[threadID].sleepCond, &threads[threadID].sleepLock);
-
- lock_release(&threads[threadID].sleepLock);
- }
-
- // If this thread has been assigned work, launch a search
- if (threads[threadID].state == THREAD_WORKISWAITING)
- {
- assert(!allThreadsShouldExit);
-
- threads[threadID].state = THREAD_SEARCHING;
-
- // Copy split point position and search stack and call search()
- // with SplitPoint template parameter set to true.
- SearchStack ss[PLY_MAX_PLUS_2];
- SplitPoint* tsp = threads[threadID].splitPoint;
- Position pos(*tsp->pos, threadID);
-
- memcpy(ss, tsp->ss - 1, 4 * sizeof(SearchStack));
- (ss+1)->sp = tsp;
-
- if (tsp->pvNode)
- search<PV, true, false>(pos, ss+1, tsp->alpha, tsp->beta, tsp->depth);
- else
- search<NonPV, true, false>(pos, ss+1, tsp->alpha, tsp->beta, tsp->depth);
-
- 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 ( useSleepingThreads
- && threadID != tsp->master
- && threads[tsp->master].state == THREAD_AVAILABLE)
- threads[tsp->master].wake_up();
- }
-
- // 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.
- for (i = 0; sp && i < activeThreads && !sp->slaves[i]; i++) {}
- allFinished = (i == activeThreads);
-
- if (allFinished)
- {
- // Because sp->slaves[] is reset under lock protection,
- // be sure sp->lock has been released before to return.
- lock_grab(&(sp->lock));
- lock_release(&(sp->lock));
-
- // In helpful master concept a master can help only a sub-tree, and
- // because here is all finished is not possible master is booked.
- assert(threads[threadID].state == THREAD_AVAILABLE);
-
- threads[threadID].state = THREAD_SEARCHING;
- return;
- }
- }
- }
-
-
- // init_threads() is called during startup. Initializes locks and condition
- // variables and launches all threads sending them immediately to sleep.
-
- void ThreadsManager::init_threads() {