]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
cmake: check for unaligned access 28936/head
authorKefu Chai <kchai@redhat.com>
Tue, 9 Jul 2019 07:27:59 +0000 (15:27 +0800)
committerKefu Chai <kchai@redhat.com>
Wed, 11 Sep 2019 04:47:26 +0000 (12:47 +0800)
C and C++ allow us to cast a pointer with an alignment requirement to
one with a different alignment requirement. but if the destination
type's alignment is greater/stricter than the source type, the behavior
is undefined. on amd64, it's allowed. and on aarch64, GCC offers an
option named `-munaligned-access` to enable this behavior. so we cannot
take this as guaranteed.

in denc.h and messenger implementations, we just cast the pointers to
the type we want to access without memcpy(), which is, strictly
speaking, not quite standard compliant.

so, to be on the safe side, we detect the support of unaligned access at
compile time.

please note, this would fail the cross-compile. as the target platform
might not support unaligned access, and the produced executable does not
run on the build platform. so this test is skipped if the building
host's architecture is different than that of target host.

Signed-off-by: Kefu Chai <kchai@redhat.com>
cmake/modules/CephChecks.cmake

index 642d35eaa8935a65e459c915d441b22beee8da5c..f6dd41cf10555e01e4df056439f23b478bd05e8e 100644 (file)
@@ -89,3 +89,49 @@ CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec sys/stat.h
   HAVE_STAT_ST_MTIM_TV_NSEC LANGUAGE C)
 CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec sys/stat.h
   HAVE_STAT_ST_MTIMESPEC_TV_NSEC LANGUAGE C)
+
+if(CMAKE_SYSTEM_PROCESSOR STREQUAL CMAKE_HOST_SYSTEM_PROCESSOR)
+  include(CheckCXXSourceRuns)
+  cmake_push_check_state()
+  set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++17")
+  check_cxx_source_runs("
+#include <cstdint>
+#include <iterator>
+#include <arpa/inet.h>
+
+uint32_t load(char* p, size_t offset)
+{
+  return *reinterpret_cast<uint32_t*>(p + offset);
+}
+
+bool good(uint32_t lhs, uint32_t small_endian)
+{
+  uint32_t rhs;
+  if (ntohl(0xdeadbeaf) == 0xdeadbeaf) {
+    return lhs == ntohl(small_endian);
+  } else {
+    return lhs == small_endian;
+  }
+}
+
+int main(int argc, char **argv)
+{
+  char a1[] = \"ABCDEFG\";
+  uint32_t a2[] = {0x44434241,
+                   0x45444342,
+                   0x46454443,
+                   0x47464544};
+  for (size_t i = 0; i < std::size(a2); i++) {
+    if (!good(load(a1, i), a2[i])) {
+      return 1;
+    }
+  }
+}"
+    HAVE_UNALIGNED_ACCESS)
+  cmake_pop_check_state()
+  if(NOT HAVE_UNALIGNED_ACCESS)
+    message(FATAL_ERROR "Unaligned access is required")
+  endif()
+else(CMAKE_SYSTEM_PROCESSOR STREQUAL CMAKE_HOST_SYSTEM_PROCESSOR)
+  message(STATUS "Assuming unaligned access is supported")
+endif(CMAKE_SYSTEM_PROCESSOR STREQUAL CMAKE_HOST_SYSTEM_PROCESSOR)