@@ -110,6 +110,7 @@ const SyncObject = Union{CuContext, CuStream, CuEvent}
110
110
const MAX_SYNC_THREADS = 4
111
111
const sync_channels = Array {BidirectionalChannel{SyncObject,CUresult}} (undef, MAX_SYNC_THREADS)
112
112
const sync_channel_cursor = Threads. Atomic {UInt32} (1 )
113
+ const sync_channel_lock = Base. ReentrantLock ()
113
114
114
115
function synchronization_worker (data)
115
116
i = Int (data)
@@ -133,15 +134,25 @@ function synchronization_worker(data)
133
134
end
134
135
135
136
@noinline function create_synchronization_worker (i)
136
- sync_channels[i] = BidirectionalChannel {SyncObject,CUresult} ()
137
- # should be safe to assign before threads are running;
138
- # any user will just submit work that makes it block
137
+ lock (sync_channel_lock) do
138
+ # test and test-and-set
139
+ if isassigned (sync_channels, i)
140
+ return
141
+ end
142
+
143
+ # should be safe to assign before threads are running;
144
+ # any user will just submit work that makes it block
145
+ sync_channels[i] = BidirectionalChannel {SyncObject,CUresult} ()
139
146
140
- # we don't know what the size of uv_thread_t is, so reserve enough space
141
- tid = Ref {NTuple{32, UInt8}} (ntuple (i -> 0 , 32 ))
147
+ # we don't know what the size of uv_thread_t is, so reserve enough space
148
+ tid = Ref {NTuple{32, UInt8}} (ntuple (i -> 0 , 32 ))
142
149
143
- cb = @cfunction (synchronization_worker, Cvoid, (Ptr{Cvoid},))
144
- @ccall uv_thread_create (tid:: Ptr{Cvoid} , cb:: Ptr{Cvoid} , Ptr {Cvoid} (i):: Ptr{Cvoid} ):: Int32
150
+ cb = @cfunction (synchronization_worker, Cvoid, (Ptr{Cvoid},))
151
+ err = @ccall uv_thread_create (tid:: Ptr{Cvoid} , cb:: Ptr{Cvoid} , Ptr {Cvoid} (i):: Ptr{Cvoid} ):: Cint
152
+ err == 0 || Base. uv_error (" uv_thread_create" , err)
153
+ @ccall uv_thread_detach (tid:: Ptr{Cvoid} ):: Cint
154
+ err == 0 || Base. uv_error (" uv_thread_detach" , err)
155
+ end
145
156
146
157
return
147
158
end
0 commit comments