<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - [ARM] Possible race condition in std::atomic_compare_exchange_strong"
   href="https://llvm.org/bugs/show_bug.cgi?id=30445">30445</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[ARM] Possible race condition in std::atomic_compare_exchange_strong
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libc++
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>Other
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>All Bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>renato.golin@linaro.org
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org, mclow.lists@gmail.com
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>The tests for atomic_compare_exchange_strong may be exhibiting a race
condition.

Source:
<a href="http://buildmaster.tcwglab.linaro.org/builders/libcxx-libcxxabi-libunwind-arm-linux">http://buildmaster.tcwglab.linaro.org/builders/libcxx-libcxxabi-libunwind-arm-linux</a>

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>}</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>