Recursive lock all split point's chain
authorMarco Costalba <mcostalba@gmail.com>
Sat, 20 Feb 2010 17:29:53 +0000 (18:29 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Sat, 20 Feb 2010 17:29:53 +0000 (18:29 +0100)
When we found a cut-off then lock all the split point chain,
not only current one to avoid races in case two threads running
on different split points where one is ancestor then the other,
find a beta cut-off at the same time, in this case we want only
one to call sp_update_pv().

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/search.cpp

index 88ef5237de054378e2514ad0f631269892ddf557..38e2ac14084a26442fdafa19581f5843ec1dc897 100644 (file)
@@ -1860,17 +1860,29 @@ namespace {
       // New best move?
       if (value > sp->bestValue) // Less then 2% of cases
       {
-          lock_grab(&(sp->lock));
+          // Recursive locking, lock current split point and its ancestors to
+          // guarantee thread_should_stop() and sp_update_pv() are race free.
+          SplitPoint* spChain[MAX_THREADS * ACTIVE_SPLIT_POINTS_MAX];
+          int cnt = 0;
+          for (spChain[cnt] = sp; spChain[cnt]; )
+          {
+              lock_grab(&(spChain[cnt++]->lock));
+              spChain[cnt] = spChain[cnt - 1]->parent;
+          }
+
           if (value > sp->bestValue && !TM.thread_should_stop(threadID))
           {
               sp->bestValue = value;
               if (sp->bestValue >= sp->beta)
               {
-                  sp_update_pv(sp->parentSstack, ss, sp->ply);
                   sp->stopRequest = true;
+                  sp_update_pv(sp->parentSstack, ss, sp->ply);
               }
           }
-          lock_release(&(sp->lock));
+
+          // Release locks in reverse order
+          while (cnt > 0)
+              lock_release(&(spChain[--cnt]->lock));
       }
     }
 
@@ -1975,7 +1987,16 @@ namespace {
       // New best move?
       if (value > sp->bestValue) // Less then 2% of cases
       {
-          lock_grab(&(sp->lock));
+          // Recursive locking, lock current split point and its ancestors to
+          // guarantee thread_should_stop() and sp_update_pv() are race free.
+          SplitPoint* spChain[MAX_THREADS * ACTIVE_SPLIT_POINTS_MAX];
+          int cnt = 0;
+          for (spChain[cnt] = sp; spChain[cnt]; )
+          {
+              lock_grab(&(spChain[cnt++]->lock));
+              spChain[cnt] = spChain[cnt - 1]->parent;
+          }
+
           if (value > sp->bestValue && !TM.thread_should_stop(threadID))
           {
               sp->bestValue = value;
@@ -1992,7 +2013,10 @@ namespace {
                       ss[sp->ply].mateKiller = move;
               }
           }
-          lock_release(&(sp->lock));
+
+          // Release locks in reverse order
+          while (cnt > 0)
+              lock_release(&(spChain[--cnt]->lock));
       }
     }