summaryrefslogtreecommitdiffstats
path: root/tools/perf/util/stat.h
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2026-09-14 22:12:34 -1000
committerTejun Heo <tj@kernel.org>2026-09-15 06:57:20 -1000
commita9e3760b0838299649c0d57cca44daaf40ba3c33 (patch)
tree95807ff0e511c05602ef34808cfc660303309057 /tools/perf/util/stat.h
downloadlinux-stable-a9e3760b0838299649c0d57cca44daaf40ba3c33.tar.gz
linux-stable-a9e3760b0838299649c0d57cca44daaf40ba3c33.zip
sched_ext: Maintain an online cid mask in the scheduler arenagrafted
Schedulers on the default cid mapping treat [0, nr_online_cids) as the online set and restart on hotplug. Schedulers that install their own mapping with scx_bpf_cid_override() have no way to learn which cids are online: the count no longer identifies members and the CPU-form cpumask is unusable from cid programs. This is an obvious hole in the cid API. Add scx_bpf_online_cmask(), a kernel-maintained cmask in the scheduler's arena, allocated alongside the per-CPU scratch masks and populated after the cid mapping is finalized and before ops.init(), for child schedulers too. The pointer stays valid through ops.exit() with no reference to take. It is the arena offset as a void pointer, the same form struct_ops arena arguments arrive in. The verifier types the void return as a scalar for the program's arena cast. The mask follows the SCX hotplug notifications: seeded from cpu_active_mask and updated before ops.cid_online/offline() runs, so it lags cpu_online_mask only inside a hotplug transition. Updates walk the scheduler list under the lock that also serializes unlinking. Reads are live, not atomic snapshots. Root initialization excludes hotplug. v2: Reworded the getter kerneldoc (Andrea Righi). Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
Diffstat (limited to 'tools/perf/util/stat.h')
-rw-r--r--tools/perf/util/stat.h209
1 files changed, 209 insertions, 0 deletions
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
new file mode 100644
index 000000000..4bced233d
--- /dev/null
+++ b/tools/perf/util/stat.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PERF_STATS_H
+#define __PERF_STATS_H
+
+#include <linux/types.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include "cpumap.h"
+#include "counts.h"
+
+struct perf_cpu_map;
+struct perf_stat_config;
+struct timespec;
+
+struct stats {
+ double n, mean, M2;
+ u64 max, min;
+};
+
+/* hold aggregated event info */
+struct perf_stat_aggr {
+ /* aggregated values */
+ struct perf_counts_values counts;
+ /* number of entries (CPUs) aggregated */
+ int nr;
+ /* whether any entry has failed to read/process event */
+ bool failed;
+ /* to mark this data is processed already */
+ bool used;
+};
+
+/* per-evsel event stats */
+struct perf_stat_evsel {
+ /* used for repeated runs */
+ struct stats res_stats;
+ /* number of allocated 'aggr' */
+ int nr_aggr;
+ /* aggregated event values */
+ struct perf_stat_aggr *aggr;
+ /* used for group read */
+ u64 *group_data;
+};
+
+enum aggr_mode {
+ AGGR_NONE,
+ AGGR_GLOBAL,
+ AGGR_SOCKET,
+ AGGR_DIE,
+ AGGR_CLUSTER,
+ AGGR_CACHE,
+ AGGR_CORE,
+ AGGR_THREAD,
+ AGGR_UNSET,
+ AGGR_NODE,
+ AGGR_MAX
+};
+
+typedef struct aggr_cpu_id (*aggr_get_id_t)(struct perf_stat_config *config, struct perf_cpu cpu);
+
+struct perf_stat_config {
+ enum aggr_mode aggr_mode;
+ u32 aggr_level;
+ bool scale;
+ bool no_inherit;
+ bool identifier;
+ bool csv_output;
+ bool json_output;
+ bool interval_clear;
+ bool metric_only;
+ bool null_run;
+ bool ru_display;
+ bool big_num;
+ bool hybrid_merge;
+ bool walltime_run_table;
+ bool all_kernel;
+ bool all_user;
+ bool percore_show_thread;
+ bool summary;
+ bool no_csv_summary;
+ bool metric_no_group;
+ bool metric_no_merge;
+ bool metric_no_threshold;
+ bool hardware_aware_grouping;
+ bool stop_read_counter;
+ bool iostat_run;
+ char *user_requested_cpu_list;
+ bool system_wide;
+ FILE *output;
+ unsigned int interval;
+ unsigned int timeout;
+ unsigned int unit_width;
+ unsigned int metric_only_len;
+ int times;
+ int run_count;
+ int print_free_counters_hint;
+ const char *csv_sep;
+ struct stats *walltime_nsecs_stats;
+ struct rusage ru_data;
+ struct cpu_aggr_map *aggr_map;
+ aggr_get_id_t aggr_get_id;
+ struct cpu_aggr_map *cpus_aggr_map;
+ u64 *walltime_run;
+ int ctl_fd;
+ int ctl_fd_ack;
+ bool ctl_fd_close;
+ const char *cgroup_list;
+ unsigned int topdown_level;
+};
+
+extern struct perf_stat_config stat_config;
+
+void perf_stat__set_big_num(int set);
+
+void update_stats(struct stats *stats, u64 val);
+double avg_stats(struct stats *stats);
+double stddev_stats(struct stats *stats);
+double rel_stddev_stats(double stddev, double avg);
+
+static inline void init_stats(struct stats *stats)
+{
+ stats->n = 0.0;
+ stats->mean = 0.0;
+ stats->M2 = 0.0;
+ stats->min = (u64) -1;
+ stats->max = 0;
+}
+
+struct evsel;
+struct evlist;
+
+enum metric_threshold_classify {
+ METRIC_THRESHOLD_UNKNOWN,
+ METRIC_THRESHOLD_BAD,
+ METRIC_THRESHOLD_NEARLY_BAD,
+ METRIC_THRESHOLD_LESS_GOOD,
+ METRIC_THRESHOLD_GOOD,
+};
+const char *metric_threshold_classify__color(enum metric_threshold_classify thresh);
+
+typedef void (*print_metric_t)(struct perf_stat_config *config,
+ void *ctx,
+ enum metric_threshold_classify thresh,
+ const char *fmt,
+ const char *unit,
+ double val);
+typedef void (*new_line_t)(struct perf_stat_config *config, void *ctx);
+
+/* Used to print the display name of the Default metricgroup for now. */
+typedef void (*print_metricgroup_header_t)(struct perf_stat_config *config,
+ void *ctx, const char *metricgroup_name);
+
+void perf_stat__reset_shadow_stats(void);
+struct perf_stat_output_ctx {
+ void *ctx;
+ print_metric_t print_metric;
+ new_line_t new_line;
+ print_metricgroup_header_t print_metricgroup_header;
+ bool force_header;
+};
+
+void perf_stat__print_shadow_stats(struct perf_stat_config *config,
+ struct evsel *evsel,
+ int aggr_idx,
+ struct perf_stat_output_ctx *out);
+bool perf_stat__skip_metric_event(struct evsel *evsel);
+void *perf_stat__print_shadow_stats_metricgroup(struct perf_stat_config *config,
+ struct evsel *evsel,
+ int aggr_idx,
+ int *num,
+ void *from,
+ struct perf_stat_output_ctx *out);
+
+int evlist__alloc_stats(struct perf_stat_config *config,
+ struct evlist *evlist, bool alloc_raw);
+void evlist__free_stats(struct evlist *evlist);
+void evlist__reset_stats(struct evlist *evlist);
+void evlist__reset_prev_raw_counts(struct evlist *evlist);
+void evlist__copy_prev_raw_counts(struct evlist *evlist);
+void evlist__save_aggr_prev_raw_counts(struct evlist *evlist);
+
+int evlist__alloc_aggr_stats(struct evlist *evlist, int nr_aggr);
+void evlist__reset_aggr_stats(struct evlist *evlist);
+void evlist__copy_res_stats(struct perf_stat_config *config, struct evlist *evlist);
+
+int perf_stat_process_counter(struct perf_stat_config *config,
+ struct evsel *counter);
+void perf_stat_merge_counters(struct perf_stat_config *config, struct evlist *evlist);
+void perf_stat_process_percore(struct perf_stat_config *config, struct evlist *evlist);
+
+struct perf_tool;
+union perf_event;
+struct perf_session;
+struct target;
+
+int perf_event__process_stat_event(const struct perf_tool *tool,
+ struct perf_session *session,
+ union perf_event *event);
+
+size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
+
+void evlist__print_counters(struct evlist *evlist, struct perf_stat_config *config,
+ struct target *_target, struct timespec *ts, int argc, const char **argv);
+
+struct metric_expr;
+double test_generic_metric(struct metric_expr *mexp, int aggr_idx);
+#endif