forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This was removed before and added back apparently by mistake. (cherry picked from commit 5928786)
- Loading branch information
1 parent
9472d72
commit 490d5e6
Showing
1 changed file
with
131 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,131 +1,131 @@ | ||
# This file is a part of Julia. License is MIT: https://julialang.org/license | ||
|
||
let cmd = `$(Base.julia_cmd()) --depwarn=error --startup-file=no threads_exec.jl` | ||
for test_nthreads in (1, 2, 4, 4) # run once to try single-threaded mode, then try a couple times to trigger bad races | ||
run(pipeline(setenv(cmd, "JULIA_NUM_THREADS" => test_nthreads), stdout = stdout, stderr = stderr)) | ||
end | ||
end | ||
|
||
# issue #34415 - make sure external affinity settings work | ||
if Sys.islinux() && Sys.CPU_THREADS > 1 && Sys.which("taskset") !== nothing | ||
run_with_affinity(spec) = readchomp(`taskset -c $spec $(Base.julia_cmd()) -e "run(\`taskset -p \$(getpid())\`)"`) | ||
@test endswith(run_with_affinity("1"), "2") | ||
@test endswith(run_with_affinity("0,1"), "3") | ||
end | ||
|
||
# issue #34769 | ||
function idle_callback(handle) | ||
idle = @Base.handle_as handle UvTestIdle | ||
if idle.active | ||
idle.count += 1 | ||
if idle.count == 1 | ||
# We want to hit the case where we're allowing | ||
# the thread to go to sleep, which only happens | ||
# after some default amount of time (DEFAULT_THREAD_SLEEP_THRESHOLD) | ||
# so spend that amount of time here. | ||
Libc.systemsleep(0.004) | ||
elseif idle.count >= 10 | ||
lock(idle.cond) | ||
try | ||
notify(idle.cond, true) | ||
finally | ||
unlock(idle.cond) | ||
end | ||
idle.active = false | ||
end | ||
end | ||
nothing | ||
end | ||
|
||
mutable struct UvTestIdle | ||
handle::Ptr{Cvoid} | ||
cond::Base.ThreadSynchronizer | ||
isopen::Bool | ||
active::Bool | ||
count::Int | ||
|
||
function UvTestIdle() | ||
this = new(Libc.malloc(Base._sizeof_uv_idle), Base.ThreadSynchronizer(), true, false, 0) | ||
Base.iolock_begin() | ||
Base.associate_julia_struct(this.handle, this) | ||
err = ccall(:uv_idle_init, Cint, (Ptr{Cvoid}, Ptr{Cvoid}), | ||
Base.eventloop(), this.handle) | ||
if err != 0 | ||
Libc.free(this.handle) | ||
this.handle = C_NULL | ||
throw(_UVError("uv_idle_init", err)) | ||
end | ||
err = ccall(:uv_idle_start, Cint, (Ptr{Cvoid}, Ptr{Cvoid}), | ||
this.handle, @cfunction(idle_callback, Cvoid, (Ptr{Cvoid},))) | ||
if err != 0 | ||
Libc.free(this.handle) | ||
this.handle = C_NULL | ||
throw(_UVError("uv_idle_start", err)) | ||
end | ||
finalizer(Base.uvfinalize, this) | ||
Base.iolock_end() | ||
return this | ||
end | ||
end | ||
Base.unsafe_convert(::Type{Ptr{Cvoid}}, idle::UvTestIdle) = idle.handle | ||
|
||
function Base.uvfinalize(t::UvTestIdle) | ||
Base.iolock_begin() | ||
Base.lock(t.cond) | ||
try | ||
if t.handle != C_NULL | ||
Base.disassociate_julia_struct(t.handle) # not going to call the usual close hooks | ||
if t.isopen | ||
t.isopen = false | ||
ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), t) | ||
end | ||
t.handle = C_NULL | ||
notify(t.cond, false) | ||
end | ||
finally | ||
unlock(t.cond) | ||
end | ||
Base.iolock_end() | ||
nothing | ||
end | ||
|
||
function Base.wait(idle::UvTestIdle) | ||
Base.iolock_begin() | ||
Base.preserve_handle(idle) | ||
Base.lock(idle.cond) | ||
try | ||
idle.active = true | ||
wait(idle.cond) | ||
finally | ||
Base.unlock(idle.cond) | ||
Base.unpreserve_handle(idle) | ||
Base.iolock_end() | ||
end | ||
end | ||
|
||
# Spawn another process as a watchdog. If this test fails, it'll unrecoverably | ||
# hang in the event loop. Another process needs to kill it | ||
cmd = """ | ||
@async (Base.wait_readnb(stdin, 1); exit()) | ||
sleep(100) | ||
isopen(stdin) || exit() | ||
println(stderr, "ERROR: Killing threads test due to watchdog expiry") | ||
ccall(:uv_kill, Cint, (Cint, Cint), $(getpid()), Base.SIGTERM) | ||
""" | ||
proc = open(pipeline(`$(Base.julia_cmd()) -e $cmd`; stderr=stderr); write=true) | ||
|
||
let idle=UvTestIdle() | ||
wait(idle) | ||
end | ||
|
||
using Base.Threads | ||
@threads for i = 1:1 | ||
let idle=UvTestIdle() | ||
wait(idle) | ||
end | ||
end | ||
|
||
@test process_running(proc) | ||
|
||
# We don't need the watchdog anymore | ||
close(proc.in) | ||
# This file is a part of Julia. License is MIT: https://julialang.org/license | ||
|
||
let cmd = `$(Base.julia_cmd()) --depwarn=error --startup-file=no threads_exec.jl` | ||
for test_nthreads in (1, 2, 4, 4) # run once to try single-threaded mode, then try a couple times to trigger bad races | ||
run(pipeline(setenv(cmd, "JULIA_NUM_THREADS" => test_nthreads), stdout = stdout, stderr = stderr)) | ||
end | ||
end | ||
|
||
# issue #34415 - make sure external affinity settings work | ||
if Sys.islinux() && Sys.CPU_THREADS > 1 && Sys.which("taskset") !== nothing | ||
run_with_affinity(spec) = readchomp(`taskset -c $spec $(Base.julia_cmd()) -e "run(\`taskset -p \$(getpid())\`)"`) | ||
@test endswith(run_with_affinity("1"), "2") | ||
@test endswith(run_with_affinity("0,1"), "3") | ||
end | ||
|
||
# issue #34769 | ||
function idle_callback(handle) | ||
idle = @Base.handle_as handle UvTestIdle | ||
if idle.active | ||
idle.count += 1 | ||
if idle.count == 1 | ||
# We want to hit the case where we're allowing | ||
# the thread to go to sleep, which only happens | ||
# after some default amount of time (DEFAULT_THREAD_SLEEP_THRESHOLD) | ||
# so spend that amount of time here. | ||
Libc.systemsleep(0.004) | ||
elseif idle.count >= 10 | ||
lock(idle.cond) | ||
try | ||
notify(idle.cond, true) | ||
finally | ||
unlock(idle.cond) | ||
end | ||
idle.active = false | ||
end | ||
end | ||
nothing | ||
end | ||
|
||
mutable struct UvTestIdle | ||
handle::Ptr{Cvoid} | ||
cond::Base.ThreadSynchronizer | ||
isopen::Bool | ||
active::Bool | ||
count::Int | ||
|
||
function UvTestIdle() | ||
this = new(Libc.malloc(Base._sizeof_uv_idle), Base.ThreadSynchronizer(), true, false, 0) | ||
Base.iolock_begin() | ||
Base.associate_julia_struct(this.handle, this) | ||
err = ccall(:uv_idle_init, Cint, (Ptr{Cvoid}, Ptr{Cvoid}), | ||
Base.eventloop(), this.handle) | ||
if err != 0 | ||
Libc.free(this.handle) | ||
this.handle = C_NULL | ||
throw(_UVError("uv_idle_init", err)) | ||
end | ||
err = ccall(:uv_idle_start, Cint, (Ptr{Cvoid}, Ptr{Cvoid}), | ||
this.handle, @cfunction(idle_callback, Cvoid, (Ptr{Cvoid},))) | ||
if err != 0 | ||
Libc.free(this.handle) | ||
this.handle = C_NULL | ||
throw(_UVError("uv_idle_start", err)) | ||
end | ||
finalizer(Base.uvfinalize, this) | ||
Base.iolock_end() | ||
return this | ||
end | ||
end | ||
Base.unsafe_convert(::Type{Ptr{Cvoid}}, idle::UvTestIdle) = idle.handle | ||
|
||
function Base.uvfinalize(t::UvTestIdle) | ||
Base.iolock_begin() | ||
Base.lock(t.cond) | ||
try | ||
if t.handle != C_NULL | ||
Base.disassociate_julia_struct(t.handle) # not going to call the usual close hooks | ||
if t.isopen | ||
t.isopen = false | ||
ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), t) | ||
end | ||
t.handle = C_NULL | ||
notify(t.cond, false) | ||
end | ||
finally | ||
unlock(t.cond) | ||
end | ||
Base.iolock_end() | ||
nothing | ||
end | ||
|
||
function Base.wait(idle::UvTestIdle) | ||
Base.iolock_begin() | ||
Base.preserve_handle(idle) | ||
Base.lock(idle.cond) | ||
try | ||
idle.active = true | ||
wait(idle.cond) | ||
finally | ||
Base.unlock(idle.cond) | ||
Base.unpreserve_handle(idle) | ||
Base.iolock_end() | ||
end | ||
end | ||
|
||
# Spawn another process as a watchdog. If this test fails, it'll unrecoverably | ||
# hang in the event loop. Another process needs to kill it | ||
cmd = """ | ||
@async (Base.wait_readnb(stdin, 1); exit()) | ||
sleep(100) | ||
isopen(stdin) || exit() | ||
println(stderr, "ERROR: Killing threads test due to watchdog expiry") | ||
ccall(:uv_kill, Cint, (Cint, Cint), $(getpid()), Base.SIGTERM) | ||
""" | ||
proc = open(pipeline(`$(Base.julia_cmd()) -e $cmd`; stderr=stderr); write=true) | ||
|
||
let idle=UvTestIdle() | ||
wait(idle) | ||
end | ||
|
||
using Base.Threads | ||
@threads for i = 1:1 | ||
let idle=UvTestIdle() | ||
wait(idle) | ||
end | ||
end | ||
|
||
@test process_running(proc) | ||
|
||
# We don't need the watchdog anymore | ||
close(proc.in) |