From 34ff636f322c6d5e4f0a52338fa63a7dff09a495 Mon Sep 17 00:00:00 2001 From: Joel Fernandes Date: Sat, 18 Jul 2026 13:15:36 -0400 Subject: scftorture: Count single_rpc offline failures in statistics output scf_torture_stats_print() aggregates each invoker thread's counters into a local scf_statistics structure before printing, but the n_single_rpc_ofl field is missing from the aggregation loop. As a result, the "single_rpc_ofl" value printed in the statistics line is always zero, even when smp_call_function_single() invocations for the RPC test have failed due to offline CPUs and been counted by the invoker threads. Add the missing accumulation so that the printed value reflects the actual counts. Signed-off-by: Joel Fernandes Signed-off-by: Paul E. McKenney --- tools/perf/util/env.h | 245 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 tools/perf/util/env.h (limited to 'tools/perf/util/env.h') diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h new file mode 100644 index 000000000..7acca39b4 --- /dev/null +++ b/tools/perf/util/env.h @@ -0,0 +1,245 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __PERF_ENV_H +#define __PERF_ENV_H + +#include +#include +#include "cpumap.h" +#include "rwsem.h" +#include "mutex.h" + +struct perf_cpu_map; + +struct cpu_topology_map { + int socket_id; + int die_id; + int cluster_id; + int core_id; +}; + +struct cpu_cache_level { + u32 level; + u32 line_size; + u32 sets; + u32 ways; + char *type; + char *size; + char *map; +}; + +struct numa_node { + u32 node; + u64 mem_total; + u64 mem_free; + struct perf_cpu_map *map; +}; + +struct memory_node { + u64 node; + u64 size; + unsigned long *set; +}; + +struct hybrid_node { + char *pmu_name; + char *cpus; +}; + +struct pmu_caps { + int nr_caps; + unsigned int max_branches; + unsigned int br_cntr_nr; + unsigned int br_cntr_width; + + char **caps; + char *pmu_name; +}; + +struct domain_info { + u32 domain; + char *dname; + char *cpumask; + char *cpulist; +}; + +struct cpu_domain_map { + u32 cpu; + u32 nr_domains; + struct domain_info **domains; +}; + +struct perf_env { + char *hostname; + char *os_release; + char *version; + char *arch; + /* e_machine expanded from 16 to 32-bits for alignment. */ + u32 e_machine; + u32 e_flags; + int nr_cpus_online; + int nr_cpus_avail; + char *cpu_desc; + char *cpuid; + unsigned long long total_mem; + unsigned int msr_pmu_type; + unsigned int max_branches; + unsigned int br_cntr_nr; + unsigned int br_cntr_width; + unsigned int schedstat_version; + unsigned int max_sched_domains; + int kernel_is_64_bit; + + int nr_cmdline; + int nr_sibling_cores; + int nr_sibling_dies; + int nr_sibling_threads; + int nr_numa_nodes; + int nr_memory_nodes; + int nr_pmu_mappings; + int nr_groups; + int nr_cpu_pmu_caps; + int nr_hybrid_nodes; + int nr_pmus_with_caps; + char *cmdline; + const char **cmdline_argv; + char *sibling_cores; + char *sibling_dies; + char *sibling_threads; + char *pmu_mappings; + char **cpu_pmu_caps; + struct cpu_topology_map *cpu; + struct cpu_cache_level *caches; + struct cpu_domain_map **cpu_domain; + int caches_cnt; + unsigned int cln_size; + u32 comp_ratio; + u32 comp_ver; + u32 comp_type; + u32 comp_level; + u32 comp_mmap_len; + struct numa_node *numa_nodes; + struct memory_node *memory_nodes; + unsigned long long memory_bsize; + struct hybrid_node *hybrid_nodes; + struct pmu_caps *pmu_caps; +#ifdef HAVE_LIBBPF_SUPPORT + /* + * bpf_info_lock protects bpf rbtrees. This is needed because the + * trees are accessed by different threads in perf-top + */ + struct { + struct rw_semaphore lock; + struct rb_root infos; + u32 infos_cnt; + struct rb_root btfs; + u32 btfs_cnt; + } bpf_progs; +#endif // HAVE_LIBBPF_SUPPORT + /* same reason as above (for perf-top) */ + struct { + struct rw_semaphore lock; + struct rb_root tree; + } cgroups; + + /* For fast cpu to numa node lookup via perf_env__numa_node */ + int *numa_map; + int nr_numa_map; + + /* For real clock time reference. */ + struct { + u64 tod_ns; + u64 clockid_ns; + u64 clockid_res_ns; + int clockid; + /* + * enabled is valid for report mode, and is true if above + * values are set, it's set in process_clock_data + */ + bool enabled; + } clock; + /* Protects lazy environment initialization (e.g. os_release, e_machine). */ + struct mutex lock; +}; + +enum perf_compress_type { + PERF_COMP_NONE = 0, + PERF_COMP_ZSTD, + PERF_COMP_MAX +}; + +struct bpf_prog_info_node; +struct btf_node; + +int perf_env__read_core_pmu_caps(struct perf_env *env); +void free_cpu_domain_info(struct cpu_domain_map **cd_map, u32 schedstat_version, u32 nr); +void perf_env__exit(struct perf_env *env); + +int perf_env__kernel_is_64_bit(struct perf_env *env); +bool perf_arch_is_big_endian(const char *arch); +const char *perf_env__os_release(struct perf_env *env); + +int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]); + +int perf_env__read_cpuid(struct perf_env *env); +int perf_env__read_pmu_mappings(struct perf_env *env); +int perf_env__nr_pmu_mappings(struct perf_env *env); +const char *perf_env__pmu_mappings(struct perf_env *env); + +int perf_env__read_cpu_topology_map(struct perf_env *env); + +/* + * Safe accessor for env->cpu[] topology array. env->cpu can be NULL when + * reading old-format perf.data that predates topology information — + * process_cpu_topology() in header.c frees it while nr_cpus_avail remains + * set, so callers must not index env->cpu[] without this check. + */ +static inline struct cpu_topology_map * +perf_env__get_cpu_topology(struct perf_env *env, struct perf_cpu cpu) +{ + if (env->cpu && cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) + return &env->cpu[cpu.cpu]; + return NULL; +} + +void cpu_cache_level__free(struct cpu_cache_level *cache); + +uint16_t perf_env__e_machine_nocache(struct perf_env *env, uint32_t *e_flags); +uint16_t perf_env__e_machine(struct perf_env *env, uint32_t *e_flags); +const char *perf_env__arch(struct perf_env *env); +const char *perf_env__arch_strerrno(uint16_t e_machine, int err); +const char *perf_env__cpuid(struct perf_env *env); +int perf_env__nr_cpus_avail(struct perf_env *env); + +void perf_env__init(struct perf_env *env); +#ifdef HAVE_LIBBPF_SUPPORT +bool __perf_env__insert_bpf_prog_info(struct perf_env *env, + struct bpf_prog_info_node *info_node); +bool perf_env__insert_bpf_prog_info(struct perf_env *env, + struct bpf_prog_info_node *info_node); +struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env, + __u32 prog_id); +void perf_env__iterate_bpf_prog_info(struct perf_env *env, + void (*cb)(struct bpf_prog_info_node *node, + void *data), + void *data); +bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node); +bool __perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node); +struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id); +struct btf_node *__perf_env__find_btf(struct perf_env *env, __u32 btf_id); +#endif // HAVE_LIBBPF_SUPPORT + +int perf_env__numa_node(struct perf_env *env, struct perf_cpu cpu); +char *perf_env__find_pmu_cap(struct perf_env *env, const char *pmu_name, + const char *cap); + +bool perf_env__has_pmu_mapping(struct perf_env *env, const char *pmu_name); +void perf_env__find_br_cntr_info(struct perf_env *env, + unsigned int *nr, + unsigned int *width); + +bool x86__is_amd_cpu(void); +bool perf_env__is_x86_amd_cpu(struct perf_env *env); +bool x86__is_intel_cpu(void); +bool perf_env__is_x86_intel_cpu(struct perf_env *env); + +#endif /* __PERF_ENV_H */ -- cgit v1.3.1