]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
cksum,wc: support disabling hardware acceleration at runtime
authorPádraig Brady <P@draigBrady.com>
Fri, 12 Sep 2025 16:03:11 +0000 (17:03 +0100)
committerPádraig Brady <P@draigBrady.com>
Sun, 14 Sep 2025 12:43:49 +0000 (13:43 +0100)
This is useful to give better test coverage at least,
and may be useful for users to tune their environment.

* bootstrap.conf: Reference the cpu-supports gnulib module.
* src/cksum.c: Use cpu_supports() rather than __builtin_cpu_supports().
* src/wc.c: Likewise.
* tests/cksum/cksum.sh: Adjust to testing all implementations.
* tests/wc/wc-cpu.sh: A new test to do likewise.
* tests/local.mk: Reference the new wc test.

bootstrap.conf
src/cksum.c
src/wc.c
tests/cksum/cksum.sh
tests/local.mk
tests/wc/wc-cpu.sh [new file with mode: 0755]

index 03848e9ea4fb2ee043dd4096b7415dd796158d1b..50e76652dfd3a65f36f0c69b4ce4b30aefca8ef3 100644 (file)
@@ -65,6 +65,7 @@ gnulib_modules="
   config-h
   configmake
   copy-file-range
+  cpu-supports
   crc-x86_64
   crypto/md5
   crypto/sha1
index 31098691291cef526b177d4dc4579946c846f37b..3e009febd623b793176ec44b0e6d8acab6744a96 100644 (file)
@@ -134,6 +134,7 @@ main (void)
 # endif
 
 # include "crc.h"
+# include "cpu-supports.h"
 
 /* Number of bytes to read at once.  */
 # define BUFLEN (1 << 16)
@@ -144,8 +145,8 @@ static cksum_fp_t
 pclmul_supported (void)
 {
 # if USE_PCLMUL_CRC32 || GL_CRC_X86_64_PCLMUL
-  bool pclmul_enabled = (0 < __builtin_cpu_supports ("pclmul")
-                         && 0 < __builtin_cpu_supports ("avx"));
+  bool pclmul_enabled = (cpu_supports ("avx")
+                         && cpu_supports ("pclmul"));
   if (cksum_debug)
     error (0, 0, "%s",
            (pclmul_enabled
@@ -165,8 +166,8 @@ avx2_supported (void)
      the avx512 version, but it implies that the avx2 version
      is supported  */
 # if USE_AVX2_CRC32
-  bool avx2_enabled = (0 < __builtin_cpu_supports ("vpclmulqdq")
-                       && 0 < __builtin_cpu_supports ("avx2"));
+  bool avx2_enabled = (cpu_supports ("avx2")
+                       && cpu_supports ("vpclmulqdq"));
   if (cksum_debug)
     error (0, 0, "%s",
            (avx2_enabled
@@ -186,9 +187,10 @@ avx512_supported (void)
      mavx512f for most of the avx512 functions we're using
      mavx512bw for byte swapping  */
 # if USE_AVX512_CRC32
-  bool avx512_enabled = (0 < __builtin_cpu_supports ("vpclmulqdq")
-                         && 0 < __builtin_cpu_supports ("avx512bw")
-                         && 0 < __builtin_cpu_supports ("avx512f"));
+  bool avx512_enabled = (cpu_supports ("avx512f")
+                         && cpu_supports ("avx512bw")
+                         && cpu_supports ("vpclmulqdq"));
+
   if (cksum_debug)
     error (0, 0, "%s",
            (avx512_enabled
@@ -206,7 +208,8 @@ vmull_supported (void)
 {
   /* vmull for multiplication  */
 # if USE_VMULL_CRC32
-  bool vmull_enabled = (getauxval (AT_HWCAP) & HWCAP_PMULL) > 0;
+  bool vmull_enabled = (cpu_may_support ("pmull")
+                        && (getauxval (AT_HWCAP) & HWCAP_PMULL) > 0);
   if (cksum_debug)
     error (0, 0, "%s",
            (vmull_enabled
index 268b947bb03493bbff8f837169c7a31e26598c10..5f974e1c0f009febc160d5da269d47ebb0caa547 100644 (file)
--- a/src/wc.c
+++ b/src/wc.c
@@ -33,6 +33,7 @@
 #include <xbinary-io.h>
 
 #include "system.h"
+#include "cpu-supports.h"
 #include "ioblksize.h"
 #include "wc.h"
 
@@ -133,7 +134,7 @@ static enum total_type total_mode = total_auto;
 static bool
 avx2_supported (void)
 {
-  bool avx_enabled = 0 < __builtin_cpu_supports ("avx2");
+  bool avx_enabled = cpu_supports ("avx2");
 
   if (debug)
     error (0, 0, (avx_enabled
index 83f61ad2f36fe0404abc8fe5480b90b97019b050..e216183c63e0c979a7bdf990eb77fd6fba81c2f2 100755 (executable)
@@ -22,15 +22,26 @@ print_ver_ cksum printf
 
 returns_ 1 cksum missing 2> /dev/null || fail=1
 
+GLIBC_TUNABLES='glibc.cpu.hwcaps=-AVX512F,-AVX2,-AVX,-PMULL' \
+ cksum --debug /dev/null 2>debug || fail=1
+grep 'using.*hardware support' debug && fail=1
+
 # Pass in expected crc and crc32b for file "in"
 # Sets fail=1 upon failure
 crc_check() {
-  for crct in crc crc32b; do
-    cksum -a $crct in > out || fail=1
-    case "$crct" in crc) crce="$1";; crc32b) crce="$2";; esac
-    size=$(stat -c %s in) || framework_failure_
-    printf '%s\n' "$crce $size in" > exp || framework_failure_
-    compare exp out || fail=1
+  TUNABLE_DISABLE='glibc.cpu.hwcaps='
+  for DHW in NONE AVX512F AVX2 AVX PMULL; do
+    TUNABLE_DISABLE="$TUNABLE_DISABLE-$DHW,"
+    for crct in crc crc32b; do
+      GLIBC_TUNABLES="$TUNABLE_DISABLE" \
+       cksum -a $crct in || fail=1
+      GLIBC_TUNABLES="$TUNABLE_DISABLE" \
+       cksum -a $crct in > out || fail=1
+      case "$crct" in crc) crce="$1";; crc32b) crce="$2";; esac
+      size=$(stat -c %s in) || framework_failure_
+      printf '%s\n' "$crce $size in" > exp || framework_failure_
+      compare exp out || fail=1
+    done
   done
 }
 
index 885787c3a8aade581d29b2ea30470ab8457ecd19..67a919e841508af7a983d53b3366bd60d77d0a14 100644 (file)
@@ -283,6 +283,7 @@ all_tests =                                 \
   tests/cut/cut.pl                             \
   tests/cut/cut-huge-range.sh                  \
   tests/wc/wc.pl                               \
+  tests/wc/wc-cpu.sh                           \
   tests/wc/wc-files0-from.pl                   \
   tests/wc/wc-files0.sh                                \
   tests/wc/wc-nbsp.sh                          \
diff --git a/tests/wc/wc-cpu.sh b/tests/wc/wc-cpu.sh
new file mode 100755 (executable)
index 0000000..725817a
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh
+# Ensure cpu specific code operates correctly
+
+# Copyright (C) 2025 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ wc
+
+GLIBC_TUNABLES='glibc.cpu.hwcaps=-AVX2' \
+ wc --debug /dev/null 2>debug || fail=1
+grep 'using.*hardware support' debug && fail=1
+
+lines=$(shuf -i 0-1000 | head -n1)  || framework_failure_
+seq 1000 | head -n "$lines" > lines || framework_failure_
+
+wc_accelerated=$(wc -l < lines) || fail=1
+wc_base=$(GLIBC_TUNABLES='glibc.cpu.hwcaps=-AVX2' wc -l < lines) || fail=1
+
+test "$wc_accelerated" = "$wc_base" || fail=1
+
+Exit $fail