X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fsearch.cpp;h=4654256065bd54612ff03e1c2a6778e65a7f169c;hb=fb5ba1d32912a3b5fc405511fc34d504df5393b9;hp=fbae76d7720fee3dd5833697b0b70be412428b5c;hpb=093dd8fe88d278db6cd5c956a771a45a295e1de3;p=stockfish diff --git a/src/search.cpp b/src/search.cpp index fbae76d7..46542560 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -280,6 +280,7 @@ namespace { const Value futilityValue, Depth depth, int *moves, MovePicker *mp, int master, bool pvNode); void wake_sleeping_threads(); + void put_threads_to_sleep(); #if !defined(_MSC_VER) void *init_thread(void *threadID); @@ -335,7 +336,7 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move, int maxNodes, int maxTime, Move searchMoves[]) { // Initialize global search variables - AllThreadsShouldSleep = StopOnPonderhit = AbortSearch = Quit = false; + StopOnPonderhit = AbortSearch = Quit = false; AspirationFailLow = false; NodesSincePoll = 0; SearchStartTime = get_system_time(); @@ -521,7 +522,8 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move, if (UseLogFile) LogFile.close(); - AllThreadsShouldSleep = true; + put_threads_to_sleep(); + return !Quit; } @@ -606,19 +608,19 @@ void init_threads() { Application::exit_with_failure(); } - // Wait until the thread has finished launching - while (!Threads[i].running); + // Wait until the thread has finished launching and is gone to sleep + while (!Threads[i].running || !Threads[i].sleeping); } } -/// stop_threads() is called when the program exits. It makes all the +/// exit_threads() is called when the program exits. It makes all the /// helper threads exit cleanly. -void stop_threads() { +void exit_threads() { ActiveThreads = THREAD_MAX; // HACK - AllThreadsShouldSleep = false; // HACK + AllThreadsShouldSleep = true; // HACK wake_sleeping_threads(); AllThreadsShouldExit = true; for (int i = 1; i < THREAD_MAX; i++) @@ -2786,16 +2788,19 @@ namespace { #if !defined(_MSC_VER) pthread_mutex_lock(&WaitLock); - if (Idle || threadID >= ActiveThreads) + if (AllThreadsShouldSleep || threadID >= ActiveThreads) pthread_cond_wait(&WaitCond, &WaitLock); pthread_mutex_unlock(&WaitLock); #else WaitForSingleObject(SitIdleEvent[threadID], INFINITE); #endif - Threads[threadID].sleeping = false; } + // Out of the while loop to avoid races in case thread is woken up but + // while condition still holds true so that is put to sleep again. + Threads[threadID].sleeping = false; + // If this thread has been assigned work, launch a search if (Threads[threadID].workIsWaiting) { @@ -3047,10 +3052,16 @@ namespace { void wake_sleeping_threads() { + assert(AllThreadsShouldSleep); + + AllThreadsShouldSleep = false; + if (ActiveThreads > 1) { for (int i = 1; i < ActiveThreads; i++) { + assert(Threads[i].sleeping == true); + Threads[i].idle = true; Threads[i].workIsWaiting = false; } @@ -3063,10 +3074,30 @@ namespace { for (int i = 1; i < THREAD_MAX; i++) SetEvent(SitIdleEvent[i]); #endif + + // Wait for the threads to be all woken up + for (int i = 1; i < ActiveThreads; i++) + while (Threads[i].sleeping); } } + // put_threads_to_sleep() makes all the threads go to sleep just before + // to leave think(), at the end of the search. Threads should have already + // finished the job and should be idle. + + void put_threads_to_sleep() { + + assert(!AllThreadsShouldSleep); + + AllThreadsShouldSleep = true; + + // Wait for the threads to be all sleeping + for (int i = 1; i < ActiveThreads; i++) + while (!Threads[i].sleeping); + } + + // 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