summary refs log tree commit diff stats
path: root/lib/pure/concurrency
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure/concurrency')
-rw-r--r--lib/pure/concurrency/threadpool.nim38
1 files changed, 35 insertions, 3 deletions
diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim
index 9490dbbd5..baa96cacd 100644
--- a/lib/pure/concurrency/threadpool.nim
+++ b/lib/pure/concurrency/threadpool.nim
@@ -297,9 +297,17 @@ var
   gSomeReady : Semaphore
   readyWorker: ptr Worker
 
+# A workaround for recursion deadlock issue
+# https://github.com/nim-lang/Nim/issues/4597
+var
+  numSlavesRunning: int
+  numSlavesWaiting: int
+  isSlave {.threadvar.}: bool
+
 gSomeReady.initSemaphore()
 
 proc slave(w: ptr Worker) {.thread.} =
+  isSlave = true
   while true:
     when declared(atomicStoreN):
       atomicStoreN(addr(w.ready), true, ATOMIC_SEQ_CST)
@@ -311,7 +319,11 @@ proc slave(w: ptr Worker) {.thread.} =
     # XXX Somebody needs to look into this (why does this assertion fail
     # in Visual Studio?)
     when not defined(vcc): assert(not w.ready)
+
+    atomicInc numSlavesRunning
     w.f(w, w.data)
+    atomicDec numSlavesRunning
+
     if w.q.len != 0: w.cleanFlowVars
     if w.shutdown:
       w.shutdown = false
@@ -464,10 +476,30 @@ proc nimSpawn3(fn: WorkerProc; data: pointer) {.compilerProc.} =
         fn(self, data)
         await(self.taskStarted)
         return
+
+    if isSlave and numSlavesRunning <= numSlavesWaiting + 1:
+      # All the other slaves are waiting
+      # If we wait now, we-re deadlocked until
+      # an external spawn happens !
+      if currentPoolSize < maxPoolSize:
+        if not workersData[currentPoolSize].initialized:
+          activateWorkerThread(currentPoolSize)
+        let w = addr(workersData[currentPoolSize])
+        atomicInc currentPoolSize
+        if selectWorker(w, fn, data):
+          return
       else:
-        await(gSomeReady)
-    else:
-      await(gSomeReady)
+        # There is no place in pool. We're deadlocked.
+        # echo "Deadlock!"
+        discard
+
+    if isSlave:
+      atomicInc numSlavesWaiting
+
+    await(gSomeReady)
+
+    if isSlave:
+      atomicDec numSlavesWaiting
 
 var
   distinguishedLock: Lock
pre>
c498f6cd ^
c442a5ad ^

c498f6cd ^
c442a5ad ^
c88b9e31 ^
5cec03b4 ^



c442a5ad ^

54ed56f2 ^
c442a5ad ^
c88b9e31 ^
5cec03b4 ^


c442a5ad ^
5cec03b4 ^
c442a5ad ^
c88b9e31 ^
5cec03b4 ^


c442a5ad ^

54ed56f2 ^
c442a5ad ^
c88b9e31 ^
5cec03b4 ^

c442a5ad ^

54ed56f2 ^
c442a5ad ^
c88b9e31 ^
5cec03b4 ^

c442a5ad ^


54ed56f2 ^
c442a5ad ^
c88b9e31 ^
5cec03b4 ^
2ec6d1e5 ^
c442a5ad ^
2ec6d1e5 ^


c442a5ad ^
2ec6d1e5 ^
95fbb9bf ^

e0d71f95 ^

5cec03b4 ^





a754efc5 ^
5cec03b4 ^


a754efc5 ^
5cec03b4 ^





583a966d ^
5cec03b4 ^


2ec6d1e5 ^

c88b9e31 ^
d5d43e04 ^
2ec6d1e5 ^
d5d43e04 ^
2ec6d1e5 ^
d5d43e04 ^
44fdc79f ^
d5d43e04 ^
6362c51d ^
9ad81331 ^
6362c51d ^
d5d43e04 ^

2ec6d1e5 ^

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123