Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .vscode/cspell.dictionaries/workspace.wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ advapi32-sys
aho-corasick
backtrace
blake2b_simd
cpufeatures

# * uutils project
uutils
Expand Down Expand Up @@ -364,6 +365,12 @@ getcwd
weblate
algs

# * CPU features and instructions
cpuid
pclmul
pclmulqdq
vmull

# translation tests
CLICOLOR
erreur
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ clap = { version = "4.5", features = ["wrap_help", "cargo", "color"] }
clap_complete = "4.4"
clap_mangen = "0.2"
compare = "0.1.0"
cpufeatures = "0.2.12"
crossterm = "0.29.0"
ctor = "0.6.0"
ctrlc = { version = "3.4.7", features = ["termination"] }
Expand Down
1 change: 1 addition & 0 deletions fuzz/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/uu/cksum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ uucore = { workspace = true, features = ["checksum", "encoding", "sum"] }
hex = { workspace = true }
fluent = { workspace = true }

[target.'cfg(all(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "loongarch64", target_arch = "x86"), not(target_os = "android")))'.dependencies]
cpufeatures = { workspace = true }

[dev-dependencies]
divan = { workspace = true }
tempfile = { workspace = true }
Expand Down
1 change: 1 addition & 0 deletions src/uu/cksum/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ cksum-help-status = don't output anything, status code shows success
cksum-help-quiet = don't print OK for each successfully verified file
cksum-help-ignore-missing = don't fail or report status for missing files
cksum-help-zero = end each output line with NUL, not newline, and disable file name escaping
cksum-help-debug = indicate which implementation is used

# Error messages
cksum-error-is-directory = { $file }: Is a directory
Expand Down
1 change: 1 addition & 0 deletions src/uu/cksum/locales/fr-FR.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ cksum-help-status = ne rien afficher, le code de statut indique le succès
cksum-help-quiet = ne pas afficher OK pour chaque fichier vérifié avec succès
cksum-help-ignore-missing = ne pas échouer ou signaler le statut pour les fichiers manquants
cksum-help-zero = terminer chaque ligne de sortie avec NUL, pas un saut de ligne, et désactiver l'échappement des noms de fichiers
cksum-help-debug = indiquer quelle implémentation est utilisée

# Messages d'erreur
cksum-error-is-directory = { $file } : Est un répertoire
Expand Down
25 changes: 25 additions & 0 deletions src/uu/cksum/src/cksum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@

// spell-checker:ignore (ToDO) fname, algo

mod hardware;

use clap::builder::ValueParser;
use clap::{Arg, ArgAction, Command};
use hardware::CpuFeatures;
use std::ffi::{OsStr, OsString};
use std::fs::File;
use std::io::{BufReader, Read, Write, stdin, stdout};
Expand Down Expand Up @@ -37,6 +40,7 @@ struct Options {
length: Option<usize>,
output_format: OutputFormat,
line_ending: LineEnding,
debug: bool,
}

/// Reading mode used to compute digest.
Expand Down Expand Up @@ -176,6 +180,13 @@ fn print_untagged_checksum(
Ok(())
}

/// Print CPU hardware capability detection information to stderr
/// This matches GNU cksum's --debug behavior
fn print_cpu_debug_info() {
let features = CpuFeatures::detect();
features.print_debug();
}

/// Calculate checksum
///
/// # Arguments
Expand All @@ -188,6 +199,12 @@ where
{
let mut files = files.peekable();

// Print CPU debug info once at startup if --debug flag is set
#[cfg(not(target_os = "android"))]
if options.debug {
print_cpu_debug_info();
}

while let Some(filename) = files.next() {
// Check that in raw mode, we are not provided with several files.
if options.output_format.is_raw() && files.peek().is_some() {
Expand Down Expand Up @@ -285,6 +302,7 @@ mod options {
pub const IGNORE_MISSING: &str = "ignore-missing";
pub const QUIET: &str = "quiet";
pub const ZERO: &str = "zero";
pub const DEBUG: &str = "debug";
}

/// cksum has a bunch of legacy behavior. We handle this in this function to
Expand Down Expand Up @@ -470,6 +488,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
length,
output_format,
line_ending,
debug: matches.get_flag(options::DEBUG),
};

cksum(opts, files)?;
Expand Down Expand Up @@ -600,5 +619,11 @@ pub fn uu_app() -> Command {
.help(translate!("cksum-help-zero"))
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(options::DEBUG)
.long(options::DEBUG)
.help(translate!("cksum-help-debug"))
.action(ArgAction::SetTrue),
)
.after_help(translate!("cksum-after-help"))
}
172 changes: 172 additions & 0 deletions src/uu/cksum/src/hardware.rs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should agree on a common implementation to put in uucore for it to be reused for the --debug flag of wc (see #9144)

Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// This file is part of the uutils coreutils package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

//! CPU hardware capability detection for cksum --debug
//!
//! This module detects available CPU features that affect cksum performance,
//! matching GNU cksum's --debug behavior.

use std::sync::Once;

/// CPU features that affect cksum performance
#[derive(Debug, Clone, Copy)]
pub struct CpuFeatures {
pub avx512: bool,
pub avx2: bool,
pub pclmul: bool,
pub vmull: bool,
}

impl CpuFeatures {
/// Detect available CPU features (cached after first call)
pub fn detect() -> Self {
static ONCE: Once = Once::new();
static mut FEATURES: CpuFeatures = CpuFeatures {
avx512: false,
avx2: false,
pclmul: false,
vmull: false,
};

unsafe {
ONCE.call_once(|| {
FEATURES = Self {
avx512: has_avx512(),
avx2: has_avx2(),
pclmul: has_pclmul(),
vmull: has_vmull(),
};
});
FEATURES
}
}

/// Print debug information to stderr
/// Outputs CPU feature availability in GNU cksum format
pub fn print_debug(&self) {
self.print_feature("avx512", self.avx512);
self.print_feature("avx2", self.avx2);
self.print_feature("pclmul", self.pclmul);
if cfg!(target_arch = "aarch64") {
self.print_feature("vmull", self.vmull);
}
}

fn print_feature(&self, name: &str, available: bool) {
let status = if available {
format!("using {name} hardware support")
} else {
format!("{name} support not detected")
};
eprintln!("cksum: {status}");
}
}

// CPU feature detection functions
// These use cpufeatures crate for cross-platform detection

#[cfg(all(
any(target_arch = "x86_64", target_arch = "x86"),
not(target_os = "android")
))]
fn has_avx512() -> bool {
cpufeatures::new!(cpuid_avx512, "avx512f", "avx512bw");
cpuid_avx512::get()
}

#[cfg(not(all(
any(target_arch = "x86_64", target_arch = "x86"),
not(target_os = "android")
)))]
fn has_avx512() -> bool {
false
}

#[cfg(all(
any(target_arch = "x86_64", target_arch = "x86"),
not(target_os = "android")
))]
fn has_avx2() -> bool {
cpufeatures::new!(cpuid_avx2, "avx2");
cpuid_avx2::get()
}

#[cfg(not(all(
any(target_arch = "x86_64", target_arch = "x86"),
not(target_os = "android")
)))]
fn has_avx2() -> bool {
false
}

#[cfg(all(
any(target_arch = "x86_64", target_arch = "x86"),
not(target_os = "android")
))]
fn has_pclmul() -> bool {
cpufeatures::new!(cpuid_pclmul, "pclmulqdq");
cpuid_pclmul::get()
}

#[cfg(not(all(
any(target_arch = "x86_64", target_arch = "x86"),
not(target_os = "android")
)))]
fn has_pclmul() -> bool {
false
}

#[cfg(target_arch = "aarch64")]
fn has_vmull() -> bool {
// ARM NEON support detection
// This would require platform-specific code
// For now, return false as a safe default
false
}

#[cfg(not(target_arch = "aarch64"))]
fn has_vmull() -> bool {
false
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
#[cfg(not(target_os = "android"))]
fn test_cpu_features_detection() {
let features = CpuFeatures::detect();
// Features should be valid booleans - just verify they can be detected
let _ = features.avx512;
let _ = features.avx2;
let _ = features.pclmul;
let _ = features.vmull;
}

#[test]
#[cfg(not(target_os = "android"))]
fn test_cpu_features_cached() {
let features1 = CpuFeatures::detect();
let features2 = CpuFeatures::detect();
// Should return same values (cached)
assert_eq!(features1.avx512, features2.avx512);
assert_eq!(features1.avx2, features2.avx2);
assert_eq!(features1.pclmul, features2.pclmul);
assert_eq!(features1.vmull, features2.vmull);
}

#[test]
#[cfg(all(
any(target_arch = "x86_64", target_arch = "x86"),
not(target_os = "android")
))]
fn test_cpu_features_on_x86() {
let features = CpuFeatures::detect();
// On x86/x86_64, at least one feature should be detected or all false
// (depending on CPU capabilities)
let _ = features;
}
}
Loading
Loading