Skip to content

Commit 52883ca

Browse files
authored
Hack in acquire-load of task state to fix tests (#38557)
On x86 loads have implicit acquire semantics, but the same is not true on other architectures (e.g. aarch64). We've been observing test failures on aarch64 as a result (#38555). Currently, we don't really have a good way to modify fields in an atomic way (pending #37847), so this just achieves the same thing using llvmcall to try and get the tests passing.
1 parent 3b30429 commit 52883ca

File tree

1 file changed

+14
-3
lines changed

1 file changed

+14
-3
lines changed

base/task.jl

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,21 @@ const task_state_runnable = UInt8(0)
131131
const task_state_done = UInt8(1)
132132
const task_state_failed = UInt8(2)
133133

134+
const _state_index = findfirst(==(:_state), fieldnames(Task))
135+
@eval function load_state_acquire(t)
136+
# TODO: Replace this by proper atomic operations when available
137+
@GC.preserve t llvmcall($("""
138+
%ptr = inttoptr i$(Sys.WORD_SIZE) %0 to i8*
139+
%rv = load atomic i8, i8* %ptr acquire, align 8
140+
ret i8 %rv
141+
"""), UInt8, Tuple{Ptr{UInt8}},
142+
Ptr{UInt8}(pointer_from_objref(t) + fieldoffset(Task, _state_index)))
143+
end
144+
134145
@inline function getproperty(t::Task, field::Symbol)
135146
if field === :state
136147
# TODO: this field name should be deprecated in 2.0
137-
st = getfield(t, :_state)
148+
st = load_state_acquire(t)
138149
if st === task_state_runnable
139150
return :runnable
140151
elseif st === task_state_done
@@ -177,7 +188,7 @@ julia> istaskdone(b)
177188
true
178189
```
179190
"""
180-
istaskdone(t::Task) = t._state !== task_state_runnable
191+
istaskdone(t::Task) = load_state_acquire(t) !== task_state_runnable
181192

182193
"""
183194
istaskstarted(t::Task) -> Bool
@@ -221,7 +232,7 @@ true
221232
!!! compat "Julia 1.3"
222233
This function requires at least Julia 1.3.
223234
"""
224-
istaskfailed(t::Task) = (t._state === task_state_failed)
235+
istaskfailed(t::Task) = (load_state_acquire(t) === task_state_failed)
225236

226237
Threads.threadid(t::Task) = Int(ccall(:jl_get_task_tid, Int16, (Any,), t)+1)
227238

0 commit comments

Comments
 (0)