[all-commits] [llvm/llvm-project] abd72b: [OpenMP] Publish target-init team state with acq_r...
Abid Qadeer via All-commits
all-commits at lists.llvm.org
Mon Jul 13 01:58:13 PDT 2026
Branch: refs/heads/main
Home: https://github.com/llvm/llvm-project
Commit: abd72b0eb7807a98c261a6cac35a969f954a76cd
https://github.com/llvm/llvm-project/commit/abd72b0eb7807a98c261a6cac35a969f954a76cd
Author: Abid Qadeer <haqadeer at amd.com>
Date: 2026-07-13 (Mon, 13 Jul 2026)
Changed paths:
A offload/test/offloading/fortran/target-teams-if-runtime-init.f90
M openmp/device/src/Kernel.cpp
Log Message:
-----------
[OpenMP] Publish target-init team state with acq_rel barrier (#208701)
In __kmpc_target_init, thread 0 initializes the team state in LDS
(HasThreadState = 0, ThreadStates = nullptr) and then releases the other
threads with synchronize::threadsAligned(atomic::relaxed). Because the
relaxed ordering emits no memory fence, the initializing LDS stores are
not guaranteed to be visible to the worker threads before they proceed.
A worker thread can then read the uninitialized team state and produce
wrong results or crash. This is the flow that causes the race as I
understand it.
```
__kmpc_target_init (Kernel.cpp:107)
-> initializeRuntime (Kernel.cpp:38)
-> state::init (State.cpp:286)
-> TeamState.init(IsSPMD) (State.cpp:295)
-> HasThreadState = false (State.cpp:248) // <-- the value later read stale
ThreadStates = nullptr (State.cpp:296)
-> synchronize::threadsAligned(atomic::relaxed) (Kernel.cpp:115) // <-- insufficient barrier:
// relaxed emits no fence, so the state stores above are not published to the other threads
... worker threads continue past the barrier ...
__kmpc_parallel_60 (Parallelism.cpp:143)
if (OMP_UNLIKELY(!if_expr || state::HasThreadState || ...)) (Parallelism.cpp:158)
^ reads HasThreadState from LDS; a stale/unpublished value (!= 0)
diverts the worker onto the wrong (serialized) path
```
The fix changes the barrier at Kernel.cpp:115 from atomic::relaxed to
atomic::acq_rel so that the memory fences are emitted.
Reproducing the problem requires an `if` clause with a non-constant
condition on the target region. The worker's read of HasThreadState
originates from the serialized-region check in __kmpc_parallel_60. When
the `if` condition is constant (or absent), the optimizer can prove that
branch is dead and eliminates the HasThreadState load entirely, so the
race has nothing to observe. A non-constant `if` keeps if_expr, and
hence the LDS read alive, exposing the problem.
I have added a Fortran offload regression test that launches a target
region many times to make the timing-dependent race likely to surface.
Fixes https://github.com/llvm/llvm-project/issues/208698.
Assisted-by: Cursor
To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications
More information about the All-commits
mailing list