MySQL 8.4.0
Source Code Documentation
ut0crc32.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 2011, 2024, Oracle and/or its affiliates.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is designed to work with certain software (including
10but not limited to OpenSSL) that is licensed under separate terms,
11as designated in a particular file or component or in included license
12documentation. The authors of MySQL hereby grant you an additional
13permission to link the program and your derivative works with the
14separately licensed software that they have either included with
15the program or referenced in the documentation.
16
17This program is distributed in the hope that it will be useful, but WITHOUT
18ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
20for more details.
21
22You should have received a copy of the GNU General Public License along with
23this program; if not, write to the Free Software Foundation, Inc.,
2451 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
26*****************************************************************************/
27
28/** @file include/ut0crc32.h
29 CRC32 implementation
30
31 Created Aug 10, 2011 Vasil Dimov
32 *******************************************************/
33
34#ifndef ut0crc32_h
35#define ut0crc32_h
36
37#include "univ.i"
38
39/*
40- 1. some things depend on the compiling environment
41 - is it a compiler for which we even know how to use intrinsics?
42 - is it x86, arm64, or mac-arm?
43- 2. some depend on runtime environment
44 - is it x86 which has crc32?
45 - is it x86 which has pcmul?
46 - is it arm which has crc32?
47 - is it arm which has pcmul?
48- 3. some depend on the runtime usage:
49 - is it 0.5kb redo buffer, 16kb page, or something else?
50 - do you need the variant with swapped byte order?
51*/
52
53#if defined(__GNUC__) && defined(__x86_64__) || defined(_WIN32)
54#define CRC32_x86_64
55#ifdef _WIN32
56#define CRC32_x86_64_WIN
57#else /* _WIN32 */
58#define CRC32_x86_64_DEFAULT
59#endif /* _WIN32 */
60#elif defined(__aarch64__) && defined(__GNUC__)
61#define CRC32_ARM64
62#ifdef APPLE_ARM
63#define CRC32_ARM64_APPLE
64#else /* APPLE_ARM */
65#define CRC32_ARM64_DEFAULT
66#endif /* APPLE_ARM */
67#else
68#define CRC32_DEFAULT
69#endif /* defined(__aarch64__) && defined(__GNUC__) */
70
71/* At this point we have classified the system statically into exactly one of
72the possible cases:
73
74CRC32_x86_64
75 An environment in which we can use `cpuid` instruction to detect if it has
76 support for crc32 and pclmul instructions, which (if available) can be used
77 via _mm_crc32_u64 and _mm_clmulepi64_si128 respectively exposed by
78 nmmintrin.h and wmmintrin.h.
79 This is narrowed further into one of:
80
81 CRC32_x86_64_WIN
82 An environment which seems to be like Visual Studio, so we expect
83 intrin.h header exposing `__cpuid`, which we can use instead of inline
84 assembly, which is good as Visual Studio dialect of asm is different.
85 Also, __attribute__(target(...)) probably doesn't work on it.
86 CRC32_x86_64_DEFAULT
87 An environment which seems to be like gcc or clang, and thus we can use
88 inline assembly to get `cpuid`.
89 Also, we can/have to use __attribute__(target(...)) on functions which
90 use intrinsics, and may need to use __attribute__(flatten) at top level
91 to ensure that the run-time selection of target-specific variant of the
92 function happens just once at the top, not in every leaf, which would
93 break inlining and optimizations.
94CRC32_ARM64
95 An environment in which it is probable that __crc32cd and vmull_p64 could be
96 used for hardware accelerated crc32 and polynomial multiplication
97 computations, respectively. However we might need to perform some runtime
98 checks via getauxval() to see if this particular processor on which we run
99 supports them.
100 This is narrowed further into one of:
101
102 CRC32_ARM64_APPLE
103 An environment which seems to be like Apple's M1 processor, and we don't
104 expect to find sys/auxv.h header which defines getauxval() on it, yet we
105 also expect the __crc32cd and vmull_p64 to "just work" on it, without
106 checking getauxval().
107
108 CRC32_ARM64_DEFAULT
109 An environment which seems to be like a "regular" ARM64. Note that this
110 is not very specific term, as there are ARMv7-A, ARMv8-A, and the later
111 has two execution states AArch32 and AArch64. FWIW we use __aarch64__ to
112 detect this case. We still need to call getauxval() to see if particular
113 instruction set is available. We assume we run in 64-bit execution state
114 thus we use AT_HWCAP (as opposed to AT_HWCAP2).
115CRC32_DEFAULT
116 An environment in which we don't even know how to ask if the hardware
117 supports crc32 or polynomial multiplication and even if it does we don't
118 know how to ask it to do it anyway. We use software implementation of crc32.
119*/
120
121#ifdef CRC32_x86_64
122#include <nmmintrin.h>
123#include <wmmintrin.h>
124#endif /* CRC32_x86_64 */
125
126#ifdef CRC32_x86_64_WIN
127#include <intrin.h>
128#endif /* CRC32_x86_64_WIN */
129
130#ifdef CRC32_ARM64
131#include <arm_acle.h>
132#include <arm_neon.h>
133#endif /* CRC32_ARM64 */
134
135#ifdef CRC32_ARM64_DEFAULT
136#include <asm/hwcap.h>
137#include <sys/auxv.h>
138#endif /* CRC32_ARM64_DEFAULT */
139
140#ifdef CRC32_ARM64_APPLE
141#if __has_include(<asm/hwcap.h>) && __has_include(<sys/auxv.h>)
142#error \
143 "Current implementation is based on assumption that APPLE_ARM always " \
144 "supports crc32 and pmull and that there is no way to check it, yet it "\
145 "seem that this APPLE_ARM has getauxval()."
146#endif /* __has_include(<asm/hwcap.h>) && __has_include(<sys/auxv.h>) */
147#endif /* CRC32_ARM64_APPLE */
148
149/** Initializes the data structures used by ut_crc32*(). Does not do any
150 allocations, would not hurt if called twice, but would be pointless. */
151void ut_crc32_init();
152
153/** The CRC-32C polynomial without the implicit highest 1 at x^32 */
154constexpr uint32_t CRC32C_POLYNOMIAL{0x1EDC6F41};
155
156/** Calculates CRC32.
157 @param ptr - data over which to calculate CRC32.
158 @param len - data length in bytes.
159 @return calculated hash */
160typedef uint32_t (*ut_crc32_func_t)(const byte *ptr, size_t len);
161
162/** Pointer to standard-compliant CRC32-C (using the GF(2) primitive polynomial
1630x11EDC6F41) calculation function picked by ut_crc32_init() as the fastest
164implementation for the current environment. */
166
167/** Calculates CRC32 using legacy algorithm, which uses big-endian byte ordering
168when converting byte sequence to integers - flips each full aligned 8-byte chunk
169within the buf, but not the initial and trailing unaligned fragments.
170ut_crc32_init() needs to be called at least once before calling this function.
171@param[in] buf data over which to calculate CRC32
172@param[in] len data length
173@return calculated hash */
174uint32_t ut_crc32_legacy_big_endian(const byte *buf, size_t len);
175
176/** Flag that tells whether the CPU supports CRC32 or not. */
177extern bool ut_crc32_cpu_enabled;
178
179/** Flag that tells whether the CPU supports polynomial multiplication or not.*/
180extern bool ut_poly_mul_cpu_enabled;
181
182#ifndef CRC32_DEFAULT
183/** Updates CRC32 value with hardware accelerated.
184@param[in] crc base CRC32 value
185@param[in] data 8 bytes data to be processed
186@return updated CRC32 value */
187#ifdef CRC32_x86_64
188MY_ATTRIBUTE((target("sse4.2")))
189#elif defined(CRC32_ARM64_DEFAULT)
190MY_ATTRIBUTE((target("+crc")))
191#endif /* CRC32_x86_64 */
192static inline uint64_t crc32_update_uint64(uint64_t crc, uint64_t data) {
193#ifdef CRC32_x86_64
194 return _mm_crc32_u64(crc, data);
195#elif defined(CRC32_ARM64)
196 return (uint64_t)__crc32cd((uint32_t)crc, data);
197#endif /* CRC32_x86_64 */
198}
199
200/** Hashes a 64-bit integer with CRC32 instructions of the architecture.
201@param[in] value 64-bit integer
202@return hashed value */
203static inline uint64_t crc32_hash_uint64(uint64_t value) {
205 value *= 0xb5eb6fbadd39bf9b;
206 return (crc32_update_uint64(0, value) ^ value) << 32 |
207 crc32_update_uint64(0, (value >> 32 | value << 32));
208}
209#endif /* !CRC32_DEFAULT */
210
211#endif /* ut0crc32_h */
Definition: buf0block_hint.cc:30
Version control for database, common definitions, and include files.
uint32_t(* ut_crc32_func_t)(const byte *ptr, size_t len)
Calculates CRC32.
Definition: ut0crc32.h:160
bool ut_crc32_cpu_enabled
Flag that tells whether the CPU supports CRC32 or not.
Definition: crc32.cc:103
uint32_t ut_crc32_legacy_big_endian(const byte *buf, size_t len)
Calculates CRC32 using legacy algorithm, which uses big-endian byte ordering when converting byte seq...
Definition: crc32.cc:287
ut_crc32_func_t ut_crc32
Pointer to standard-compliant CRC32-C (using the GF(2) primitive polynomial 0x11EDC6F41) calculation ...
Definition: crc32.cc:101
void ut_crc32_init()
Initializes the data structures used by ut_crc32*().
Definition: crc32.cc:786
bool ut_poly_mul_cpu_enabled
Flag that tells whether the CPU supports polynomial multiplication or not.
Definition: crc32.cc:104
constexpr uint32_t CRC32C_POLYNOMIAL
The CRC-32C polynomial without the implicit highest 1 at x^32.
Definition: ut0crc32.h:154
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:105