]> granicus.if.org Git - postgresql/commitdiff
Improve our method for probing the availability of ARM CRC instructions.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 2 May 2018 22:06:43 +0000 (18:06 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 2 May 2018 22:06:43 +0000 (18:06 -0400)
Instead of depending on glibc's getauxval() function, just try to execute
the CRC code, and trap SIGILL if that happens.

Thomas Munro

Discussion: https://postgr.es/m/HE1PR0801MB1323D171938EABC04FFE7FA9E3110@HE1PR0801MB1323.eurprd08.prod.outlook.com

configure
configure.in
src/include/pg_config.h.in
src/port/pg_crc32c_armv8_choose.c

index 56f18dfbc269332bbd63b994b57b04352235714d..0aafd9c8c06971cd63dc817b39cee02b4b5aa438 100755 (executable)
--- a/configure
+++ b/configure
 fi
 
 
-# In order to detect at runtime, if the ARM CRC Extension is available,
-# we will do "getauxval(AT_HWCAP) & HWCAP_CRC32". Check if we have
-# everything we need for that.
-for ac_func in getauxval
-do :
-  ac_fn_c_check_func "$LINENO" "getauxval" "ac_cv_func_getauxval"
-if test "x$ac_cv_func_getauxval" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_GETAUXVAL 1
-_ACEOF
-
-fi
-done
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-#include <sys/auxv.h>
-#include <asm/hwcap.h>
-
-int
-main ()
-{
-
-#ifndef AT_HWCAP
-#error AT_HWCAP not defined
-#endif
-#ifndef HWCAP_CRC32
-#error HWCAP_CRC32 not defined
-#endif
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  HAVE_HWCAP_CRC32=1
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
 # Select CRC-32C implementation.
 #
 # If we are targeting a processor that has Intel SSE 4.2 instructions, we can
@@ -17414,9 +17374,8 @@ if test x"$USE_SLICING_BY_8_CRC32C" = x"" && test x"$USE_SSE42_CRC32C" = x"" &&
       if test x"$pgac_armv8_crc32c_intrinsics" = x"yes" && test x"$CFLAGS_ARMV8_CRC32C" = x""; then
         USE_ARMV8_CRC32C=1
       else
-        # ARM CRC Extension, with runtime check? The getauxval() function and
-        # HWCAP_CRC32 are needed for the runtime check.
-        if test x"$pgac_armv8_crc32c_intrinsics" = x"yes" && test x"$ac_cv_func_getauxval" = x"yes" && test x"$HAVE_HWCAP_CRC32" = x"1"; then
+        # ARM CRC Extension, with runtime check?
+        if test x"$pgac_armv8_crc32c_intrinsics" = x"yes"; then
           USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK=1
         else
           # fall back to slicing-by-8 algorithm, which doesn't require any
index da02a56ec661cd18d46807b358c0ee501eaeb015..c3841d5b07fcd42a811b320c06ecbe6849397c45 100644 (file)
@@ -2014,22 +2014,6 @@ if test x"$pgac_armv8_crc32c_intrinsics" != x"yes"; then
 fi
 AC_SUBST(CFLAGS_ARMV8_CRC32C)
 
-# In order to detect at runtime, if the ARM CRC Extension is available,
-# we will do "getauxval(AT_HWCAP) & HWCAP_CRC32". Check if we have
-# everything we need for that.
-AC_CHECK_FUNCS([getauxval])
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
-#include <sys/auxv.h>
-#include <asm/hwcap.h>
-], [
-#ifndef AT_HWCAP
-#error AT_HWCAP not defined
-#endif
-#ifndef HWCAP_CRC32
-#error HWCAP_CRC32 not defined
-#endif
-])], [HAVE_HWCAP_CRC32=1])
-
 # Select CRC-32C implementation.
 #
 # If we are targeting a processor that has Intel SSE 4.2 instructions, we can
@@ -2060,9 +2044,8 @@ if test x"$USE_SLICING_BY_8_CRC32C" = x"" && test x"$USE_SSE42_CRC32C" = x"" &&
       if test x"$pgac_armv8_crc32c_intrinsics" = x"yes" && test x"$CFLAGS_ARMV8_CRC32C" = x""; then
         USE_ARMV8_CRC32C=1
       else
-        # ARM CRC Extension, with runtime check? The getauxval() function and
-        # HWCAP_CRC32 are needed for the runtime check.
-        if test x"$pgac_armv8_crc32c_intrinsics" = x"yes" && test x"$ac_cv_func_getauxval" = x"yes" && test x"$HAVE_HWCAP_CRC32" = x"1"; then
+        # ARM CRC Extension, with runtime check?
+        if test x"$pgac_armv8_crc32c_intrinsics" = x"yes"; then
           USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK=1
         else
           # fall back to slicing-by-8 algorithm, which doesn't require any
index f3620231a7178ae91265e4a114cb6c2a0ce3f378..9411f485121a24a38cfd4cf8a12dc7d4bf07ea9a 100644 (file)
 /* Define to 1 if you have the `getaddrinfo' function. */
 #undef HAVE_GETADDRINFO
 
-/* Define to 1 if you have the `getauxval' function. */
-#undef HAVE_GETAUXVAL
-
 /* Define to 1 if you have the `gethostbyname_r' function. */
 #undef HAVE_GETHOSTBYNAME_R
 
index f21a8243e9add0fea30d8f88090ef5671def5385..d0d3a3da78ed9bfcc48794a6d69462b6fc7daa5f 100644 (file)
@@ -8,10 +8,6 @@
  * computation. Otherwise, fall back to the pure software implementation
  * (slicing-by-8).
  *
- * XXX: The glibc-specific getauxval() function, with the HWCAP_CRC32
- * flag, is used to determine if the CRC Extension is available on the
- * current platform. Is there a more portable way to determine that?
- *
  * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
 
 #include "c.h"
 
-#include <sys/auxv.h>
-#include <asm/hwcap.h>
+#include <setjmp.h>
 
+#include "libpq/pqsignal.h"
 #include "port/pg_crc32c.h"
 
+
+static sigjmp_buf illegal_instruction_jump;
+
+/*
+ * Probe by trying to execute pg_comp_crc32c_armv8().  If the instruction
+ * isn't available, we expect to get SIGILL, which we can trap.
+ */
+static void
+illegal_instruction_handler(int signo)
+{
+       siglongjmp(illegal_instruction_jump, 1);
+}
+
 static bool
 pg_crc32c_armv8_available(void)
 {
-       unsigned long auxv = getauxval(AT_HWCAP);
+       uint64          data = 42;
+       bool            result;
+
+       pqsignal(SIGILL, illegal_instruction_handler);
+       if (sigsetjmp(illegal_instruction_jump, 1) == 0)
+               result = (pg_comp_crc32c_armv8(0, &data, sizeof(data)) == 0xdd439b0d);
+       else
+               result = false;
+       pqsignal(SIGILL, SIG_DFL);
 
-       return (auxv & HWCAP_CRC32) != 0;
+       return result;
 }
 
 /*