From 7bd3839cda04d89a4f1d190aff3a35a319664d8b Mon Sep 17 00:00:00 2001 From: =?utf8?q?P=C3=A1draig=20Brady?= Date: Fri, 12 Sep 2025 17:03:11 +0100 Subject: [PATCH] cksum,wc: support disabling hardware acceleration at runtime 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 | 1 + src/cksum.c | 19 +++++++++++-------- src/wc.c | 3 ++- tests/cksum/cksum.sh | 23 +++++++++++++++++------ tests/local.mk | 1 + tests/wc/wc-cpu.sh | 34 ++++++++++++++++++++++++++++++++++ 6 files changed, 66 insertions(+), 15 deletions(-) create mode 100755 tests/wc/wc-cpu.sh diff --git a/bootstrap.conf b/bootstrap.conf index 03848e9ea4..50e76652df 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -65,6 +65,7 @@ gnulib_modules=" config-h configmake copy-file-range + cpu-supports crc-x86_64 crypto/md5 crypto/sha1 diff --git a/src/cksum.c b/src/cksum.c index 3109869129..3e009febd6 100644 --- a/src/cksum.c +++ b/src/cksum.c @@ -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 diff --git a/src/wc.c b/src/wc.c index 268b947bb0..5f974e1c0f 100644 --- a/src/wc.c +++ b/src/wc.c @@ -33,6 +33,7 @@ #include #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 diff --git a/tests/cksum/cksum.sh b/tests/cksum/cksum.sh index 83f61ad2f3..e216183c63 100755 --- a/tests/cksum/cksum.sh +++ b/tests/cksum/cksum.sh @@ -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 } diff --git a/tests/local.mk b/tests/local.mk index 885787c3a8..67a919e841 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -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 index 0000000000..725817a7cc --- /dev/null +++ b/tests/wc/wc-cpu.sh @@ -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 . + +. "${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 -- 2.47.3