Skip to content

Commit

Permalink
Merge #5: Move helper functions out of sse4.2 object
Browse files Browse the repository at this point in the history
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
  • Loading branch information
sipa committed Jul 21, 2017
2 parents 4953164 + 8d4eb08 commit d4c268a
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 19 deletions.
4 changes: 4 additions & 0 deletions port/port_example.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions port/port_posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
#include <stdio.h>
#include <string.h>

#if defined(__GNUC__)
#include <cpuid.h>
#endif

namespace leveldb {
namespace port {

Expand Down Expand Up @@ -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
1 change: 1 addition & 0 deletions port/port_posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 0 additions & 19 deletions port/port_posix_sse.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include <intrin.h>
#elif defined(__GNUC__) && defined(__SSE4_2__)
#include <nmmintrin.h>
#include <cpuid.h>
#endif

#endif // defined(LEVELDB_PLATFORM_POSIX_SSE)
Expand Down Expand Up @@ -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, 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:
Expand All @@ -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<const uint8_t *>(buf);
const uint8_t *e = p + size;
Expand Down
11 changes: 11 additions & 0 deletions port/port_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#include <windows.h>
#include <cassert>
#include <intrin.h>

namespace leveldb {
namespace port {
Expand Down Expand Up @@ -143,5 +144,15 @@ void AtomicPointer::NoBarrier_Store(void* v) {
rep_ = v;
}

bool HasAcceleratedCRC32C() {
#if (__x86_64__ || __i386__)
int cpu_info[4];
__cpuid(cpu_info, 1);
return (cpu_info[2] & (1 << 20)) != 0;
#else
return false;
#endif
}

}
}
1 change: 1 addition & 0 deletions port/port_win.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,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);

}
Expand Down
4 changes: 4 additions & 0 deletions util/crc32c.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit d4c268a

Please sign in to comment.