@@ -415,8 +415,8 @@ let e = Base.Event(true),
415415 newthreads = zeros (Int16, length (tids))
416416 onces = Vector {Vector{Nothing}} (undef, length (tids))
417417 allonces = Vector {Vector{Vector{Nothing}}} (undef, length (tids))
418- for i = 1 : length (tids)
419- function cl ()
418+ # allocate closure memory to last until all threads are started
419+ cls = [ function cl ()
420420 GC. gc (false ) # stress test the GC-safepoint mechanics of jl_adopt_thread
421421 try
422422 newthreads[i] = threadid ()
@@ -434,43 +434,50 @@ let e = Base.Event(true),
434434 GC. gc (false ) # stress test the GC-safepoint mechanics of jl_delete_thread
435435 nothing
436436 end
437- function threadcallclosure (cl:: F ) where {F} # create sparam so we can reference the type of cl in the ccall type
438- threadwork = @cfunction cl -> cl () Cvoid (Ref{F},) # create a cfunction that specializes on cl as an argument and calls it
439- err = @ccall uv_thread_create (Ref (tids, i):: Ptr{UInt} , threadwork:: Ptr{Cvoid} , cl:: Ref{F} ):: Cint # call that on a thread
440- err == 0 || Base. uv_error (" uv_thread_create" , err)
441- end
442- threadcallclosure (cl)
443- end
444- @noinline function waitallthreads (tids)
437+ for i = 1 : length (tids)]
438+ GC. @preserve cls begin # this memory must survive until each corresponding thread exits (waitallthreads / uv_thread_join)
439+ Base. preserve_handle (cls)
445440 for i = 1 : length (tids)
446- tid = Ref (tids, i)
447- tidp = Base. unsafe_convert (Ptr{UInt}, tid):: Ptr{UInt}
448- gc_state = @ccall jl_gc_safe_enter ():: Int8
449- GC. @preserve tid err = @ccall uv_thread_join (tidp:: Ptr{UInt} ):: Cint
450- @ccall jl_gc_safe_leave (gc_state:: Int8 ):: Cvoid
451- err == 0 || Base. uv_error (" uv_thread_join" , err)
452- end
453- end
454- try
455- # let them finish in batches of 10
456- for i = 1 : length (tids) ÷ 10
457- for i = 1 : 10
458- newid = take! (started)
459- @test newid != threadid ()
441+ function threadcallclosure (tid:: Ref{UInt} , cl:: Ref{F} ) where {F} # create sparam so we can reference the type of cl in the ccall type
442+ threadwork = @cfunction cl -> cl () Cvoid (Ref{F},) # create a cfunction that specializes on cl as an argument and calls it
443+ err = @ccall uv_thread_create (tid:: Ptr{UInt} , threadwork:: Ptr{Cvoid} , cl:: Ref{F} ):: Cint # call that on a thread
444+ err == 0 || Base. uv_error (" uv_thread_create" , err)
445+ nothing
460446 end
461- for i = 1 : 10
462- push! (finish, nothing )
447+ threadcallclosure (Ref (tids, i), Ref (cls, i))
448+ end
449+ @noinline function waitallthreads (tids, cls)
450+ for i = 1 : length (tids)
451+ tid = Ref (tids, i)
452+ tidp = Base. unsafe_convert (Ptr{UInt}, tid):: Ptr{UInt}
453+ gc_state = @ccall jl_gc_safe_enter ():: Int8
454+ GC. @preserve tid err = @ccall uv_thread_join (tidp:: Ptr{UInt} ):: Cint
455+ @ccall jl_gc_safe_leave (gc_state:: Int8 ):: Cvoid
456+ err == 0 || Base. uv_error (" uv_thread_join" , err)
463457 end
458+ Base. unpreserve_handle (cls)
464459 end
465- @test isempty (started)
466- # now run the second part of the test where they all try to access the other threads elements
467- notify (starttest2)
468- finally
469- for _ = 1 : length (tids)
470- # run IO loop until all threads are close to exiting
471- take! (exiting)
460+ try
461+ # let them finish in batches of 10
462+ for i = 1 : length (tids) ÷ 10
463+ for i = 1 : 10
464+ newid = take! (started)
465+ @test newid != threadid ()
466+ end
467+ for i = 1 : 10
468+ push! (finish, nothing )
469+ end
470+ end
471+ @test isempty (started)
472+ # now run the second part of the test where they all try to access the other threads elements
473+ notify (starttest2)
474+ finally
475+ for _ = 1 : length (tids)
476+ # run IO loop until all threads are close to exiting
477+ take! (exiting)
478+ end
479+ waitallthreads (tids, cls)
472480 end
473- waitallthreads (tids)
474481 end
475482 @test isempty (started)
476483 @test isempty (finish)
0 commit comments