Fix subtle race with slave allocation

When allocating a slave we set both is_searching
and splitPoint under lock protection.

Unfortunatly the order in which the variables are
set is not defined. This article was very clarifying:

http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/

So when in idle loop we test for is_searching and then
access splitPoint, it could happen that splitPoint is still
not updated leading to a possible crash.

Fix the race lock protecting splitPoint access.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
Marco Costalba
2012-01-31 20:19:25 +01:00
parent df31398bb9
commit 51e8efdab5
3 changed files with 38 additions and 47 deletions
+16 -6
View File
@@ -1864,9 +1864,14 @@ void Thread::idle_loop(SplitPoint* sp_master) {
{
assert(!do_sleep && !do_exit);
// Copy split point position and search stack and call search()
Stack ss[MAX_PLY_PLUS_2];
lock_grab(Threads.splitLock);
assert(is_searching);
SplitPoint* sp = splitPoint;
lock_release(Threads.splitLock);
Stack ss[MAX_PLY_PLUS_2];
Position pos(*sp->pos, threadID);
memcpy(ss, sp->ss - 1, 4 * sizeof(Stack));
@@ -1885,12 +1890,9 @@ void Thread::idle_loop(SplitPoint* sp_master) {
assert(is_searching);
// We return from search with lock held
is_searching = false;
sp->slavesMask &= ~(1ULL << threadID);
sp->nodes += pos.nodes_searched();
lock_release(sp->lock);
is_searching = false;
// 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.
@@ -1898,8 +1900,16 @@ void Thread::idle_loop(SplitPoint* sp_master) {
&& threadID != sp->master
&& !Threads[sp->master].is_searching)
Threads[sp->master].wake_up();
// 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);
}
}
// In helpful master concept a master can help only a sub-tree of its split
// point, and because here is all finished is not possible master is booked.
assert(!is_searching);
}