]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
cmake: Improve test for 16-byte atomic support on IBM Z 32802/head
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Thu, 23 Jan 2020 12:07:08 +0000 (13:07 +0100)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Thu, 23 Jan 2020 12:13:58 +0000 (13:13 +0100)
Commit d1b9d14324586d02dc6c8dd0a9bdf4b98ae16416 added a check for
16-byte atomics without library support on IBM Z.  Unfortunately
it turns out this test only works correctly when the test case
is built without optimization.  (This is normally true, but it
may not be the case when passing explicit CXXFLAGS to cmake.)

The underlying reason is that GCC may choose to use either an
inline implementation of the 16-byte atomics or library calls,
depending on whether or not it is able to prove the atomic
variable is properly aligned.  At -O0 it is never able to prove
that, but at higher optimization levels it depends on the complexity
of the expression (in particular, whether GCC can track down the
definition of the underlying object).

As the test case uses a very simple expression, it may happen that
this test can be built without requiring library support, but some
of the "real" uses of atomics in Ceph code cannot.   This defeats
the whole purpose of the test at configure time.

Fixed by making the access pattern in the test more complex, so
that the test fails even at high optimization levels.

Fixes: https://tracker.ceph.com/issues/43747
Signed-off-by: Ulrich Weigand <ulrich.weigand@de.ibm.com>
cmake/modules/CheckCxxAtomic.cmake

index 68efa15314b9d9d3d27dead99b314b1f2fe49c51..f2d89cf3e0beb44e8c664a8d20e4b828edf8b86c 100644 (file)
@@ -10,18 +10,29 @@ function(check_cxx_atomics var)
     check_cxx_source_compiles("
 #include <atomic>
 #include <cstdint>
+
+#if __s390x__
+// Boost needs 16-byte atomics for tagged pointers.
+// These are implemented via inline instructions on the platform
+// if 16-byte alignment can be proven, and are delegated to libatomic
+// library routines otherwise.  Whether or not alignment is provably
+// OK for a std::atomic unfortunately depends on compiler version and
+// optimization levels, and also on the details of the expression.
+// We specifically test access via an otherwise unknown pointer here
+// to ensure we get the most complex case.  If this access can be
+// done without libatomic, then all accesses can be done.
+bool atomic16(std::atomic<unsigned __int128> *ptr)
+{
+  return *ptr != 0;
+}
+#endif
+
 int main() {
   std::atomic<uint8_t> w1;
   std::atomic<uint16_t> w2;
   std::atomic<uint32_t> w4;
   std::atomic<uint64_t> w8;
-#ifdef __s390x__
-  // Boost needs 16-byte atomics for tagged pointers.
-  std::atomic<unsigned __int128> w16;
-#else
-  #define w16 0
-#endif
-  return w1 + w2 + w4 + w8 + w16;
+  return w1 + w2 + w4 + w8;
 }
 " ${var})
 endfunction(check_cxx_atomics)