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