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 | |