Skip to content

Commit 4d84082

Browse files
committed
Temporary fix to make sure GC while holding a lock will not dead lock.
Add tests.
1 parent 531467d commit 4d84082

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

base/locks.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ function lock!(l::TatasLock)
2323
end
2424
end
2525
ccall(:jl_cpu_pause, Void, ())
26+
# Temporary solution before we have gc transition support in codegen.
27+
# This could mess up gc state when we add codegen support.
28+
# Use these as a safe point
29+
gc_state = ccall(:jl_gc_safe_enter, Int8, ())
30+
ccall(:jl_gc_safe_leave, Void, (Int8,), gc_state)
2631
end
2732
end
2833

@@ -61,6 +66,11 @@ function lock!(l::RecursiveTatasLock)
6166
end
6267
end
6368
ccall(:jl_cpu_pause, Void, ())
69+
# Temporary solution before we have gc transition support in codegen.
70+
# This could mess up gc state when we add codegen support.
71+
# Use these as a safe point
72+
gc_state = ccall(:jl_gc_safe_enter, Int8, ())
73+
ccall(:jl_gc_safe_leave, Void, (Int8,), gc_state)
6474
end
6575
end
6676

@@ -116,7 +126,11 @@ function lock!(m::Mutex)
116126
if m.ownertid == threadid()
117127
return 0
118128
end
129+
# Temporary solution before we have gc transition support in codegen.
130+
# This could mess up gc state when we add codegen support.
131+
gc_state = ccall(:jl_gc_safe_enter, Int8, ())
119132
ccall(:uv_mutex_lock, Void, (Ptr{Void},), m.handle)
133+
ccall(:jl_gc_safe_leave, Void, (Int8,), gc_state)
120134
m.ownertid = threadid()
121135
return 0
122136
end

test/threads.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,18 @@ let lock = Threads.RecursiveSpinLock()
8383
@test unlock!(lock) == 0
8484
@test unlock!(lock) == 1
8585
end
86+
87+
# Make sure doing a GC while holding a lock doesn't cause dead lock
88+
# PR 14190. (This is only meaningful for threading)
89+
function threaded_gc_locked{LockT}(::Type{LockT})
90+
lock = LockT()
91+
@threads for i = 1:20
92+
lock!(lock)
93+
gc(false)
94+
unlock!(lock)
95+
end
96+
end
97+
98+
threaded_gc_locked(SpinLock)
99+
threaded_gc_locked(Threads.RecursiveSpinLock)
100+
threaded_gc_locked(Mutex)

0 commit comments

Comments
 (0)