Add a lock to prevent race condition

This commit is contained in:
Dmitry Polienko 2016-08-24 22:01:37 +07:00
commit 885543e43e

View file

@ -300,10 +300,13 @@ var
# A workaround for recursion deadlock issue # A workaround for recursion deadlock issue
# https://github.com/nim-lang/Nim/issues/4597 # https://github.com/nim-lang/Nim/issues/4597
var var
numSlavesRunning: int numSlavesLock: Lock
numSlavesWaiting: int numSlavesRunning {.guard: numSlavesLock}: int
numSlavesWaiting {.guard: numSlavesLock}: int
isSlave {.threadvar.}: bool isSlave {.threadvar.}: bool
numSlavesLock.initLock
gSomeReady.initSemaphore() gSomeReady.initSemaphore()
proc slave(w: ptr Worker) {.thread.} = proc slave(w: ptr Worker) {.thread.} =
@ -320,9 +323,13 @@ proc slave(w: ptr Worker) {.thread.} =
# in Visual Studio?) # in Visual Studio?)
when not defined(vcc): assert(not w.ready) when not defined(vcc): assert(not w.ready)
atomicInc numSlavesRunning withLock numSlavesLock:
inc numSlavesRunning
w.f(w, w.data) w.f(w, w.data)
atomicDec numSlavesRunning
withLock numSlavesLock:
dec numSlavesRunning
if w.q.len != 0: w.cleanFlowVars if w.q.len != 0: w.cleanFlowVars
if w.shutdown: if w.shutdown:
@ -477,7 +484,11 @@ proc nimSpawn3(fn: WorkerProc; data: pointer) {.compilerProc.} =
await(self.taskStarted) await(self.taskStarted)
return return
if isSlave and numSlavesRunning <= numSlavesWaiting + 1: if isSlave:
# Run under lock until `numSlavesWaiting` increment to avoid a
# race (otherwise two last threads might start waiting together)
withLock numSlavesLock:
if numSlavesRunning <= numSlavesWaiting + 1:
# All the other slaves are waiting # All the other slaves are waiting
# If we wait now, we-re deadlocked until # If we wait now, we-re deadlocked until
# an external spawn happens ! # an external spawn happens !
@ -489,17 +500,17 @@ proc nimSpawn3(fn: WorkerProc; data: pointer) {.compilerProc.} =
if selectWorker(w, fn, data): if selectWorker(w, fn, data):
return return
else: else:
# There is no place in pool. We're deadlocked. # There is no place in the pool. We're deadlocked.
# echo "Deadlock!" # echo "Deadlock!"
discard discard
if isSlave: inc numSlavesWaiting
atomicInc numSlavesWaiting
await(gSomeReady) await(gSomeReady)
if isSlave: if isSlave:
atomicDec numSlavesWaiting withLock numSlavesLock:
dec numSlavesWaiting
var var
distinguishedLock: Lock distinguishedLock: Lock