diff --git a/base/lock.jl b/base/lock.jl index 461cb2b12a807..e47e03c2bd1fa 100644 --- a/base/lock.jl +++ b/base/lock.jl @@ -797,7 +797,7 @@ end # share a lock/condition, since we just need it briefly, so some contention is okay -const PerThreadLock = ThreadSynchronizer() +const PerThreadLock = Threads.SpinLock() """ OncePerThread{T}(init::Function)() -> T @@ -901,7 +901,15 @@ OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof( state = @atomic :monotonic ss[tid] while state == PerStateConcurrent # lost race, wait for notification this is done running elsewhere - wait(PerThreadLock) # wait for initializer to finish without releasing this thread + # without releasing this thread + unlock(PerThreadLock) + while state == PerStateConcurrent + # spin loop until ready + ss = @atomic :acquire once.ss + state = @atomic :monotonic ss[tid] + GC.safepoint() + end + lock(PerThreadLock) ss = @atomic :monotonic once.ss state = @atomic :monotonic ss[tid] end @@ -915,7 +923,6 @@ OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof( lock(PerThreadLock) ss = @atomic :monotonic once.ss @atomic :release ss[tid] = PerStateErrored - notify(PerThreadLock) rethrow() end # store result and notify waiters @@ -924,7 +931,6 @@ OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof( @atomic :release xs[tid] = result ss = @atomic :monotonic once.ss @atomic :release ss[tid] = PerStateHasrun - notify(PerThreadLock) elseif state == PerStateErrored error("OncePerThread initializer failed previously") elseif state != PerStateHasrun