-#else
-
- DWORD WINAPI init_thread(LPVOID threadID) {
-
- ThreadsMgr.idle_loop(*(int*)threadID, NULL);
- return 0;
- }
-
-#endif
-
-
- /// The ThreadsManager class
-
-
- // 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 = false;
-
- 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
- || (threads[threadID].state == THREAD_AVAILABLE && (!sp || UseSleepingMaster)))
- {
- lock_grab(&MPLock);
-
- // 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 && (!sp || UseSleepingMaster))))
- {
- lock_release(&MPLock);
- break;
- }
-
- // Put thread to sleep
- threads[threadID].state = THREAD_AVAILABLE;
- cond_wait(&WaitCond[threadID], &MPLock);
- lock_release(&MPLock);
- }
-
- // If this thread has been assigned work, launch a search
- if (threads[threadID].state == THREAD_WORKISWAITING)
- {
- assert(!AllThreadsShouldExit);
-
- threads[threadID].state = THREAD_SEARCHING;
-
- // Here we call search() with SplitPoint template parameter set to true
- SplitPoint* tsp = threads[threadID].splitPoint;
- Position pos(*tsp->pos, threadID);
- SearchStack* ss = tsp->sstack[threadID] + 1;
- ss->sp = tsp;
-
- if (tsp->pvNode)
- search<PV, true>(pos, ss, tsp->alpha, tsp->beta, tsp->depth, tsp->ply);
- else {
- search<NonPV, true>(pos, ss, tsp->alpha, tsp->beta, tsp->depth, tsp->ply);
- }
- 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 (UseSleepingMaster && 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.
- 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. It launches all helper threads,
- // and initializes the split point stack and the global locks and condition
- // objects.
-
- void ThreadsManager::init_threads() {
-
- int i, arg[MAX_THREADS];
- bool ok;
-
- // Initialize global locks
- lock_init(&MPLock);
-
- for (i = 0; i < MAX_THREADS; i++)
- cond_init(&WaitCond[i]);
-
- // Initialize splitPoints[] locks
- for (i = 0; i < MAX_THREADS; i++)
- for (int j = 0; j < MAX_ACTIVE_SPLIT_POINTS; j++)
- lock_init(&(threads[i].splitPoints[j].lock));
-
- // Will be set just before program exits to properly end the threads
- AllThreadsShouldExit = false;
-
- // Threads will be put all threads to sleep as soon as created
- ActiveThreads = 1;
-
- // All threads except the main thread should be initialized to THREAD_INITIALIZING
- threads[0].state = THREAD_SEARCHING;
- for (i = 1; i < MAX_THREADS; i++)
- threads[i].state = THREAD_INITIALIZING;
-
- // Launch the helper threads
- for (i = 1; i < MAX_THREADS; i++)
- {
- arg[i] = i;
-
-#if !defined(_MSC_VER)
- pthread_t pthread[1];
- ok = (pthread_create(pthread, NULL, init_thread, (void*)(&arg[i])) == 0);
- pthread_detach(pthread[0]);
-#else
- ok = (CreateThread(NULL, 0, init_thread, (LPVOID)(&arg[i]), 0, NULL) != NULL);
-#endif
- if (!ok)
- {
- cout << "Failed to create thread number " << i << endl;
- Application::exit_with_failure();
- }
-
- // Wait until the thread has finished launching and is gone to sleep
- while (threads[i].state == THREAD_INITIALIZING) {}
- }
- }