[Bug 277047] /usr/lib/libcompiler_rt.a(atomic.o) hidden visibility causes non-atomic atomics
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 277047] /usr/lib/libcompiler_rt.a(atomic.o) hidden visibility causes non-atomic atomics"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 277047] /usr/lib/libcompiler_rt.a(atomic.o) hidden visibility causes non-atomic atomics"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 14 Feb 2024 08:21:13 UTC
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: 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. 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.