Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 Feb 2024 08:21:13 +0000
From:      bugzilla-noreply@freebsd.org
To:        bugs@FreeBSD.org
Subject:   [Bug 277047] /usr/lib/libcompiler_rt.a(atomic.o) hidden visibility causes non-atomic atomics
Message-ID:  <bug-277047-227@https.bugs.freebsd.org/bugzilla/>

next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D277047

            Bug ID: 277047
           Summary: /usr/lib/libcompiler_rt.a(atomic.o) hidden visibility
                    causes non-atomic atomics
           Product: Base System
           Version: Unspecified
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: misc
          Assignee: bugs@FreeBSD.org
          Reporter: i@maskray.me

lib/libcompiler_rt/ builds llvm-project/compiler-rt including atomics (for =
arm
there is additional sys/arm/arm/stdatomic.c).
Many packages have a dependency on lib/libcompiler_rt. lib/libcompiler_rt is
installed to /usr/lib/libcompiler_rt.a.=20
The symbols are hidden, which usually lead to benign ODR violations if both=
 an
executable and its DT_NEEDED get a copy of libcompiler_rt.a.=20

However, atomic.o has a global lock pool, and having different lock pools w=
ould
lead to non-synchronized atomic operations.

Prepare input files as attached at the end of this post.

% zsh a.sh
/tmp/b-9aaa82.o: reference to __atomic_compare_exchange
/usr/lib/libcompiler_rt.a(atomic.o): definition of __atomic_compare_exchange
/tmp/a-864004.o: reference to __atomic_compare_exchange
/usr/lib/libcompiler_rt.a(atomic.o): definition of __atomic_compare_exchange
9470401
/tmp/b-28139a.o: reference to __atomic_compare_exchange
/usr/lib/libgcc.a(atomic.o): definition of __atomic_compare_exchange
/tmp/a-1dceb9.o: reference to __atomic_compare_exchange
/usr/lib/libgcc.a(atomic.o): definition of __atomic_compare_exchange
9481088

The expected result is 10000000. libgcc.a has the same issue.
In practice it is extremely rare when two pieces of code operating on the s=
ame
atomic lives in different link units.

---

cat > a.cc <<'eof'
#include <cstdint>
#include <iostream>
#include <thread>
#include <vector>
using namespace std;

#define REP(i, n) for (int i =3D 0; i < (n); i++)

constexpr int kIterations =3D 500'000;
__int128_t g;

void loop_b();
void loop_a() {
  REP(i, kIterations) {
    for(;;) {
      auto e =3D __atomic_load_n(&g, __ATOMIC_RELAXED), desired =3D e+1;
      if (__atomic_compare_exchange_n(&g, &e, desired, 0, __ATOMIC_RELAXED,
__ATOMIC_RELAXED))
        break;
    }
  }
}

int main() {
  vector<thread> ts;
  REP(i, 10) ts.emplace_back(loop_a), ts.emplace_back(loop_b);
  for (auto &t : ts) t.join();
  cout << (int64_t)g << '\n';
}
eof
cat > a.sh <<'eof'
clang++ -O1 -fpic -Wno-atomic-alignment b.cc -shared -lcompiler_rt -o b.so
-Wl,-y,__atomic_compare_exchange
clang++ -O1 -Wno-atomic-alignment a.cc ./b.so -lcompiler_rt -pthread -o a
-Wl,-y,__atomic_compare_exchange
./a

clang++ -O1 -fpic -Wno-atomic-alignment b.cc -shared -o b.gcc.so
-Wl,-y,__atomic_compare_exchange
clang++ -O1 -Wno-atomic-alignment a.cc ./b.gcc.so -pthread -o a.gcc
-Wl,-y,__atomic_compare_exchange
./a.gcc
eof
cat > b.cc <<'eof'
#define REP(i, n) for (int i =3D 0; i < (n); i++)
extern __int128_t g;
constexpr int kIterations =3D 500'000;
void loop_b() {
  REP(i, kIterations) {
    for(;;) {
      auto e =3D __atomic_load_n(&g, __ATOMIC_RELAXED);
      auto desired =3D e + 1;
      if (__atomic_compare_exchange_n(&g, &e, desired, 0, __ATOMIC_RELAXED,
__ATOMIC_RELAXED))
        break;
    }
  }
}
eof

--=20
You are receiving this mail because:
You are the assignee for the bug.=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-277047-227>