Skip to content

Commit

Permalink
fix JuliaLang#34415, remove affinity setting code (JuliaLang#34433)
Browse files Browse the repository at this point in the history
This was removed before and added back apparently by mistake.

(cherry picked from commit 5928786)
  • Loading branch information
JeffBezanson authored and BioTurboNick committed Apr 13, 2020
1 parent 9472d72 commit 490d5e6
Showing 1 changed file with 131 additions and 131 deletions.
262 changes: 131 additions & 131 deletions test/threads.jl
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)

0 comments on commit 490d5e6

Please sign in to comment.