Skip to content

Commit

Permalink
Add support for ARM64 darwin (#43)
Browse files Browse the repository at this point in the history
* Rename linux specific functions and file.
* Use sysctlbyname to get ARM64 CRC32 instruction
  availability.
* Tested on ARM64 macOS machine. This might also
  work on iOS (untested!)
  • Loading branch information
hjmallon authored Sep 17, 2020
1 parent 3bb959c commit 1f85030
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 20 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ Google Inc.
Fangming Fang <Fangming.Fang@arm.com>
Vadim Skipin <vadim.skipin@gmail.com>
Rodrigo Tobar <rtobar@icrar.org>
Harry Mallon <hjmallon@gmail.com>
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ target_sources(crc32c
PRIVATE
"${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
"src/crc32c_arm64.h"
"src/crc32c_arm64_linux_check.h"
"src/crc32c_arm64_check.h"
"src/crc32c_internal.h"
"src/crc32c_portable.cc"
"src/crc32c_prefetch.h"
Expand Down
6 changes: 3 additions & 3 deletions src/crc32c.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <cstdint>

#include "./crc32c_arm64.h"
#include "./crc32c_arm64_linux_check.h"
#include "./crc32c_arm64_check.h"
#include "./crc32c_internal.h"
#include "./crc32c_sse42.h"
#include "./crc32c_sse42_check.h"
Expand All @@ -20,8 +20,8 @@ uint32_t Extend(uint32_t crc, const uint8_t* data, size_t count) {
static bool can_use_sse42 = CanUseSse42();
if (can_use_sse42) return ExtendSse42(crc, data, count);
#elif HAVE_ARM64_CRC32C
static bool can_use_arm_linux = CanUseArm64Linux();
if (can_use_arm_linux) return ExtendArm64(crc, data, count);
static bool can_use_arm64_crc32 = CanUseArm64Crc32();
if (can_use_arm64_crc32) return ExtendArm64(crc, data, count);
#endif // HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))

return ExtendPortable(crc, data, count);
Expand Down
8 changes: 4 additions & 4 deletions src/crc32c_arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

// Linux-specific code checking the availability for ARM CRC32C instructions.
// ARM-specific code

#ifndef CRC32C_CRC32C_ARM_LINUX_H_
#define CRC32C_CRC32C_ARM_LINUX_H_
#ifndef CRC32C_CRC32C_ARM_H_
#define CRC32C_CRC32C_ARM_H_

#include <cstddef>
#include <cstdint>
Expand All @@ -22,4 +22,4 @@ uint32_t ExtendArm64(uint32_t crc, const uint8_t* data, size_t count);

#endif // HAVE_ARM64_CRC32C

#endif // CRC32C_CRC32C_ARM_LINUX_H_
#endif // CRC32C_CRC32C_ARM_H_
26 changes: 18 additions & 8 deletions src/crc32c_arm64_linux_check.h → src/crc32c_arm64_check.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

// ARM Linux-specific code checking for the availability of CRC32C instructions.
// ARM-specific code checking for the availability of CRC32C instructions.

#ifndef CRC32C_CRC32C_ARM_LINUX_CHECK_H_
#define CRC32C_CRC32C_ARM_LINUX_CHECK_H_

// X86-specific code checking for the availability of SSE4.2 instructions.
#ifndef CRC32C_CRC32C_ARM_CHECK_H_
#define CRC32C_CRC32C_ARM_CHECK_H_

#include <cstddef>
#include <cstdint>
Expand All @@ -16,6 +14,7 @@

#if HAVE_ARM64_CRC32C

#ifdef __linux__
#if HAVE_STRONG_GETAUXVAL
#include <sys/auxv.h>
#elif HAVE_WEAK_GETAUXVAL
Expand All @@ -25,17 +24,28 @@ extern "C" unsigned long getauxval(unsigned long type) __attribute__((weak));

#define AT_HWCAP 16
#endif // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL
#endif // defined (__linux__)

#ifdef __APPLE__
#include <sys/types.h>
#include <sys/sysctl.h>
#endif // defined (__APPLE__)

namespace crc32c {

inline bool CanUseArm64Linux() {
#if HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL
inline bool CanUseArm64Crc32() {
#if defined (__linux__) && (HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL)
// From 'arch/arm64/include/uapi/asm/hwcap.h' in Linux kernel source code.
constexpr unsigned long kHWCAP_PMULL = 1 << 4;
constexpr unsigned long kHWCAP_CRC32 = 1 << 7;
unsigned long hwcap = (&getauxval != nullptr) ? getauxval(AT_HWCAP) : 0;
return (hwcap & (kHWCAP_PMULL | kHWCAP_CRC32)) ==
(kHWCAP_PMULL | kHWCAP_CRC32);
#elif defined(__APPLE__)
int val = 0;
size_t len = sizeof(val);
return sysctlbyname("hw.optional.armv8_crc32", &val, &len, nullptr, 0) == 0
&& val != 0;
#else
return false;
#endif // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL
Expand All @@ -45,4 +55,4 @@ inline bool CanUseArm64Linux() {

#endif // HAVE_ARM64_CRC32C

#endif // CRC32C_CRC32C_ARM_LINUX_CHECK_H_
#endif // CRC32C_CRC32C_ARM_CHECK_H_
8 changes: 4 additions & 4 deletions src/crc32c_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#endif // CRC32C_TESTS_BUILT_WITH_GLOG

#include "./crc32c_arm64.h"
#include "./crc32c_arm64_linux_check.h"
#include "./crc32c_arm64_check.h"
#include "./crc32c_internal.h"
#include "./crc32c_sse42.h"
#include "./crc32c_sse42_check.h"
Expand Down Expand Up @@ -56,8 +56,8 @@ BENCHMARK_REGISTER_F(CRC32CBenchmark, Portable)

#if HAVE_ARM64_CRC32C

BENCHMARK_DEFINE_F(CRC32CBenchmark, ArmLinux)(benchmark::State& state) {
if (!crc32c::CanUseArm64Linux()) {
BENCHMARK_DEFINE_F(CRC32CBenchmark, ArmCRC32C)(benchmark::State& state) {
if (!crc32c::CanUseArm64Crc32()) {
state.SkipWithError("ARM CRC32C instructions not available or not enabled");
return;
}
Expand All @@ -67,7 +67,7 @@ BENCHMARK_DEFINE_F(CRC32CBenchmark, ArmLinux)(benchmark::State& state) {
crc = crc32c::ExtendArm64(crc, block_buffer_, block_size_);
state.SetBytesProcessed(state.iterations() * block_size_);
}
BENCHMARK_REGISTER_F(CRC32CBenchmark, ArmLinux)
BENCHMARK_REGISTER_F(CRC32CBenchmark, ArmCRC32C)
->RangeMultiplier(16)
->Range(256, 16777216); // Block size.

Expand Down

0 comments on commit 1f85030

Please sign in to comment.