Skip to content

Commit 77cfbfd

Browse files
committed
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.
1 parent 4c1e9e0 commit 77cfbfd

File tree

5 files changed

+23
-19
lines changed

5 files changed

+23
-19
lines changed

port/port_example.h

+4
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ extern bool Snappy_Uncompress(const char* input_data, size_t input_length,
129129
// The concatenation of all "data[0,n-1]" fragments is the heap profile.
130130
extern bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg);
131131

132+
// Determine whether a working accelerated crc32 implementation exists
133+
// Returns true if AcceleratedCRC32C is safe to call
134+
bool HasAcceleratedCRC32C();
135+
132136
// Extend the CRC to include the first n bytes of buf.
133137
//
134138
// Returns zero if the CRC cannot be extended using acceleration, else returns

port/port_posix.cc

+14
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
#include <stdio.h>
99
#include <string.h>
1010

11+
#if defined(__GNUC__)
12+
#include <cpuid.h>
13+
#endif
14+
1115
namespace leveldb {
1216
namespace port {
1317

@@ -49,5 +53,15 @@ void InitOnce(OnceType* once, void (*initializer)()) {
4953
PthreadCall("once", pthread_once(once, initializer));
5054
}
5155

56+
bool HasAcceleratedCRC32C() {
57+
#if (__x86_64__ || __i386__) && defined(__GNUC__)
58+
unsigned int eax, ebx, ecx, edx;
59+
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
60+
return (ecx & (1 << 20)) != 0;
61+
#else
62+
return false;
63+
#endif
64+
}
65+
5266
} // namespace port
5367
} // namespace leveldb

port/port_posix.h

+1
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) {
152152
return false;
153153
}
154154

155+
bool HasAcceleratedCRC32C();
155156
uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size);
156157

157158
} // namespace port

port/port_posix_sse.cc

-19
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include <intrin.h>
2020
#elif defined(__GNUC__) && defined(__SSE4_2__)
2121
#include <nmmintrin.h>
22-
#include <cpuid.h>
2322
#endif
2423

2524
#endif // defined(LEVELDB_PLATFORM_POSIX_SSE)
@@ -48,20 +47,6 @@ static inline uint64_t LE_LOAD64(const uint8_t *p) {
4847

4948
#endif // defined(_M_X64) || defined(__x86_64__)
5049

51-
static inline bool HaveSSE42() {
52-
#if defined(_MSC_VER)
53-
int cpu_info[4] = {};
54-
__cpuid(cpu_info, 1);
55-
return (cpu_info[2] & (1 << 20)) != 0;
56-
#elif defined(__GNUC__)
57-
unsigned int eax, ebx, ecx=0, edx;
58-
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
59-
return (ecx & (1 << 20)) != 0;
60-
#else
61-
return false;
62-
#endif
63-
}
64-
6550
#endif // defined(LEVELDB_PLATFORM_POSIX_SSE)
6651

6752
// For further improvements see Intel publication at:
@@ -70,10 +55,6 @@ uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size) {
7055
#if !defined(LEVELDB_PLATFORM_POSIX_SSE)
7156
return 0;
7257
#else
73-
static bool have = HaveSSE42();
74-
if (!have) {
75-
return 0;
76-
}
7758

7859
const uint8_t *p = reinterpret_cast<const uint8_t *>(buf);
7960
const uint8_t *e = p + size;

util/crc32c.cc

+4
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,10 @@ static inline uint32_t LE_LOAD32(const uint8_t *p) {
288288
// Determine if the CPU running this program can accelerate the CRC32C
289289
// calculation.
290290
static bool CanAccelerateCRC32C() {
291+
if (!port::HasAcceleratedCRC32C())
292+
return false;
293+
294+
// Double-check that the accelerated implementation functions correctly.
291295
// port::AcceleretedCRC32C returns zero when unable to accelerate.
292296
static const char kTestCRCBuffer[] = "TestCRCBuffer";
293297
static const char kBufSize = sizeof(kTestCRCBuffer) - 1;

0 commit comments

Comments
 (0)