[libcxx] r217319 - PR20546: Fix tests for compare_exchange_weak.

Dan Albert danalbert at google.com
Sat Sep 6 13:38:26 PDT 2014


Author: danalbert
Date: Sat Sep  6 15:38:25 2014
New Revision: 217319

URL: http://llvm.org/viewvc/llvm-project?rev=217319&view=rev
Log:
PR20546: Fix tests for compare_exchange_weak.

These calls are allowed to fail spuriously.

29.6.5.25:

    Remark: A weak compare-and-exchange operation may fail spuriously.
    That is, even when the contents of memory referred to by expected
    and object are equal, it may return false and store back to expected
    the same memory contents that were originally there. [ Note: This
    spurious failure enables implementation of compare and-exchange on a
    broader class of machines, e.g., load-locked store-conditional
    machines. A consequence of spurious failure is that nearly all uses
    of weak compare-and-exchange will be in a loop.

To fix this, we replace any assert() that expects
std::atomic::compare_exchange_weak() to return true with a loop. If the
call does not return true within N runs (with N currently equal to 10),
then the test fails.

http://llvm.org/bugs/show_bug.cgi?id=20546

Added:
    libcxx/trunk/test/support/cmpxchg_loop.h
Modified:
    libcxx/trunk/test/atomics/atomics.types.generic/address.pass.cpp
    libcxx/trunk/test/atomics/atomics.types.generic/bool.pass.cpp
    libcxx/trunk/test/atomics/atomics.types.generic/integral.pass.cpp
    libcxx/trunk/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp
    libcxx/trunk/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp

Modified: libcxx/trunk/test/atomics/atomics.types.generic/address.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/atomics/atomics.types.generic/address.pass.cpp?rev=217319&r1=217318&r2=217319&view=diff
==============================================================================
--- libcxx/trunk/test/atomics/atomics.types.generic/address.pass.cpp (original)
+++ libcxx/trunk/test/atomics/atomics.types.generic/address.pass.cpp Sat Sep  6 15:38:25 2014
@@ -73,6 +73,8 @@
 #include <type_traits>
 #include <cassert>
 
+#include <cmpxchg_loop.h>
+
 template <class A, class T>
 void
 do_test()
@@ -96,7 +98,7 @@ do_test()
     assert(obj.exchange(T(3), std::memory_order_relaxed) == T(2));
     assert(obj == T(3));
     T x = obj;
-    assert(obj.compare_exchange_weak(x, T(2)) == true);
+    assert(cmpxchg_weak_loop(obj, x, T(2)) == true);
     assert(obj == T(2));
     assert(x == T(3));
     assert(obj.compare_exchange_weak(x, T(1)) == false);

Modified: libcxx/trunk/test/atomics/atomics.types.generic/bool.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/atomics/atomics.types.generic/bool.pass.cpp?rev=217319&r1=217318&r2=217319&view=diff
==============================================================================
--- libcxx/trunk/test/atomics/atomics.types.generic/bool.pass.cpp (original)
+++ libcxx/trunk/test/atomics/atomics.types.generic/bool.pass.cpp Sat Sep  6 15:38:25 2014
@@ -55,6 +55,8 @@
 #include <new>
 #include <cassert>
 
+#include <cmpxchg_loop.h>
+
 int main()
 {
     {
@@ -77,7 +79,7 @@ int main()
         assert(obj.exchange(true, std::memory_order_relaxed) == false);
         assert(obj == true);
         bool x = obj;
-        assert(obj.compare_exchange_weak(x, false) == true);
+        assert(cmpxchg_weak_loop(obj, x, false) == true);
         assert(obj == false);
         assert(x == true);
         assert(obj.compare_exchange_weak(x, true,
@@ -86,9 +88,9 @@ int main()
         assert(x == false);
         obj.store(true);
         x = true;
-        assert(obj.compare_exchange_weak(x, false,
-                                         std::memory_order_seq_cst,
-                                         std::memory_order_seq_cst) == true);
+        assert(cmpxchg_weak_loop(obj, x, false,
+                                 std::memory_order_seq_cst,
+                                 std::memory_order_seq_cst) == true);
         assert(obj == false);
         assert(x == true);
         x = true;
@@ -132,7 +134,7 @@ int main()
         assert(obj.exchange(true, std::memory_order_relaxed) == false);
         assert(obj == true);
         bool x = obj;
-        assert(obj.compare_exchange_weak(x, false) == true);
+        assert(cmpxchg_weak_loop(obj, x, false) == true);
         assert(obj == false);
         assert(x == true);
         assert(obj.compare_exchange_weak(x, true,
@@ -141,9 +143,9 @@ int main()
         assert(x == false);
         obj.store(true);
         x = true;
-        assert(obj.compare_exchange_weak(x, false,
-                                         std::memory_order_seq_cst,
-                                         std::memory_order_seq_cst) == true);
+        assert(cmpxchg_weak_loop(obj, x, false,
+                                 std::memory_order_seq_cst,
+                                 std::memory_order_seq_cst) == true);
         assert(obj == false);
         assert(x == true);
         x = true;
@@ -187,7 +189,7 @@ int main()
         assert(obj.exchange(true, std::memory_order_relaxed) == false);
         assert(obj == true);
         bool x = obj;
-        assert(obj.compare_exchange_weak(x, false) == true);
+        assert(cmpxchg_weak_loop(obj, x, false) == true);
         assert(obj == false);
         assert(x == true);
         assert(obj.compare_exchange_weak(x, true,
@@ -196,9 +198,9 @@ int main()
         assert(x == false);
         obj.store(true);
         x = true;
-        assert(obj.compare_exchange_weak(x, false,
-                                         std::memory_order_seq_cst,
-                                         std::memory_order_seq_cst) == true);
+        assert(cmpxchg_weak_loop(obj, x, false,
+                                 std::memory_order_seq_cst,
+                                 std::memory_order_seq_cst) == true);
         assert(obj == false);
         assert(x == true);
         x = true;

Modified: libcxx/trunk/test/atomics/atomics.types.generic/integral.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/atomics/atomics.types.generic/integral.pass.cpp?rev=217319&r1=217318&r2=217319&view=diff
==============================================================================
--- libcxx/trunk/test/atomics/atomics.types.generic/integral.pass.cpp (original)
+++ libcxx/trunk/test/atomics/atomics.types.generic/integral.pass.cpp Sat Sep  6 15:38:25 2014
@@ -90,6 +90,8 @@
 #include <new>
 #include <cassert>
 
+#include <cmpxchg_loop.h>
+
 template <class A, class T>
 void
 do_test()
@@ -112,7 +114,7 @@ do_test()
     assert(obj.exchange(T(3), std::memory_order_relaxed) == T(2));
     assert(obj == T(3));
     T x = obj;
-    assert(obj.compare_exchange_weak(x, T(2)) == true);
+    assert(cmpxchg_weak_loop(obj, x, T(2)) == true);
     assert(obj == T(2));
     assert(x == T(3));
     assert(obj.compare_exchange_weak(x, T(1)) == false);

Modified: libcxx/trunk/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp?rev=217319&r1=217318&r2=217319&view=diff
==============================================================================
--- libcxx/trunk/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp (original)
+++ libcxx/trunk/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp Sat Sep  6 15:38:25 2014
@@ -24,6 +24,8 @@
 #include <type_traits>
 #include <cassert>
 
+#include <cmpxchg_loop.h>
+
 template <class T>
 void
 test()
@@ -33,7 +35,7 @@ test()
         A a;
         T t(T(1));
         std::atomic_init(&a, t);
-        assert(std::atomic_compare_exchange_weak(&a, &t, T(2)) == true);
+        assert(c_cmpxchg_weak_loop(&a, &t, T(2)) == true);
         assert(a == T(2));
         assert(t == T(1));
         assert(std::atomic_compare_exchange_weak(&a, &t, T(3)) == false);
@@ -45,7 +47,7 @@ test()
         volatile A a;
         T t(T(1));
         std::atomic_init(&a, t);
-        assert(std::atomic_compare_exchange_weak(&a, &t, T(2)) == true);
+        assert(c_cmpxchg_weak_loop(&a, &t, T(2)) == true);
         assert(a == T(2));
         assert(t == T(1));
         assert(std::atomic_compare_exchange_weak(&a, &t, T(3)) == false);

Modified: libcxx/trunk/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp?rev=217319&r1=217318&r2=217319&view=diff
==============================================================================
--- libcxx/trunk/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp (original)
+++ libcxx/trunk/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp Sat Sep  6 15:38:25 2014
@@ -27,6 +27,8 @@
 #include <type_traits>
 #include <cassert>
 
+#include <cmpxchg_loop.h>
+
 template <class T>
 void
 test()
@@ -36,7 +38,7 @@ test()
         A a;
         T t(T(1));
         std::atomic_init(&a, t);
-        assert(std::atomic_compare_exchange_weak_explicit(&a, &t, T(2),
+        assert(c_cmpxchg_weak_loop(&a, &t, T(2),
                std::memory_order_seq_cst, std::memory_order_seq_cst) == true);
         assert(a == T(2));
         assert(t == T(1));
@@ -50,7 +52,7 @@ test()
         volatile A a;
         T t(T(1));
         std::atomic_init(&a, t);
-        assert(std::atomic_compare_exchange_weak_explicit(&a, &t, T(2),
+        assert(c_cmpxchg_weak_loop(&a, &t, T(2),
                std::memory_order_seq_cst, std::memory_order_seq_cst) == true);
         assert(a == T(2));
         assert(t == T(1));

Added: libcxx/trunk/test/support/cmpxchg_loop.h
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/support/cmpxchg_loop.h?rev=217319&view=auto
==============================================================================
--- libcxx/trunk/test/support/cmpxchg_loop.h (added)
+++ libcxx/trunk/test/support/cmpxchg_loop.h Sat Sep  6 15:38:25 2014
@@ -0,0 +1,51 @@
+#include <atomic>
+
+template <class A, class T>
+bool cmpxchg_weak_loop(A& atomic, T& expected, T desired) {
+  for (int i = 0; i < 10; i++) {
+    if (atomic.compare_exchange_weak(expected, desired) == true) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+template <class A, class T>
+bool cmpxchg_weak_loop(A& atomic, T& expected, T desired,
+                       std::memory_order success,
+                       std::memory_order failure) {
+  for (int i = 0; i < 10; i++) {
+    if (atomic.compare_exchange_weak(expected, desired, success,
+                                     failure) == true) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+template <class A, class T>
+bool c_cmpxchg_weak_loop(A* atomic, T* expected, T desired) {
+  for (int i = 0; i < 10; i++) {
+    if (std::atomic_compare_exchange_weak(atomic, expected, desired) == true) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+template <class A, class T>
+bool c_cmpxchg_weak_loop(A* atomic, T* expected, T desired,
+                         std::memory_order success,
+                         std::memory_order failure) {
+  for (int i = 0; i < 10; i++) {
+    if (std::atomic_compare_exchange_weak_explicit(atomic, expected, desired,
+                                                   success, failure) == true) {
+      return true;
+    }
+  }
+
+  return false;
+}





More information about the cfe-commits mailing list