Files
Yuta Mukai ce68f28703 [OpenMP][libomp] Fix dist barrier arrival synchronization (#213845)
Make distributedBarrier::stillNeed atomic and use release/acquire
ordering for distributed barrier gather arrival flags.

The old volatile stillNeed flag did not synchronize an arriving thread's
pre-barrier writes with the thread that observed its arrival. On weakly
ordered architectures, a group leader could observe stillNeed == 0
before the arriving thread's pre-barrier writes were visible. This
allowed another thread to pass the barrier and read stale data written
before the barrier.

Use release stores when publishing stillNeed == 0. Keep the spin loops
on relaxed loads, then perform one acquire fence after all expected zero
values have been observed. This connects the arriving threads'
pre-barrier writes to the observer through the standard release/acquire
happens-before chain, without using acquire loads on every poll.

The same pattern is used when a group leader publishes its own stillNeed
== 0 after the in-group gather completes. The existing go-flag
release/acquire path then carries the ordering to threads leaving the
barrier.

Initialization and next-iteration reset stores remain relaxed because
they do not publish pre-barrier data.

On x86, this does not change the generated instruction sequence for the
affected stillNeed polling/arrival code, since TSO already provides the
needed ordering for ordinary loads and stores.

Reproducer:

I used the following stress test to reproduce the distributed-barrier
visibility issue on AArch64 (Grace).

`test.c`:

```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>

int main() {
  int nt;
#pragma omp parallel
#pragma omp master
  nt = omp_get_num_threads();

  int n = 1024;
  int *p = aligned_alloc(64, nt * n * sizeof(int));
  memset(p, 0, nt * n * sizeof(int));

#pragma omp parallel
  {
    int t = omp_get_thread_num();
    int *pt = p + t * n;
    int *pt2 = p + ((t + 1) % nt) * n;

    for (int it = 1; it <= 100000; it++) {
      for (int i = 0; i < n; i++)
        pt[i] = it;

#pragma omp barrier

      for (int i = 0; i < n; i++) {
        if (pt2[i] != it) {
          printf("thread #%d observes pt2[%d] != %d\n", t, i, it);
          abort();
        }
      }

#pragma omp barrier
    }
  }

  printf("ok\n");
  return 0;
}
```

`noise.c`:

```c
// background memory-bandwidth noise
#include <stdlib.h>
#include <omp.h>

int main() {
  long N = 1024L*1024;

#pragma omp parallel
  {
    long *b = malloc(sizeof(long)*N);

    for (long j=0; j<1000; j++)
      for (long i = 0; i < N; i += 8)
        b[i] += 1;
  }
  return 0;
}
```

Build and run:

```bash
clang test.c -O -fopenmp -o test
clang noise.c -O -fopenmp -o noise

./noise &

KMP_PLAIN_BARRIER_PATTERN=dist,dist \
KMP_FORKJOIN_BARRIER_PATTERN=dist,dist \
KMP_REDUCTION_BARRIER_PATTERN=dist,dist \
OMP_NUM_THREADS=10 \
./test
```

With the old runtime, this can fail as follows:

```text
thread #5 observes pt2[112] != 343
Aborted (core dumped)
```

The same test passes with the patched runtime.

(cherry picked from commit 0fa6182e280d36dc73472f9a79dcb1b82d548893)
2026-09-05 09:12:01 +02:00
..

               README for the LLVM* OpenMP* Runtime Library
               ============================================

How to Build Documentation
==========================

The main documentation is in Doxygen* format, and this distribution
should come with pre-built PDF documentation in doc/Reference.pdf.
However, an HTML version can be built by executing:

% doxygen doc/doxygen/config

in the runtime directory.

That will produce HTML documentation in the doc/doxygen/generated
directory, which can be accessed by pointing a web browser at the
index.html file there.

If you don't have Doxygen installed, you can download it from
www.doxygen.org.


How to Build the LLVM* OpenMP* Runtime Library
==============================================

For build instructions, please see https://openmp.llvm.org/Building.html.


Architectures Supported
=======================
* IA-32 architecture
* Intel(R) 64 architecture
* Intel(R) Many Integrated Core Architecture
* ARM* architecture
* Aarch64 (64-bit ARM) architecture
* IBM(R) Power architecture (big endian)
* IBM(R) Power architecture (little endian)
* IBM(R) Z (s390x) architecture
* MIPS and MIPS64 architecture
* RISCV64 architecture
* LoongArch64 architecture

Supported RTL Build Configurations
==================================

Supported Architectures: IA-32 architecture, Intel(R) 64, and
Intel(R) Many Integrated Core Architecture

              ----------------------------------------------
              |   icc/icl     |    gcc      |   clang      |
--------------|---------------|----------------------------|
| Linux* OS   |   Yes(1,5)    |  Yes(2,4)   | Yes(4,6,7)   |
| FreeBSD*    |   No          |  No         | Yes(4,6,7,8) |
| OS X*       |   Yes(1,3,4)  |  No         | Yes(4,6,7)   |
| Windows* OS |   Yes(1,4)    |  No         | No           |
------------------------------------------------------------

(1) On IA-32 architecture and Intel(R) 64, icc/icl versions 12.x are
    supported (12.1 is recommended).
(2) GCC* version 4.7 is supported.
(3) For icc on OS X*, OS X* version 10.5.8 is supported.
(4) Intel(R) Many Integrated Core Architecture not supported.
(5) On Intel(R) Many Integrated Core Architecture, icc/icl versions 13.0
    or later are required.
(6) Clang* version 3.3 is supported.
(7) Clang* currently does not offer a software-implemented 128 bit extended
    precision type.  Thus, all entry points reliant on this type are removed
    from the library and cannot be called in the user program.  The following
    functions are not available:
    __kmpc_atomic_cmplx16_*
    __kmpc_atomic_float16_*
    __kmpc_atomic_*_fp
(8) Community contribution provided AS IS, not tested by Intel.

Supported Architectures: IBM(R) Power 7 and Power 8

              -----------------------------
              |   gcc      |   clang      |
--------------|------------|--------------|
| Linux* OS   |  Yes(1,2)  | Yes(3,4)     |
-------------------------------------------

(1) On Power 7, gcc version 4.8.2 is supported.
(2) On Power 8, gcc version 4.8.2 is supported.
(3) On Power 7, clang version 3.7 is supported.
(4) On Power 8, clang version 3.7 is supported.


Front-end Compilers that work with this RTL
===========================================

The following compilers are known to do compatible code generation for
this RTL: clang (from the OpenMP development branch at
http://clang-omp.github.io/ ), Intel compilers, GCC.  See the documentation
for more details.

-----------------------------------------------------------------------

Notices
=======

*Other names and brands may be claimed as the property of others.