]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Don't reparent if a cutoff is pending
[stockfish] / src / search.cpp
index 371144086898bf417e16af7d17a261e8b5849870..dd3030a0dd4f1390b0ef8b1043ff70bfa73afb19 100644 (file)
@@ -265,7 +265,7 @@ void Search::think() {
       goto finalize;
   }
 
-  if (Options["OwnBook"])
+  if (Options["OwnBook"] && !Limits.infinite)
   {
       Move bookMove = book.probe(pos, Options["Book File"], Options["Best Book Move"]);
 
@@ -332,7 +332,7 @@ finalize:
   // but if we are pondering or in infinite search, we shouldn't print the best
   // move before we are told to do so.
   if (!Signals.stop && (Limits.ponder || Limits.infinite))
-      Threads.this_thread()->wait_for_stop_or_ponderhit();
+      pos.this_thread()->wait_for_stop_or_ponderhit();
 
   // Best move could be MOVE_NONE when searching on a stalemate position
   cout << "bestmove " << move_to_uci(RootMoves[0].pv[0], Chess960)
@@ -531,7 +531,7 @@ namespace {
     assert((alpha == beta - 1) || PvNode);
     assert(depth > DEPTH_ZERO);
 
-    Move movesSearched[MAX_MOVES];
+    Move movesSearched[64];
     StateInfo st;
     const TTEntry *tte;
     Key posKey;
@@ -543,7 +543,7 @@ namespace {
     bool isPvMove, inCheck, singularExtensionNode, givesCheck;
     bool captureOrPromotion, dangerous, doFullDepthSearch;
     int moveCount = 0, playedMoveCount = 0;
-    Thread* thisThread = Threads.this_thread();
+    Thread* thisThread = pos.this_thread();
     SplitPoint* sp = NULL;
 
     refinedValue = bestValue = value = -VALUE_INFINITE;
@@ -944,7 +944,7 @@ split_point_start: // At split points actual search starts from here
       }
 
       ss->currentMove = move;
-      if (!SpNode && !captureOrPromotion)
+      if (!SpNode && !captureOrPromotion && playedMoveCount < 64)
           movesSearched[playedMoveCount++] = move;
 
       // Step 14. Make the move
@@ -1825,8 +1825,7 @@ void Thread::idle_loop(SplitPoint* sp_master) {
           lock_release(Threads.splitLock);
 
           Stack ss[MAX_PLY_PLUS_2];
-          Position pos(*sp->pos);
-          Thread* master = sp->master;
+          Position pos(*sp->pos, this);
 
           memcpy(ss, sp->ss - 1, 4 * sizeof(Stack));
           (ss+1)->sp = sp;
@@ -1848,17 +1847,57 @@ void Thread::idle_loop(SplitPoint* sp_master) {
           sp->slavesMask &= ~(1ULL << idx);
           sp->nodes += pos.nodes_searched();
 
-          // After releasing the lock we cannot access anymore any SplitPoint
-          // related data in a reliably way becuase it could have been released
-          // under our feet by the sp master.
-          lock_release(sp->lock);
-
           // 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 (   Threads.use_sleeping_threads()
-              && this != master
-              && !master->is_searching)
-              master->wake_up();
+              && this != sp->master
+              && !sp->master->is_searching)
+              sp->master->wake_up();
+
+          // After releasing the lock we cannot access anymore any SplitPoint
+          // related data in a safe way becuase it could have been released under
+          // our feet by the sp master. Also accessing other Thread objects is
+          // unsafe because if we are exiting there is a chance are already freed.
+          lock_release(sp->lock);
+
+          // Try to reparent to another split point. Only for slave threads
+          // that are not master of any active split point.
+          if (!splitPointsCnt)
+              for (int i = 0; i < Threads.size(); i++)
+              {
+                  Thread* th = &Threads[i];
+                  SplitPoint* oldest = &th->splitPoints[0];
+
+                  // Find the first split point with still all slaves running
+                  // where we are available as a possible slave.
+                  if (   !is_searching
+                      &&  th->splitPointsCnt
+                      && !oldest->cutoff
+                      &&  oldest->slavesMask == oldest->allSlavesMask
+                      && !single_bit(oldest->allSlavesMask))
+                  {
+                      lock_grab(oldest->lock);
+                      lock_grab(Threads.splitLock);
+
+                      // Retest all under lock protection, we are in the middle
+                      // of a race storm here !
+                      if (   !is_searching
+                          &&  th->splitPointsCnt
+                          && !oldest->cutoff
+                          &&  oldest->slavesMask == oldest->allSlavesMask
+                          && !single_bit(oldest->allSlavesMask))
+                      {
+                          oldest->slavesMask |= 1ULL << idx; // allSlavesMask is not updated
+                          curSplitPoint = oldest;
+                          is_searching = true;
+                      }
+
+                      lock_release(Threads.splitLock);
+                      lock_release(oldest->lock);
+
+                      break; // Exit anyhow, only one try (enough in 99% of cases)
+                  }
+              }
       }
   }
 }