1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * pg_crc32c_sse42_choose.c |
4 | * Choose between Intel SSE 4.2 and software CRC-32C implementation. |
5 | * |
6 | * On first call, checks if the CPU we're running on supports Intel SSE |
7 | * 4.2. If it does, use the special SSE instructions for CRC-32C |
8 | * computation. Otherwise, fall back to the pure software implementation |
9 | * (slicing-by-8). |
10 | * |
11 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
12 | * Portions Copyright (c) 1994, Regents of the University of California |
13 | * |
14 | * |
15 | * IDENTIFICATION |
16 | * src/port/pg_crc32c_sse42_choose.c |
17 | * |
18 | *------------------------------------------------------------------------- |
19 | */ |
20 | |
21 | #include "c.h" |
22 | |
23 | #ifdef HAVE__GET_CPUID |
24 | #include <cpuid.h> |
25 | #endif |
26 | |
27 | #ifdef HAVE__CPUID |
28 | #include <intrin.h> |
29 | #endif |
30 | |
31 | #include "port/pg_crc32c.h" |
32 | |
33 | static bool |
34 | pg_crc32c_sse42_available(void) |
35 | { |
36 | unsigned int exx[4] = {0, 0, 0, 0}; |
37 | |
38 | #if defined(HAVE__GET_CPUID) |
39 | __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); |
40 | #elif defined(HAVE__CPUID) |
41 | __cpuid(exx, 1); |
42 | #else |
43 | #error cpuid instruction not available |
44 | #endif |
45 | |
46 | return (exx[2] & (1 << 20)) != 0; /* SSE 4.2 */ |
47 | } |
48 | |
49 | /* |
50 | * This gets called on the first call. It replaces the function pointer |
51 | * so that subsequent calls are routed directly to the chosen implementation. |
52 | */ |
53 | static pg_crc32c |
54 | pg_comp_crc32c_choose(pg_crc32c crc, const void *data, size_t len) |
55 | { |
56 | if (pg_crc32c_sse42_available()) |
57 | pg_comp_crc32c = pg_comp_crc32c_sse42; |
58 | else |
59 | pg_comp_crc32c = pg_comp_crc32c_sb8; |
60 | |
61 | return pg_comp_crc32c(crc, data, len); |
62 | } |
63 | |
64 | pg_crc32c (*pg_comp_crc32c) (pg_crc32c crc, const void *data, size_t len) = pg_comp_crc32c_choose; |
65 | |