Skip to content

Commit

Permalink
Merge pull request #455 from JuliaParallel/jps/errormonitor-spin-lock
Browse files Browse the repository at this point in the history
errormonitor_tracked: Use spin lock
  • Loading branch information
jpsamaroo authored Nov 16, 2023
2 parents 304888d + 0b695bc commit b258524
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/sch/Sch.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Base: @invokelatest
import ..Dagger
import ..Dagger: Context, Processor, Thunk, WeakThunk, ThunkFuture, ThunkFailedException, Chunk, WeakChunk, OSProc, AnyScope, DefaultScope, LockedObject
import ..Dagger: order, dependents, noffspring, istask, inputs, unwrap_weak_checked, affinity, tochunk, timespan_start, timespan_finish, procs, move, chunktype, processor, default_enabled, get_processors, get_parent, execute!, rmprocs!, addprocs!, thunk_processor, constrain, cputhreadtime
import ..Dagger: @dagdebug
import ..Dagger: @dagdebug, @safe_lock_spin1
import DataStructures: PriorityQueue, enqueue!, dequeue_pair!, peek

import ..Dagger
Expand Down
2 changes: 1 addition & 1 deletion src/sch/util.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"Like `errormonitor`, but tracks how many outstanding tasks are running."
function errormonitor_tracked(t::Task)
errormonitor(t)
lock(ERRORMONITOR_TRACKED) do tracked
@safe_lock_spin1 ERRORMONITOR_TRACKED tracked begin
push!(tracked, t)
end
errormonitor(Threads.@spawn begin
Expand Down
26 changes: 26 additions & 0 deletions src/utils/locked-object.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,29 @@ function Base.lock(f, x::LockedObject)
unlock(x.lock)
end
end
Base.trylock(x::LockedObject) = trylock(x.lock)
Base.unlock(x::LockedObject) = unlock(x.lock)
payload(x::LockedObject) = x.payload

# TODO: Move this back to MemPool
# If we actually want to acquire a lock from a finalizer, we can't cause a task
# switch. As a NonReentrantLock can only be taken by another thread that should
# be running, and not a concurrent task we'd need to switch to, we can safely
# spin.
macro safe_lock_spin1(l, o, ex)
quote
temp = $(esc(l))
while !trylock(temp)
# we can't yield here
GC.safepoint()
end
MemPool.enable_finalizers(false) # retains compatibility with non-finalizer callers
try
$(esc(o)) = $payload(temp)
$(esc(ex))
finally
unlock(temp)
MemPool.enable_finalizers(true)
end
end
end

0 comments on commit b258524

Please sign in to comment.