| ! Regression test for a race at kernel start-up. |
| |
| ! On entry to a target region, thread 0 initializes the team state in LDS |
| ! (HasThreadState = 0, ThreadStates = nullptr) inside __kmpc_target_init and |
| ! then releases the other threads with a barrier. That barrier was emitted with |
| ! `atomic::relaxed`, so the initializing LDS stores are not guaranteed to be |
| ! visible to the worker threads before they proceed. A worker could then read |
| ! uninitialized team state, which showed up as wrong results (or a crash). |
| ! |
| ! The race is timing dependent, so the proven reproducer pattern is repeated |
| ! over a large iteration space to make a bad ordering likely to surface. A |
| ! correct runtime passes every launch deterministically. |
| |
| ! REQUIRES: flang, amdgpu |
| |
| ! RUN: %libomptarget-compile-fortran-generic |
| ! RUN: %libomptarget-run-generic 2>&1 | %fcheck-generic |
| |
| module control_mod |
| implicit none |
| ! Not a parameter on purpose: a runtime `if` value is required to triggered |
| ! the failure. |
| logical :: should_offload = .true. |
| end module |
| |
| program target_teams_if_runtime_init |
| use control_mod |
| implicit none |
| integer, parameter :: n = 30000 |
| integer, parameter :: nlaunch = 50 |
| integer :: data(n) |
| integer :: i, launch, errors |
| |
| errors = 0 |
| |
| do launch = 1, nlaunch |
| data = 0 |
| |
| !$omp target enter data map(alloc: data) |
| |
| !$omp target teams distribute parallel do map(present, tofrom: data) & |
| !$omp& if(should_offload) |
| do i = 1, n |
| data(i) = i |
| end do |
| !$omp end target teams distribute parallel do |
| |
| !$omp target exit data map(from: data) |
| |
| do i = 1, n |
| if (data(i) /= i) then |
| errors = errors + 1 |
| end if |
| end do |
| end do |
| |
| print *, "number of errors: ", errors |
| |
| end program target_teams_if_runtime_init |
| |
| ! CHECK: number of errors: 0 |