From 77cfbfd250a690978a3b81d364054039467ed549 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 16 Jun 2017 19:30:24 -0400 Subject: [PATCH] crc32: move helper functions out of port_posix_sse.cc As this file is compiled with sse42 flags, it's possible that the feature discovery ends up using an unsupported runtime flag. Fix this by adding HasAcceleratedCRC32C to the port api, and requiring that it be checked before using AcceleratedCRC32C. --- port/port_example.h | 4 ++++ port/port_posix.cc | 14 ++++++++++++++ port/port_posix.h | 1 + port/port_posix_sse.cc | 19 ------------------- util/crc32c.cc | 4 ++++ 5 files changed, 23 insertions(+), 19 deletions(-) diff --git a/port/port_example.h b/port/port_example.h index 97bd669a5ed6cd..5b1d027de556eb 100644 --- a/port/port_example.h +++ b/port/port_example.h @@ -129,6 +129,10 @@ extern bool Snappy_Uncompress(const char* input_data, size_t input_length, // The concatenation of all "data[0,n-1]" fragments is the heap profile. extern bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg); +// Determine whether a working accelerated crc32 implementation exists +// Returns true if AcceleratedCRC32C is safe to call +bool HasAcceleratedCRC32C(); + // Extend the CRC to include the first n bytes of buf. // // Returns zero if the CRC cannot be extended using acceleration, else returns diff --git a/port/port_posix.cc b/port/port_posix.cc index 30e8007ae3cf11..6e55cca8bcb2a4 100644 --- a/port/port_posix.cc +++ b/port/port_posix.cc @@ -8,6 +8,10 @@ #include #include +#if defined(__GNUC__) +#include +#endif + namespace leveldb { namespace port { @@ -49,5 +53,15 @@ void InitOnce(OnceType* once, void (*initializer)()) { PthreadCall("once", pthread_once(once, initializer)); } +bool HasAcceleratedCRC32C() { +#if (__x86_64__ || __i386__) && defined(__GNUC__) + unsigned int eax, ebx, ecx, edx; + __get_cpuid(1, &eax, &ebx, &ecx, &edx); + return (ecx & (1 << 20)) != 0; +#else + return false; +#endif +} + } // namespace port } // namespace leveldb diff --git a/port/port_posix.h b/port/port_posix.h index 7e8213b22ecaf2..d85fa5d63fe0fc 100644 --- a/port/port_posix.h +++ b/port/port_posix.h @@ -152,6 +152,7 @@ inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) { return false; } +bool HasAcceleratedCRC32C(); uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size); } // namespace port diff --git a/port/port_posix_sse.cc b/port/port_posix_sse.cc index 22c1e1d336c021..2d49c21dd8b0eb 100644 --- a/port/port_posix_sse.cc +++ b/port/port_posix_sse.cc @@ -19,7 +19,6 @@ #include #elif defined(__GNUC__) && defined(__SSE4_2__) #include -#include #endif #endif // defined(LEVELDB_PLATFORM_POSIX_SSE) @@ -48,20 +47,6 @@ static inline uint64_t LE_LOAD64(const uint8_t *p) { #endif // defined(_M_X64) || defined(__x86_64__) -static inline bool HaveSSE42() { -#if defined(_MSC_VER) - int cpu_info[4] = {}; - __cpuid(cpu_info, 1); - return (cpu_info[2] & (1 << 20)) != 0; -#elif defined(__GNUC__) - unsigned int eax, ebx, ecx=0, edx; - __get_cpuid(1, &eax, &ebx, &ecx, &edx); - return (ecx & (1 << 20)) != 0; -#else - return false; -#endif -} - #endif // defined(LEVELDB_PLATFORM_POSIX_SSE) // For further improvements see Intel publication at: @@ -70,10 +55,6 @@ uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size) { #if !defined(LEVELDB_PLATFORM_POSIX_SSE) return 0; #else - static bool have = HaveSSE42(); - if (!have) { - return 0; - } const uint8_t *p = reinterpret_cast(buf); const uint8_t *e = p + size; diff --git a/util/crc32c.cc b/util/crc32c.cc index edd61cfd6fca83..b3f40eeeed45f5 100644 --- a/util/crc32c.cc +++ b/util/crc32c.cc @@ -288,6 +288,10 @@ static inline uint32_t LE_LOAD32(const uint8_t *p) { // Determine if the CPU running this program can accelerate the CRC32C // calculation. static bool CanAccelerateCRC32C() { + if (!port::HasAcceleratedCRC32C()) + return false; + + // Double-check that the accelerated implementation functions correctly. // port::AcceleretedCRC32C returns zero when unable to accelerate. static const char kTestCRCBuffer[] = "TestCRCBuffer"; static const char kBufSize = sizeof(kTestCRCBuffer) - 1;