Update copyright for 2022
[pgsql.git] / src / port / pg_crc32c_armv8_choose.c
blob6443e6a68e0fe51b5fc4eb7cc46ee567f91fea6d
1 /*-------------------------------------------------------------------------
3 * pg_crc32c_armv8_choose.c
4 * Choose between ARMv8 and software CRC-32C implementation.
6 * On first call, checks if the CPU we're running on supports the ARMv8
7 * CRC Extension. If it does, use the special instructions for CRC-32C
8 * computation. Otherwise, fall back to the pure software implementation
9 * (slicing-by-8).
11 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
12 * Portions Copyright (c) 1994, Regents of the University of California
15 * IDENTIFICATION
16 * src/port/pg_crc32c_armv8_choose.c
18 *-------------------------------------------------------------------------
21 #ifndef FRONTEND
22 #include "postgres.h"
23 #else
24 #include "postgres_fe.h"
25 #endif
27 #include <setjmp.h>
28 #include <signal.h>
30 #include "port/pg_crc32c.h"
33 static sigjmp_buf illegal_instruction_jump;
36 * Probe by trying to execute pg_comp_crc32c_armv8(). If the instruction
37 * isn't available, we expect to get SIGILL, which we can trap.
39 static void
40 illegal_instruction_handler(SIGNAL_ARGS)
42 siglongjmp(illegal_instruction_jump, 1);
45 static bool
46 pg_crc32c_armv8_available(void)
48 uint64 data = 42;
49 int result;
52 * Be careful not to do anything that might throw an error while we have
53 * the SIGILL handler set to a nonstandard value.
55 pqsignal(SIGILL, illegal_instruction_handler);
56 if (sigsetjmp(illegal_instruction_jump, 1) == 0)
58 /* Rather than hard-wiring an expected result, compare to SB8 code */
59 result = (pg_comp_crc32c_armv8(0, &data, sizeof(data)) ==
60 pg_comp_crc32c_sb8(0, &data, sizeof(data)));
62 else
64 /* We got the SIGILL trap */
65 result = -1;
67 pqsignal(SIGILL, SIG_DFL);
69 #ifndef FRONTEND
70 /* We don't expect this case, so complain loudly */
71 if (result == 0)
72 elog(ERROR, "crc32 hardware and software results disagree");
74 elog(DEBUG1, "using armv8 crc32 hardware = %d", (result > 0));
75 #endif
77 return (result > 0);
81 * This gets called on the first call. It replaces the function pointer
82 * so that subsequent calls are routed directly to the chosen implementation.
84 static pg_crc32c
85 pg_comp_crc32c_choose(pg_crc32c crc, const void *data, size_t len)
87 if (pg_crc32c_armv8_available())
88 pg_comp_crc32c = pg_comp_crc32c_armv8;
89 else
90 pg_comp_crc32c = pg_comp_crc32c_sb8;
92 return pg_comp_crc32c(crc, data, len);
95 pg_crc32c (*pg_comp_crc32c) (pg_crc32c crc, const void *data, size_t len) = pg_comp_crc32c_choose;