https://llvm.org/bugs/show_bug.cgi?id=30445
Bug ID: 30445 Summary: [ARM] Possible race condition in std::atomic_compare_exchange_strong Product: libc++ Version: unspecified Hardware: Other OS: Linux Status: NEW Severity: normal Priority: P Component: All Bugs Assignee: unassignedclangb...@nondot.org Reporter: renato.go...@linaro.org CC: llvm-bugs@lists.llvm.org, mclow.li...@gmail.com Classification: Unclassified The tests for atomic_compare_exchange_strong may be exhibiting a race condition. Source: http://buildmaster.tcwglab.linaro.org/builders/libcxx-libcxxabi-libunwind-arm-linux Environment: ARMv7 Cortex-A15 Ubuntu Xenial 16.04.2 gcc version 5.4.0 20160609 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.2) GNU ld (GNU Binutils for Ubuntu) 2.26.1 ldd (Ubuntu GLIBC 2.23-0ubuntu3) 2.23 The same tests pass on our production bot: ARMv7 Cortex-A15 Ubuntu Trusty 14.04 gcc version 4.8.2 (Ubuntu/Linaro 4.8.2-19ubuntu1) GNU ld (GNU Binutils for Ubuntu) 2.24 ldd (Ubuntu EGLIBC 2.19-0ubuntu6.3) 2.19 I'm building in the *exact* same configuration (our master is a mirror). I have tested it on two different boards (Chromebooks and Jetson TK1s) with Xenial and the problem is consistent on both with Xenial and neither with Trusty. When I run the tests directly, I get an assert like this: atomic_compare_exchange_strong.pass.cpp:41: void TestFn<long long>::operator()() const [T = long long]: Assertion `a == T(2)' failed. The code is: { typedef std::atomic<T> A; A a; T t(T(1)); std::atomic_init(&a, t); assert(std::atomic_compare_exchange_strong(&a, &t, T(2)) == true); assert(a == T(2)); assert(t == T(1)); assert(std::atomic_compare_exchange_strong(&a, &t, T(3)) == false); assert(a == T(2)); assert(t == T(2)); } The first exchange does the right thing, compare, they're equal, copies T(2) into `a`, then the asserts are correct. The second exchange, however, produce `false` (as expected), but now `a` has the value of 3, which is completely unexpected. It shouldn't be writing onto `a` at all! In GDB, when I run get a stack trace, it prints `__a_ = 3`, but when I then set a breakpoint on that line, it keeps repeating (as if looping over, may be the test harness), and always producing the correct, expected results. For completeness, here's the stack trace: Program received signal SIGABRT, Aborted. __libc_do_syscall () at ../sysdeps/unix/sysv/linux/arm/libc-do-syscall.S:47 47 ../sysdeps/unix/sysv/linux/arm/libc-do-syscall.S: No such file or directory. (gdb) bt #0 __libc_do_syscall () at ../sysdeps/unix/sysv/linux/arm/libc-do-syscall.S:47 #1 0xb6d76638 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54 #2 0xb6d7733a in __GI_abort () at abort.c:89 #3 0xb6d719b2 in __assert_fail_base (fmt=0x1 <error: Cannot access memory at address 0x1>, assertion=0x2a0d8 "a == T(2)", assertion@entry=0x2 <error: Cannot access memory at address 0x2>, file=file@entry=0xb6ff3340 "", line=41, line@entry=3068375168, function=function@entry=0x2a30f "void TestFn<long long>::operator()() const [T = long long]") at assert.c:92 #4 0xb6d71a4a in __GI___assert_fail (assertion=0x2 <error: Cannot access memory at address 0x2>, file=0xb6ff3340 "", line=3068375168, function=0x2a30f "void TestFn<long long>::operator()() const [T = long long]") at assert.c:101 #5 0x000239f0 in TestFn<long long>::operator() (this=0xbefff1fc) at /home/linaro/devel/llvm/worktree/repos/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp:41 #6 0x00010700 in TestEachIntegralType<TestFn>::operator() (this=0xbefff240) at /home/linaro/devel/llvm/worktree/repos/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_helpers.h:39 #7 0x0001067c in TestEachAtomicType<TestFn>::operator() (this=0xbefff254) at /home/linaro/devel/llvm/worktree/repos/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_helpers.h:60 #8 0x00010654 in main () at /home/linaro/devel/llvm/worktree/repos/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp:61 (gdb) f 5 #5 0x000239f0 in TestFn<long long>::operator() (this=0xbefff1fc) at /home/linaro/devel/llvm/worktree/repos/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp:41 41 assert(a == T(2)); (gdb) p a $1 = {<std::__1::__atomic_base<long long, true>> = {<std::__1::__atomic_base<long long, false>> = {__a_ = 3, static is_always_lock_free = <optimized out>}, <No data fields>}, <No data fields>} -- You are receiving this mail because: You are on the CC list for the bug.
_______________________________________________ llvm-bugs mailing list llvm-bugs@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs