diff --git a/src/search.cpp b/src/search.cpp index 88ef5237..38e2ac14 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -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)); } }