https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277047
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: [email protected]
Reporter: [email protected]
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.
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.
However, atomic.o has a global lock pool, and having different lock pools would
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 same
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 = 0; i < (n); i++)
constexpr int kIterations = 500'000;
__int128_t g;
void loop_b();
void loop_a() {
REP(i, kIterations) {
for(;;) {
auto e = __atomic_load_n(&g, __ATOMIC_RELAXED), desired = 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 = 0; i < (n); i++)
extern __int128_t g;
constexpr int kIterations = 500'000;
void loop_b() {
REP(i, kIterations) {
for(;;) {
auto e = __atomic_load_n(&g, __ATOMIC_RELAXED);
auto desired = e + 1;
if (__atomic_compare_exchange_n(&g, &e, desired, 0, __ATOMIC_RELAXED,
__ATOMIC_RELAXED))
break;
}
}
}
eof
--
You are receiving this mail because:
You are the assignee for the bug.