Skip to content

Commit 6420885

Browse files
vtjnashtkf
andauthored
task: schedule sticky tasks correctly with _wait2 (#42750)
The `_wait2` function is similar to calling `schedule + wait` from another `@async` task, but optimized, so we want to observe the same side-effects of making the task sticky to the correct thread (and not accidentally making it sticky to the later task that handles the event). Refs #41334 (75858d7) Co-authored-by: Takafumi Arakaki <aka.tkf@gmail.com>
1 parent af56fc8 commit 6420885

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

base/condition.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,17 @@ function _wait2(c::GenericCondition, waiter::Task)
8282
ct = current_task()
8383
assert_havelock(c)
8484
push!(c.waitq, waiter)
85+
# since _wait2 is similar to schedule, we should observe the sticky bit now
86+
if waiter.sticky && Threads.threadid(waiter) == 0
87+
# Issue #41324
88+
# t.sticky && tid == 0 is a task that needs to be co-scheduled with
89+
# the parent task. If the parent (current_task) is not sticky we must
90+
# set it to be sticky.
91+
# XXX: Ideally we would be able to unset this
92+
ct.sticky = true
93+
tid = Threads.threadid()
94+
ccall(:jl_set_task_tid, Cvoid, (Any, Cint), waiter, tid-1)
95+
end
8596
return
8697
end
8798

base/task.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,18 @@ function _wait2(t::Task, waiter::Task)
306306
if !istaskdone(t)
307307
push!(t.donenotify.waitq, waiter)
308308
unlock(t.donenotify)
309+
# since _wait2 is similar to schedule, we should observe the sticky
310+
# bit, even if we aren't calling `schedule` due to this early-return
311+
if waiter.sticky && Threads.threadid(waiter) == 0
312+
# Issue #41324
313+
# t.sticky && tid == 0 is a task that needs to be co-scheduled with
314+
# the parent task. If the parent (current_task) is not sticky we must
315+
# set it to be sticky.
316+
# XXX: Ideally we would be able to unset this
317+
current_task().sticky = true
318+
tid = Threads.threadid()
319+
ccall(:jl_set_task_tid, Cvoid, (Any, Cint), waiter, tid-1)
320+
end
309321
return nothing
310322
else
311323
unlock(t.donenotify)
@@ -455,6 +467,7 @@ function errormonitor(t::Task)
455467
end
456468
nothing
457469
end
470+
t2.sticky = false
458471
_wait2(t, t2)
459472
return t
460473
end

0 commit comments

Comments
 (0)