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