Skip to content

Commit d4c268a

Browse files
committed
Merge #5: Move helper functions out of sse4.2 object
8d4eb08 Add HasAcceleratedCRC32C to port_win.h (Cory Fields) 77cfbfd crc32: move helper functions out of port_posix_sse.cc (Cory Fields) 4c1e9e0 silence compiler warnings about uninitialized variables (Cory Fields) Pull request description: Addresses #4. As this file is compiled with sse42 flags, it's possible that the feature discovery ends up using an unsupported instruction at runtime. Fix this by adding CanAccelerateCRC32C to the port api, and requiring that it be checked before using AcceleratedCRC32C. Tree-SHA512: 166cc0f4758bc0f22adda2126acad83e0251605a3a14d695fbb34a1d40f2328c4d938fbdcd624964281e6b9fcb3b233d3a8bde010ab889d82ae4f94479c6e545
2 parents 4953164 + 8d4eb08 commit d4c268a

7 files changed

+35
-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, 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;

port/port_win.cc

+11
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
#include <windows.h>
3434
#include <cassert>
35+
#include <intrin.h>
3536

3637
namespace leveldb {
3738
namespace port {
@@ -143,5 +144,15 @@ void AtomicPointer::NoBarrier_Store(void* v) {
143144
rep_ = v;
144145
}
145146

147+
bool HasAcceleratedCRC32C() {
148+
#if (__x86_64__ || __i386__)
149+
int cpu_info[4];
150+
__cpuid(cpu_info, 1);
151+
return (cpu_info[2] & (1 << 20)) != 0;
152+
#else
153+
return false;
154+
#endif
155+
}
156+
146157
}
147158
}

port/port_win.h

+1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) {
168168
return false;
169169
}
170170

171+
bool HasAcceleratedCRC32C();
171172
uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size);
172173

173174
}

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)