root/tools/perf/util/stat.h
/* 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