| 1 | /*------------------------------------------------------------------------- |
| 2 | * |
| 3 | * pg_crc32c.h |
| 4 | * Routines for computing CRC-32C checksums. |
| 5 | * |
| 6 | * The speed of CRC-32C calculation has a big impact on performance, so we |
| 7 | * jump through some hoops to get the best implementation for each |
| 8 | * platform. Some CPU architectures have special instructions for speeding |
| 9 | * up CRC calculations (e.g. Intel SSE 4.2), on other platforms we use the |
| 10 | * Slicing-by-8 algorithm which uses lookup tables. |
| 11 | * |
| 12 | * The public interface consists of four macros: |
| 13 | * |
| 14 | * INIT_CRC32C(crc) |
| 15 | * Initialize a CRC accumulator |
| 16 | * |
| 17 | * COMP_CRC32C(crc, data, len) |
| 18 | * Accumulate some (more) bytes into a CRC |
| 19 | * |
| 20 | * FIN_CRC32C(crc) |
| 21 | * Finish a CRC calculation |
| 22 | * |
| 23 | * EQ_CRC32C(c1, c2) |
| 24 | * Check for equality of two CRCs. |
| 25 | * |
| 26 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
| 27 | * Portions Copyright (c) 1994, Regents of the University of California |
| 28 | * |
| 29 | * src/include/port/pg_crc32c.h |
| 30 | * |
| 31 | *------------------------------------------------------------------------- |
| 32 | */ |
| 33 | #ifndef PG_CRC32C_H |
| 34 | #define PG_CRC32C_H |
| 35 | |
| 36 | #include "port/pg_bswap.h" |
| 37 | |
| 38 | typedef uint32 pg_crc32c; |
| 39 | |
| 40 | /* The INIT and EQ macros are the same for all implementations. */ |
| 41 | #define INIT_CRC32C(crc) ((crc) = 0xFFFFFFFF) |
| 42 | #define EQ_CRC32C(c1, c2) ((c1) == (c2)) |
| 43 | |
| 44 | #if defined(USE_SSE42_CRC32C) |
| 45 | /* Use Intel SSE4.2 instructions. */ |
| 46 | #define COMP_CRC32C(crc, data, len) \ |
| 47 | ((crc) = pg_comp_crc32c_sse42((crc), (data), (len))) |
| 48 | #define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF) |
| 49 | |
| 50 | extern pg_crc32c pg_comp_crc32c_sse42(pg_crc32c crc, const void *data, size_t len); |
| 51 | |
| 52 | #elif defined(USE_ARMV8_CRC32C) |
| 53 | /* Use ARMv8 CRC Extension instructions. */ |
| 54 | |
| 55 | #define COMP_CRC32C(crc, data, len) \ |
| 56 | ((crc) = pg_comp_crc32c_armv8((crc), (data), (len))) |
| 57 | #define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF) |
| 58 | |
| 59 | extern pg_crc32c pg_comp_crc32c_armv8(pg_crc32c crc, const void *data, size_t len); |
| 60 | |
| 61 | #elif defined(USE_SSE42_CRC32C_WITH_RUNTIME_CHECK) || defined(USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK) |
| 62 | |
| 63 | /* |
| 64 | * Use Intel SSE 4.2 or ARMv8 instructions, but perform a runtime check first |
| 65 | * to check that they are available. |
| 66 | */ |
| 67 | #define COMP_CRC32C(crc, data, len) \ |
| 68 | ((crc) = pg_comp_crc32c((crc), (data), (len))) |
| 69 | #define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF) |
| 70 | |
| 71 | extern pg_crc32c pg_comp_crc32c_sb8(pg_crc32c crc, const void *data, size_t len); |
| 72 | extern pg_crc32c (*pg_comp_crc32c) (pg_crc32c crc, const void *data, size_t len); |
| 73 | |
| 74 | #ifdef USE_SSE42_CRC32C_WITH_RUNTIME_CHECK |
| 75 | extern pg_crc32c pg_comp_crc32c_sse42(pg_crc32c crc, const void *data, size_t len); |
| 76 | #endif |
| 77 | #ifdef USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK |
| 78 | extern pg_crc32c pg_comp_crc32c_armv8(pg_crc32c crc, const void *data, size_t len); |
| 79 | #endif |
| 80 | |
| 81 | #else |
| 82 | /* |
| 83 | * Use slicing-by-8 algorithm. |
| 84 | * |
| 85 | * On big-endian systems, the intermediate value is kept in reverse byte |
| 86 | * order, to avoid byte-swapping during the calculation. FIN_CRC32C reverses |
| 87 | * the bytes to the final order. |
| 88 | */ |
| 89 | #define COMP_CRC32C(crc, data, len) \ |
| 90 | ((crc) = pg_comp_crc32c_sb8((crc), (data), (len))) |
| 91 | #ifdef WORDS_BIGENDIAN |
| 92 | #define FIN_CRC32C(crc) ((crc) = pg_bswap32(crc) ^ 0xFFFFFFFF) |
| 93 | #else |
| 94 | #define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF) |
| 95 | #endif |
| 96 | |
| 97 | extern pg_crc32c pg_comp_crc32c_sb8(pg_crc32c crc, const void *data, size_t len); |
| 98 | |
| 99 | #endif |
| 100 | |
| 101 | #endif /* PG_CRC32C_H */ |
| 102 | |