mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-25 18:53:23 -03:00
cf44e4ca77
196962ff0 Add AcceleratedCRC32C to port_win.h 1bdf1c34c Merge upstream LevelDB v1.20 d31721eb0 Merge #17: Fixed file sharing errors fecd44902 Fixed file sharing error in Win32Env::GetFileSize(), Win32SequentialFile::_Init(), Win32RandomAccessFile::_Init() Fixed error checking in Win32SequentialFile::_Init() 5b7510f1b Merge #14: Merge upstream LevelDB 1.19 0d969fd57 Merge #16: [LevelDB] Do no crash if filesystem can't fsync c8c029b5b [LevelDB] Do no crash if filesystem can't fsync a53934a3a Increase leveldb version to 1.20. f3f139737 Separate Env tests from PosixEnv tests. eb4f0972f leveldb: Fix compilation warnings in port_posix_sse.cc on x86 (32-bit). d0883b600 Fixed path to doc file: index.md. 7fa20948d Convert documentation to markdown. ea175e28f Implement support for Intel crc32 instruction (SSE 4.2) 95cd743e5 Including <limits> for std::numeric_limits. 646c3588d Limit the number of read-only files the POSIX Env will have open. d40bc3fa5 Merge #13: Typo ebbd772d3 Typo a2fb086d0 Add option for max file size. The currend hard-coded value of 2M is inefficient in colossus. git-subtree-dir: src/leveldb git-subtree-split: 196962ff01c39b4705d8117df5c3f8c205349950
129 lines
3.4 KiB
C++
129 lines
3.4 KiB
C++
// Copyright 2016 The LevelDB Authors. All rights reserved.
|
|
// 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.
|
|
//
|
|
// A portable implementation of crc32c, optimized to handle
|
|
// four bytes at a time.
|
|
//
|
|
// In a separate source file to allow this accelerated CRC32C function to be
|
|
// compiled with the appropriate compiler flags to enable x86 SSE 4.2
|
|
// instructions.
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include "port/port.h"
|
|
|
|
#if defined(LEVELDB_PLATFORM_POSIX_SSE)
|
|
|
|
#if defined(_MSC_VER)
|
|
#include <intrin.h>
|
|
#elif defined(__GNUC__) && defined(__SSE4_2__)
|
|
#include <nmmintrin.h>
|
|
#include <cpuid.h>
|
|
#endif
|
|
|
|
#endif // defined(LEVELDB_PLATFORM_POSIX_SSE)
|
|
|
|
namespace leveldb {
|
|
namespace port {
|
|
|
|
#if defined(LEVELDB_PLATFORM_POSIX_SSE)
|
|
|
|
// Used to fetch a naturally-aligned 32-bit word in little endian byte-order
|
|
static inline uint32_t LE_LOAD32(const uint8_t *p) {
|
|
// SSE is x86 only, so ensured that |p| is always little-endian.
|
|
uint32_t word;
|
|
memcpy(&word, p, sizeof(word));
|
|
return word;
|
|
}
|
|
|
|
#if defined(_M_X64) || defined(__x86_64__) // LE_LOAD64 is only used on x64.
|
|
|
|
// Used to fetch a naturally-aligned 64-bit word in little endian byte-order
|
|
static inline uint64_t LE_LOAD64(const uint8_t *p) {
|
|
uint64_t dword;
|
|
memcpy(&dword, p, sizeof(dword));
|
|
return dword;
|
|
}
|
|
|
|
#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:
|
|
// http://download.intel.com/design/intarch/papers/323405.pdf
|
|
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;
|
|
uint32_t l = crc ^ 0xffffffffu;
|
|
|
|
#define STEP1 do { \
|
|
l = _mm_crc32_u8(l, *p++); \
|
|
} while (0)
|
|
#define STEP4 do { \
|
|
l = _mm_crc32_u32(l, LE_LOAD32(p)); \
|
|
p += 4; \
|
|
} while (0)
|
|
#define STEP8 do { \
|
|
l = _mm_crc32_u64(l, LE_LOAD64(p)); \
|
|
p += 8; \
|
|
} while (0)
|
|
|
|
if (size > 16) {
|
|
// Process unaligned bytes
|
|
for (unsigned int i = reinterpret_cast<uintptr_t>(p) % 8; i; --i) {
|
|
STEP1;
|
|
}
|
|
|
|
// _mm_crc32_u64 is only available on x64.
|
|
#if defined(_M_X64) || defined(__x86_64__)
|
|
// Process 8 bytes at a time
|
|
while ((e-p) >= 8) {
|
|
STEP8;
|
|
}
|
|
// Process 4 bytes at a time
|
|
if ((e-p) >= 4) {
|
|
STEP4;
|
|
}
|
|
#else // !(defined(_M_X64) || defined(__x86_64__))
|
|
// Process 4 bytes at a time
|
|
while ((e-p) >= 4) {
|
|
STEP4;
|
|
}
|
|
#endif // defined(_M_X64) || defined(__x86_64__)
|
|
}
|
|
// Process the last few bytes
|
|
while (p != e) {
|
|
STEP1;
|
|
}
|
|
#undef STEP8
|
|
#undef STEP4
|
|
#undef STEP1
|
|
return l ^ 0xffffffffu;
|
|
#endif // defined(LEVELDB_PLATFORM_POSIX_SSE)
|
|
}
|
|
|
|
} // namespace port
|
|
} // namespace leveldb
|