]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Be sure threads are woken in wake_sleeping_threads()
[stockfish] / src / search.cpp
index 01412276ecdaac2594a8063646c5f20402144eea..22bc0156705121a9a02adfcd8b59c1ff66e21997 100644 (file)
@@ -219,9 +219,8 @@ namespace {
   Thread Threads[THREAD_MAX];
   Lock MPLock;
   Lock IOLock;
-  bool AllThreadsShouldExit = false;
+  bool AllThreadsShouldExit, AllThreadsShouldSleep;
   SplitPoint SplitPointStack[THREAD_MAX][ACTIVE_SPLIT_POINTS_MAX];
-  bool Idle = true;
 
 #if !defined(_MSC_VER)
   pthread_cond_t WaitCond;
@@ -336,7 +335,7 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
            int maxNodes, int maxTime, Move searchMoves[]) {
 
   // Initialize global search variables
-  Idle = StopOnPonderhit = AbortSearch = Quit = false;
+  AllThreadsShouldSleep = StopOnPonderhit = AbortSearch = Quit = false;
   AspirationFailLow = false;
   NodesSincePoll = 0;
   SearchStartTime = get_system_time();
@@ -522,7 +521,7 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
   if (UseLogFile)
       LogFile.close();
 
-  Idle = true;
+  AllThreadsShouldSleep = true;
   return !Quit;
 }
 
@@ -567,9 +566,6 @@ void init_threads() {
   pthread_t pthread[1];
 #endif
 
-  for (i = 0; i < THREAD_MAX; i++)
-      Threads[i].activeSplitPoints = 0;
-
   // Initialize global locks
   lock_init(&MPLock, NULL);
   lock_init(&IOLock, NULL);
@@ -584,14 +580,15 @@ void init_threads() {
       SitIdleEvent[i] = CreateEvent(0, FALSE, FALSE, 0);
 #endif
 
+  // Will be set just before program exits to properly end the threads
+  AllThreadsShouldExit = false;
+
+  // Threads will be put to sleep as soon as created
+  AllThreadsShouldSleep = true;
+
   // All threads except the main thread should be initialized to idle state
   for (i = 1; i < THREAD_MAX; i++)
-  {
-      Threads[i].stop = false;
-      Threads[i].workIsWaiting = false;
       Threads[i].idle = true;
-      Threads[i].running = false;
-  }
 
   // Launch the helper threads
   for (i = 1; i < THREAD_MAX; i++)
@@ -621,7 +618,7 @@ void init_threads() {
 void stop_threads() {
 
   ActiveThreads = THREAD_MAX;  // HACK
-  Idle = false;  // HACK
+  AllThreadsShouldSleep = false;  // HACK
   wake_sleeping_threads();
   AllThreadsShouldExit = true;
   for (int i = 1; i < THREAD_MAX; i++)
@@ -653,7 +650,6 @@ void SearchStack::init(int ply) {
   currentMove = threatMove = MOVE_NONE;
   reduction = Depth(0);
   eval = VALUE_NONE;
-  evalInfo = NULL;
 }
 
 void SearchStack::initKillers() {
@@ -1386,10 +1382,7 @@ namespace {
         if (tte && (tte->type() & VALUE_TYPE_EVAL))
             staticValue = value_from_tt(tte->value(), ply);
         else
-        {
             staticValue = evaluate(pos, ei, threadID);
-            ss[ply].evalInfo = &ei;
-        }
 
         ss[ply].eval = staticValue;
         futilityValue = staticValue + futility_margin(depth, 0); //FIXME: Remove me, only for split
@@ -2780,16 +2773,17 @@ namespace {
 
     Threads[threadID].running = true;
 
-    while (true)
+    while (!AllThreadsShouldExit || threadID == 0)
     {
-        if (AllThreadsShouldExit && threadID != 0)
-            break;
-
         // If we are not thinking, wait for a condition to be signaled
         // instead of wasting CPU time polling for work.
-        while (threadID != 0 && (Idle || threadID >= ActiveThreads))
+        while (    threadID != 0
+               && !AllThreadsShouldExit
+               && (AllThreadsShouldSleep || threadID >= ActiveThreads))
         {
 
+            Threads[threadID].sleeping = true;
+
 #if !defined(_MSC_VER)
             pthread_mutex_lock(&WaitLock);
             if (Idle || threadID >= ActiveThreads)
@@ -2801,6 +2795,10 @@ namespace {
 #endif
         }
 
+        // 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)
       {
@@ -3056,6 +3054,8 @@ namespace {
     {
         for (int i = 1; i < ActiveThreads; i++)
         {
+            assert(Threads[i].sleeping == true);
+
             Threads[i].idle = true;
             Threads[i].workIsWaiting = false;
         }
@@ -3068,6 +3068,10 @@ 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);
     }
   }