diff --git a/base/task.jl b/base/task.jl index 92ceb9eea20b1..af8c2c5c302b4 100644 --- a/base/task.jl +++ b/base/task.jl @@ -412,9 +412,15 @@ end function enq_work(t::Task) (t.state == :runnable && t.queue === nothing) || error("schedule: Task not runnable") tid = Threads.threadid(t) + # Note there are three reasons a Task might be put into a sticky queue + # even if t.sticky == false: + # 1. The Task's stack is currently being used by the scheduler for a certain thread. + # 2. There is only 1 thread. + # 3. The multiq is full (can be fixed by making it growable). if t.sticky || tid != 0 || Threads.nthreads() == 1 if tid == 0 tid = Threads.threadid() + ccall(:jl_set_task_tid, Cvoid, (Any, Cint), t, tid-1) end push!(Workqueues[tid], t) else diff --git a/test/threads.jl b/test/threads.jl index db0e4c605b37d..be0481a5d72fe 100644 --- a/test/threads.jl +++ b/test/threads.jl @@ -640,3 +640,16 @@ let t = Timer(identity, 0.025, interval=0.025) close(t) end end + +# shared workqueue + +function pfib(n::Int) + if n <= 1 + return n + end + t = @task pfib(n-2) + t.sticky = false + schedule(t) + return pfib(n-1) + fetch(t)::Int +end +@test pfib(20) == 6765