From 689c15523f4aa0ba91fc97f149abdcebb3ebb08a Mon Sep 17 00:00:00 2001 From: Adam Retter Date: Mon, 6 Jan 2020 18:39:50 +0000 Subject: [PATCH] ARM64 commits to 5.18.3 to create 5.18.4 (#6250) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * RocksDB CRC32c optimization with ARMv8 Intrinsic (#5221) Summary: 1. Add Arm linear crc32c implemtation for RocksDB. 2. Arm runtime check for crc32 Pull Request resolved: https://github.com/facebook/rocksdb/pull/5221 Differential Revision: D15013685 Pulled By: siying fbshipit-source-id: 2c2983743d26656d93f212dc7c1a3cf66a1acf12 * Support rocksdbjava aarch64 build and test (#5258) Summary: Verified with an Ampere Computing eMAG aarch64 system. Pull Request resolved: https://github.com/facebook/rocksdb/pull/5258 Differential Revision: D15807309 Pulled By: maysamyabandeh fbshipit-source-id: ab85d2fd3fe40e6094430ab0eba557b1e979510d * Cleanup the Arm64 CRC32 unused warning (#5565) Summary: When 'HAVE_ARM64_CRC' is set, the blew methods: - bool rocksdb::crc32c::isSSE42() - bool rocksdb::crc32c::isPCLMULQDQ() are defined but not used, the unused-function is raised when do rocksdb build. This patch try to cleanup these warnings by add ifndef, if it build under the HAVE_ARM64_CRC, we will not define `isSSE42` and `isPCLMULQDQ`. Pull Request resolved: https://github.com/facebook/rocksdb/pull/5565 Differential Revision: D16233654 fbshipit-source-id: c32a9dda7465dbf65f9ccafef159124db92cdffd * Fixes for building RocksJava releases on arm64v8 Summary: Pull Request resolved: https://github.com/facebook/rocksdb/pull/5674 Differential Revision: D16870338 fbshipit-source-id: c8dac644b1479fa734b491f3a8d50151772290f7 * Remove invalid comparison of va_list and nullptr (#5836) Summary: The comparison of va_list and nullptr is always False under any arch, and will raise invalid operands of types error in aarch64 env (`error: invalid operands of types ‘va_list {aka __va_list}’ and ‘std::nullptr_t’ to binary ‘operator!=’`). This patch removes this invalid assert. Closes: https://github.com/facebook/rocksdb/issues/4277 Pull Request resolved: https://github.com/facebook/rocksdb/pull/5836 Differential Revision: D17532470 fbshipit-source-id: ca98078ecbc6a9416c69de3bd6ffcfa33a0f0185 * Fix naming of library on PPC64LE (#6080) Summary: **NOTE**: This also needs to be back-ported to be 6.4.6 Fix a regression introduced in f2bf0b2 by https://github.com/facebook/rocksdb/pull/5674 whereby the compiled library would get the wrong name on PPC64LE platforms. On PPC64LE, the regression caused the library to be named `librocksdbjni-linux64.so` instead of `librocksdbjni-linux-ppc64le.so`. This PR corrects the name back to `librocksdbjni-linux-ppc64le.so` and also corrects the ordering of conditional arguments in the Makefile to match the expected order as defined in the documentation for Make. Pull Request resolved: https://github.com/facebook/rocksdb/pull/6080 Differential Revision: D18710351 fbshipit-source-id: d4db87ef378263b57de7f9edce1b7d15644cf9de Co-authored-by: Yuqi Co-authored-by: Patrick Zhang Co-authored-by: Yikun Jiang --- Makefile | 22 ++++++-- build_tools/build_detect_platform | 2 + java/crossbuild/docker-build-linux-centos.sh | 16 +++++- java/rocksjni/loggerjnicallback.cc | 1 - .../java/org/rocksdb/util/Environment.java | 6 +- .../org/rocksdb/util/EnvironmentTest.java | 18 ++++++ src.mk | 5 ++ util/crc32c.cc | 30 +++++++++- util/crc32c_arm64.cc | 56 +++++++++++++++++++ util/crc32c_arm64.h | 21 +++++++ 10 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 util/crc32c_arm64.cc create mode 100644 util/crc32c_arm64.h diff --git a/Makefile b/Makefile index 09e2cd3ea2f..98c1479c228 100644 --- a/Makefile +++ b/Makefile @@ -137,6 +137,12 @@ CFLAGS += -DHAVE_POWER8 HAVE_POWER8=1 endif +ifeq (,$(shell $(CXX) -fsyntax-only -march=armv8-a+crc -xc /dev/null 2>&1)) +CXXFLAGS += -march=armv8-a+crc +CFLAGS += -march=armv8-a+crc +ARMCRC_SOURCE=1 +endif + # if we're compiling for release, compile without debug code (-DNDEBUG) ifeq ($(DEBUG_LEVEL),0) OPT += -DNDEBUG @@ -1635,7 +1641,7 @@ JAVA_INCLUDE = -I$(JAVA_HOME)/include/ -I$(JAVA_HOME)/include/linux ifeq ($(PLATFORM), OS_SOLARIS) ARCH := $(shell isainfo -b) else ifeq ($(PLATFORM), OS_OPENBSD) - ifneq (,$(filter $(MACHINE), amd64 arm64 sparc64)) + ifneq (,$(filter amd64 ppc64 ppc64le arm64 aarch64 sparc64, $(MACHINE))) ARCH := 64 else ARCH := 32 @@ -1644,10 +1650,10 @@ else ARCH := $(shell getconf LONG_BIT) endif -ifeq (,$(findstring ppc,$(MACHINE))) - ROCKSDBJNILIB = librocksdbjni-linux$(ARCH).so +ifneq (,$(filter ppc% arm64 aarch64 sparc64, $(MACHINE))) + ROCKSDBJNILIB = librocksdbjni-linux-$(MACHINE).so else - ROCKSDBJNILIB = librocksdbjni-linux-$(MACHINE).so + ROCKSDBJNILIB = librocksdbjni-linux$(ARCH).so endif ROCKSDB_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-linux$(ARCH).jar ROCKSDB_JAR_ALL = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH).jar @@ -1849,6 +1855,14 @@ rocksdbjavastaticdockerppc64le: fi docker start -a rocksdb_linux_ppc64le-be +rocksdbjavastaticdockerarm64v8: + mkdir -p java/target + DOCKER_LINUX_ARM64V8_CONTAINER=`docker ps -aqf name=rocksdb_linux_arm64v8-be`; \ + if [ -z "$$DOCKER_LINUX_ARM64V8_CONTAINER" ]; then \ + docker container create --attach stdin --attach stdout --attach stderr --volume `pwd`:/rocksdb-host --name rocksdb_linux_arm64v8-be evolvedbinary/rocksjava:centos7_arm64v8-be /rocksdb-host/java/crossbuild/docker-build-linux-centos.sh; \ + fi + docker start -a rocksdb_linux_arm64v8-be + rocksdbjavastaticpublish: rocksdbjavastaticrelease rocksdbjavastaticpublishcentral rocksdbjavastaticpublishdocker: rocksdbjavastaticreleasedocker rocksdbjavastaticpublishcentral diff --git a/build_tools/build_detect_platform b/build_tools/build_detect_platform index f488f227901..b4ef63f66cf 100755 --- a/build_tools/build_detect_platform +++ b/build_tools/build_detect_platform @@ -527,6 +527,8 @@ if test -z "$PORTABLE"; then elif test -n "`echo $TARGET_ARCHITECTURE | grep ^arm`"; then # TODO: Handle this with approprite options. COMMON_FLAGS="$COMMON_FLAGS" + elif test -n "`echo $TARGET_ARCHITECTURE | grep ^aarch64`"; then + COMMON_FLAGS="$COMMON_FLAGS" elif [ "$TARGET_OS" == "IOS" ]; then COMMON_FLAGS="$COMMON_FLAGS" elif [ "$TARGET_OS" != "AIX" ] && [ "$TARGET_OS" != "SunOS" ]; then diff --git a/java/crossbuild/docker-build-linux-centos.sh b/java/crossbuild/docker-build-linux-centos.sh index 6353b9ea2b7..82306645f3e 100755 --- a/java/crossbuild/docker-build-linux-centos.sh +++ b/java/crossbuild/docker-build-linux-centos.sh @@ -8,11 +8,21 @@ cd /rocksdb-local # Use scl devtoolset if available (i.e. CentOS <7) if hash scl 2>/dev/null; then - scl enable devtoolset-2 'make jclean clean' - scl enable devtoolset-2 'PORTABLE=1 make -j8 rocksdbjavastatic' + if scl --list | grep -q 'devtoolset-7'; then + scl enable devtoolset-7 'make jclean clean' + scl enable devtoolset-7 'PORTABLE=1 make -j2 rocksdbjavastatic' + + elif scl --list | grep -q 'devtoolset-2'; then + scl enable devtoolset-2 'make jclean clean' + scl enable devtoolset-2 'PORTABLE=1 make -j2 rocksdbjavastatic' + + else + echo "Could not find devtoolset" + exit 1; + fi else make jclean clean - PORTABLE=1 make -j8 rocksdbjavastatic + PORTABLE=1 make -j2 rocksdbjavastatic fi cp java/target/librocksdbjni-linux*.so java/target/rocksdbjni-*-linux*.jar /rocksdb-host/java/target diff --git a/java/rocksjni/loggerjnicallback.cc b/java/rocksjni/loggerjnicallback.cc index 61571e98712..a731fdac96e 100644 --- a/java/rocksjni/loggerjnicallback.cc +++ b/java/rocksjni/loggerjnicallback.cc @@ -131,7 +131,6 @@ void LoggerJniCallback::Logv(const InfoLogLevel log_level, const char* format, } assert(format != nullptr); - assert(ap != nullptr); const std::unique_ptr msg = format_str(format, ap); // pass msg to java callback handler diff --git a/java/src/main/java/org/rocksdb/util/Environment.java b/java/src/main/java/org/rocksdb/util/Environment.java index bf005a34810..293e2113aaf 100644 --- a/java/src/main/java/org/rocksdb/util/Environment.java +++ b/java/src/main/java/org/rocksdb/util/Environment.java @@ -4,6 +4,10 @@ public class Environment { private static String OS = System.getProperty("os.name").toLowerCase(); private static String ARCH = System.getProperty("os.arch").toLowerCase(); + public static boolean isAarch64() { + return ARCH.contains("aarch64"); + } + public static boolean isPowerPC() { return ARCH.contains("ppc"); } @@ -59,7 +63,7 @@ public static String getSharedLibraryFileName(final String name) { public static String getJniLibraryName(final String name) { if (isUnix()) { final String arch = is64Bit() ? "64" : "32"; - if(isPowerPC()) { + if(isPowerPC() || isAarch64()) { return String.format("%sjni-linux-%s", name, ARCH); } else if(isS390x()) { return String.format("%sjni-linux%s", name, ARCH); diff --git a/java/src/test/java/org/rocksdb/util/EnvironmentTest.java b/java/src/test/java/org/rocksdb/util/EnvironmentTest.java index 28ee04768e9..49c8bf19a91 100644 --- a/java/src/test/java/org/rocksdb/util/EnvironmentTest.java +++ b/java/src/test/java/org/rocksdb/util/EnvironmentTest.java @@ -130,6 +130,24 @@ public void win64() { isEqualTo("librocksdbjni.dll"); } + @Test + public void aarch64() { + setEnvironmentClassFields("Linux", "aarch64"); + assertThat(Environment.isUnix()).isTrue(); + assertThat(Environment.isAarch64()).isTrue(); + assertThat(Environment.is64Bit()).isTrue(); + assertThat(Environment.getJniLibraryExtension()). + isEqualTo(".so"); + assertThat(Environment.getSharedLibraryName("rocksdb")). + isEqualTo("rocksdbjni"); + assertThat(Environment.getJniLibraryName("rocksdb")). + isEqualTo("rocksdbjni-linux-aarch64"); + assertThat(Environment.getJniLibraryFileName("rocksdb")). + isEqualTo("librocksdbjni-linux-aarch64.so"); + assertThat(Environment.getSharedLibraryFileName("rocksdb")). + isEqualTo("librocksdbjni.so"); + } + private void setEnvironmentClassFields(String osName, String osArch) { setEnvironmentClassField(OS_FIELD_NAME, osName); diff --git a/src.mk b/src.mk index 990aa2ab7a6..77215d24c2e 100644 --- a/src.mk +++ b/src.mk @@ -222,6 +222,11 @@ LIB_SOURCES = \ utilities/write_batch_with_index/write_batch_with_index.cc \ utilities/write_batch_with_index/write_batch_with_index_internal.cc \ +ifeq ($(ARMCRC_SOURCE),1) +LIB_SOURCES +=\ + util/crc32c_arm64.cc +endif + ifeq (,$(shell $(CXX) -fsyntax-only -maltivec -xc /dev/null 2>&1)) LIB_SOURCES_ASM =\ util/crc32c_ppc_asm.S diff --git a/util/crc32c.cc b/util/crc32c.cc index 9e4b65e66e1..9e838b830f5 100644 --- a/util/crc32c.cc +++ b/util/crc32c.cc @@ -18,6 +18,8 @@ #include "util/coding.h" #include "util/util.h" +#include "util/crc32c_arm64.h" + #ifdef __powerpc64__ #include "util/crc32c_ppc.h" #include "util/crc32c_ppc_constants.h" @@ -396,6 +398,8 @@ uint32_t ExtendImpl(uint32_t crc, const char* buf, size_t size) { return static_cast(l ^ 0xffffffffu); } +// Detect if ARM64 CRC or not. +#ifndef HAVE_ARM64_CRC // Detect if SS42 or not. #ifndef HAVE_POWER8 @@ -434,6 +438,7 @@ static bool isPCLMULQDQ() { } #endif // HAVE_POWER8 +#endif // HAVE_ARM64_CRC typedef uint32_t (*Function)(uint32_t, const char*, size_t); @@ -463,6 +468,11 @@ static bool isAltiVec() { } #endif +#if defined(__linux__) && defined(HAVE_ARM64_CRC) +uint32_t ExtendARMImpl(uint32_t crc, const char *buf, size_t size) { + return crc32c_arm64(crc, (const unsigned char *)buf, size); +} +#endif std::string IsFastCrc32Supported() { bool has_fast_crc = false; @@ -478,6 +488,14 @@ std::string IsFastCrc32Supported() { has_fast_crc = false; arch = "PPC"; #endif +#elif defined(__linux__) && defined(HAVE_ARM64_CRC) + if (crc32c_runtime_check()) { + has_fast_crc = true; + arch = "Arm64"; + } else { + has_fast_crc = false; + arch = "Arm64"; + } #else has_fast_crc = isSSE42(); arch = "x86"; @@ -1200,7 +1218,15 @@ uint32_t crc32c_3way(uint32_t crc, const char* buf, size_t len) { #endif //HAVE_SSE42 && HAVE_PCLMUL static inline Function Choose_Extend() { -#ifndef HAVE_POWER8 +#ifdef HAVE_POWER8 + return isAltiVec() ? ExtendPPCImpl : ExtendImpl; +#elif defined(__linux__) && defined(HAVE_ARM64_CRC) + if(crc32c_runtime_check()) { + return ExtendARMImpl; + } else { + return ExtendImpl; + } +#else if (isSSE42()) { if (isPCLMULQDQ()) { #if defined HAVE_SSE42 && defined HAVE_PCLMUL && !defined NO_THREEWAY_CRC32C @@ -1216,8 +1242,6 @@ static inline Function Choose_Extend() { else { return ExtendImpl; } -#else //HAVE_POWER8 - return isAltiVec() ? ExtendPPCImpl : ExtendImpl; #endif } diff --git a/util/crc32c_arm64.cc b/util/crc32c_arm64.cc new file mode 100644 index 00000000000..62fabe99e3c --- /dev/null +++ b/util/crc32c_arm64.cc @@ -0,0 +1,56 @@ +// Copyright (c) 2018, Arm Limited and affiliates. All rights reserved. +// This source code is licensed under both the GPLv2 (found in the +// COPYING file in the root directory) and Apache 2.0 License +// (found in the LICENSE.Apache file in the root directory). + +#include "util/crc32c_arm64.h" + +#if defined(__linux__) && defined(HAVE_ARM64_CRC) + +#include +#include +#ifndef HWCAP_CRC32 +#define HWCAP_CRC32 (1 << 7) +#endif +uint32_t crc32c_runtime_check(void) { + uint64_t auxv = getauxval(AT_HWCAP); + return (auxv & HWCAP_CRC32) != 0; +} + +uint32_t crc32c_arm64(uint32_t crc, unsigned char const *data, + unsigned len) { + const uint8_t *buf1; + const uint16_t *buf2; + const uint32_t *buf4; + const uint64_t *buf8; + + int64_t length = (int64_t)len; + + crc ^= 0xffffffff; + buf8 = (const uint64_t *)data; + while ((length -= sizeof(uint64_t)) >= 0) { + crc = __crc32cd(crc, *buf8++); + } + + /* The following is more efficient than the straight loop */ + buf4 = (const uint32_t *)buf8; + if (length & sizeof(uint32_t)) { + crc = __crc32cw(crc, *buf4++); + length -= 4; + } + + buf2 = (const uint16_t *)buf4; + if (length & sizeof(uint16_t)) { + crc = __crc32ch(crc, *buf2++); + length -= 2; + } + + buf1 = (const uint8_t *)buf2; + if (length & sizeof(uint8_t)) + crc = __crc32cb(crc, *buf1); + + crc ^= 0xffffffff; + return crc; +} + +#endif diff --git a/util/crc32c_arm64.h b/util/crc32c_arm64.h new file mode 100644 index 00000000000..0e77ecd0ef5 --- /dev/null +++ b/util/crc32c_arm64.h @@ -0,0 +1,21 @@ +// Copyright (c) 2018, Arm Limited and affiliates. All rights reserved. +// This source code is licensed under both the GPLv2 (found in the +// COPYING file in the root directory) and Apache 2.0 License +// (found in the LICENSE.Apache file in the root directory). + +#ifndef UTIL_CRC32C_ARM64_H +#define UTIL_CRC32C_ARM64_H + +#include + +#if defined(__aarch64__) || defined(__AARCH64__) +#ifdef __ARM_FEATURE_CRC32 +#define HAVE_ARM64_CRC +#include +extern uint32_t crc32c_arm64(uint32_t crc, unsigned char const *data, unsigned len); +extern uint32_t crc32c_runtime_check(void); +#endif +#endif + + +#endif