Skip to content

Commit

Permalink
Make locking logic task-based instead of thread-based.
Browse files Browse the repository at this point in the history
Locking relied on tasks not being migrated between threads; we
now associate the lock status with the locking task.
  • Loading branch information
rbehrends committed Aug 5, 2020
1 parent 48ed5e3 commit 8dfd851
Showing 1 changed file with 21 additions and 13 deletions.
34 changes: 21 additions & 13 deletions src/sync.jl
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
module Sync
mutable struct LockStatus
nested :: Int
owner :: Union{Task, Nothing}
end

const mutex = ReentrantLock()
const sync_level = repeat([ 0 ], Threads.nthreads())
const lock_status = LockStatus(0, nothing)

@inline is_locked() = sync_level[Threads.threadid()] > 0
@inline is_locked() = lock_status.owner == Base.current_task()

@inline function lock()
tid = Threads.threadid()
if sync_level[tid] == 0
Base.lock(mutex)
end
sync_level[tid] += 1
if is_locked()
lock_status.nested += 1
else
Base.lock(mutex)
lock_status.nested = 1
lock_status.owner = Base.current_task()
end
end

@inline function unlock()
tid = Threads.threadid()
sync_level[tid] -= 1
if sync_level[tid] == 0
Base.unlock(mutex)
end
@assert is_locked()
lock_status.nested -= 1
if lock_status.nested == 0
lock_status.owner = nothing
Base.unlock(mutex)
end
end

@inline function check_lock()
assert(is_locked())
@assert is_locked()
end
end

Expand Down

0 comments on commit 8dfd851

Please sign in to comment.