^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2017, Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) /* Manage metrics and groups of metrics from JSON files */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "metricgroup.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "evlist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "evsel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "strbuf.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "pmu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "expr.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "rblist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "strlist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <assert.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/zalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <subcmd/parse-options.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <api/fs/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "util.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "cgroup.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct metric_event *metricgroup__lookup(struct rblist *metric_events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) bool create)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct rb_node *nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct metric_event me = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) .evsel = evsel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (!metric_events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) nd = rblist__find(metric_events, &me);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (nd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return container_of(nd, struct metric_event, nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (create) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) rblist__add_node(metric_events, &me);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) nd = rblist__find(metric_events, &me);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (nd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return container_of(nd, struct metric_event, nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static int metric_event_cmp(struct rb_node *rb_node, const void *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct metric_event *a = container_of(rb_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct metric_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) const struct metric_event *b = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (a->evsel == b->evsel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if ((char *)a->evsel < (char *)b->evsel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return +1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static struct rb_node *metric_event_new(struct rblist *rblist __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) const void *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct metric_event *me = malloc(sizeof(struct metric_event));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (!me)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) memcpy(me, entry, sizeof(struct metric_event));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) me->evsel = ((struct metric_event *)entry)->evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) INIT_LIST_HEAD(&me->head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return &me->nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static void metric_event_delete(struct rblist *rblist __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct rb_node *rb_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct metric_event *me = container_of(rb_node, struct metric_event, nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct metric_expr *expr, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) list_for_each_entry_safe(expr, tmp, &me->head, nd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) free(expr->metric_refs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) free(expr->metric_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) free(expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) free(me);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static void metricgroup__rblist_init(struct rblist *metric_events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) rblist__init(metric_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) metric_events->node_cmp = metric_event_cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) metric_events->node_new = metric_event_new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) metric_events->node_delete = metric_event_delete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) void metricgroup__rblist_exit(struct rblist *metric_events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) rblist__exit(metric_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * A node in the list of referenced metrics. metric_expr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * is held as a convenience to avoid a search through the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * metric list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct metric_ref_node {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) const char *metric_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) const char *metric_expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct metric {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct list_head nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct expr_parse_ctx pctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) const char *metric_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) const char *metric_expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) const char *metric_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct list_head metric_refs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int metric_refs_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) bool has_constraint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define RECURSION_ID_MAX 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct expr_ids {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct expr_id id[RECURSION_ID_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static struct expr_id *expr_ids__alloc(struct expr_ids *ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (ids->cnt >= RECURSION_ID_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return &ids->id[ids->cnt++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static void expr_ids__exit(struct expr_ids *ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) for (i = 0; i < ids->cnt; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) free(ids->id[i].id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static bool contains_event(struct evsel **metric_events, int num_events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) const char *event_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) for (i = 0; i < num_events; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (!strcmp(metric_events[i]->name, event_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * Find a group of events in perf_evlist that correspond to those from a parsed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * metric expression. Note, as find_evsel_group is called in the same order as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * perf_evlist was constructed, metric_no_merge doesn't need to test for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * underfilling a group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * @perf_evlist: a list of events something like: {metric1 leader, metric1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * sibling, metric1 sibling}:W,duration_time,{metric2 leader, metric2 sibling,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * metric2 sibling}:W,duration_time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * @pctx: the parse context for the metric expression.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * @metric_no_merge: don't attempt to share events for the metric with other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * metrics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * @has_constraint: is there a contraint on the group of events? In which case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * the events won't be grouped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * @metric_events: out argument, null terminated array of evsel's associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * with the metric.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * @evlist_used: in/out argument, bitmap tracking which evlist events are used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * @return the first metric event or NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static struct evsel *find_evsel_group(struct evlist *perf_evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct expr_parse_ctx *pctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) bool metric_no_merge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) bool has_constraint,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct evsel **metric_events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) unsigned long *evlist_used)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct evsel *ev, *current_leader = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct expr_id_data *val_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int i = 0, matched_events = 0, events_to_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) const int idnum = (int)hashmap__size(&pctx->ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * duration_time is always grouped separately, when events are grouped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * (ie has_constraint is false) then ignore it in the matching loop and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * add it to metric_events at the end.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (!has_constraint &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) hashmap__find(&pctx->ids, "duration_time", (void **)&val_ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) events_to_match = idnum - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) events_to_match = idnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) evlist__for_each_entry (perf_evlist, ev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * Events with a constraint aren't grouped and match the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * events available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (has_constraint && ev->weak_group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* Ignore event if already used and merging is disabled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (metric_no_merge && test_bit(ev->idx, evlist_used))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (!has_constraint && ev->leader != current_leader) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * Start of a new group, discard the whole match and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * start again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) matched_events = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) memset(metric_events, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) sizeof(struct evsel *) * idnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) current_leader = ev->leader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * Check for duplicate events with the same name. For example,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * uncore_imc/cas_count_read/ will turn into 6 events per socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * on skylakex. Only the first such event is placed in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * metric_events. If events aren't grouped then this also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * ensures that the same event in different sibling groups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * aren't both added to metric_events.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (contains_event(metric_events, matched_events, ev->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* Does this event belong to the parse context? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (hashmap__find(&pctx->ids, ev->name, (void **)&val_ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) metric_events[matched_events++] = ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (matched_events == events_to_match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (events_to_match != idnum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /* Add the first duration_time. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) evlist__for_each_entry(perf_evlist, ev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (!strcmp(ev->name, "duration_time")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) metric_events[matched_events++] = ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (matched_events != idnum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* Not a whole match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) metric_events[idnum] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) for (i = 0; i < idnum; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ev = metric_events[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* Don't free the used events. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) set_bit(ev->idx, evlist_used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * The metric leader points to the identically named event in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * metric_events.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ev->metric_leader = ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * Mark two events with identical names in the same group (or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * globally) as being in use as uncore events may be duplicated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * for each pmu. Set the metric leader of such events to be the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * event that appears in metric_events.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) evlist__for_each_entry_continue(perf_evlist, ev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * If events are grouped then the search can terminate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * when then group is left.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (!has_constraint &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ev->leader != metric_events[i]->leader)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (!strcmp(metric_events[i]->name, ev->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) set_bit(ev->idx, evlist_used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ev->metric_leader = metric_events[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return metric_events[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static int metricgroup__setup_events(struct list_head *groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) bool metric_no_merge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct evlist *perf_evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct rblist *metric_events_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct metric_event *me;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct metric_expr *expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct metric *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct evsel *evsel, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) unsigned long *evlist_used;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) evlist_used = bitmap_alloc(perf_evlist->core.nr_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (!evlist_used)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) list_for_each_entry (m, groups, nd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct evsel **metric_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct metric_ref *metric_refs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) metric_events = calloc(sizeof(void *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) hashmap__size(&m->pctx.ids) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (!metric_events) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) evsel = find_evsel_group(perf_evlist, &m->pctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) metric_no_merge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) m->has_constraint, metric_events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) evlist_used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (!evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) pr_debug("Cannot resolve %s: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) m->metric_name, m->metric_expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) free(metric_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) for (i = 0; metric_events[i]; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) metric_events[i]->collect_stat = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) me = metricgroup__lookup(metric_events_list, evsel, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (!me) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) free(metric_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) expr = malloc(sizeof(struct metric_expr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (!expr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) free(metric_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * Collect and store collected nested expressions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * for metric processing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (m->metric_refs_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct metric_ref_node *ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) metric_refs = zalloc(sizeof(struct metric_ref) * (m->metric_refs_cnt + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (!metric_refs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) free(metric_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) free(expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) list_for_each_entry(ref, &m->metric_refs, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * Intentionally passing just const char pointers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * originally from 'struct pmu_event' object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * We don't need to change them, so there's no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * need to create our own copy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) metric_refs[i].metric_name = ref->metric_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) metric_refs[i].metric_expr = ref->metric_expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) expr->metric_refs = metric_refs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) expr->metric_expr = m->metric_expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) expr->metric_name = m->metric_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) expr->metric_unit = m->metric_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) expr->metric_events = metric_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) expr->runtime = m->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) list_add(&expr->nd, &me->head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) evlist__for_each_entry_safe(perf_evlist, tmp, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (!test_bit(evsel->idx, evlist_used)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) evlist__remove(perf_evlist, evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) evsel__delete(evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) bitmap_free(evlist_used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static bool match_metric(const char *n, const char *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) char *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (!list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (!strcmp(list, "all"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (!n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return !strcasecmp(list, "No_group");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) len = strlen(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) m = strcasestr(n, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (!m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if ((m == n || m[-1] == ';' || m[-1] == ' ') &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) (m[len] == 0 || m[len] == ';'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) struct mep {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct rb_node nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct strlist *metrics;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static int mep_cmp(struct rb_node *rb_node, const void *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct mep *a = container_of(rb_node, struct mep, nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct mep *b = (struct mep *)entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return strcmp(a->name, b->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static struct rb_node *mep_new(struct rblist *rl __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) const void *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) struct mep *me = malloc(sizeof(struct mep));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (!me)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) memcpy(me, entry, sizeof(struct mep));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) me->name = strdup(me->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (!me->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) goto out_me;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) me->metrics = strlist__new(NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (!me->metrics)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) goto out_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return &me->nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) out_name:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) zfree(&me->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) out_me:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) free(me);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) static struct mep *mep_lookup(struct rblist *groups, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) struct rb_node *nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) struct mep me = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) .name = name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) nd = rblist__find(groups, &me);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (nd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return container_of(nd, struct mep, nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) rblist__add_node(groups, &me);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) nd = rblist__find(groups, &me);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (nd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return container_of(nd, struct mep, nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static void mep_delete(struct rblist *rl __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct rb_node *nd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct mep *me = container_of(nd, struct mep, nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) strlist__delete(me->metrics);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) zfree(&me->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) free(me);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static void metricgroup__print_strlist(struct strlist *metrics, bool raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct str_node *sn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) int n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) strlist__for_each_entry (sn, metrics) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) printf("%s%s", n > 0 ? " " : "", sn->s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) printf(" %s\n", sn->s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) putchar('\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) void metricgroup__print(bool metrics, bool metricgroups, char *filter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) bool raw, bool details)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct pmu_events_map *map = perf_pmu__find_map(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct pmu_event *pe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct rblist groups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct rb_node *node, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) struct strlist *metriclist = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (!map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (!metricgroups) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) metriclist = strlist__new(NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (!metriclist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) rblist__init(&groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) groups.node_new = mep_new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) groups.node_cmp = mep_cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) groups.node_delete = mep_delete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) for (i = 0; ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) const char *g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) pe = &map->table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (!pe->name && !pe->metric_group && !pe->metric_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (!pe->metric_expr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) g = pe->metric_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (!g && pe->metric_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (pe->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) g = "No_group";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (g) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) char *omg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) char *mg = strdup(g);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (!mg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) omg = mg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) while ((g = strsep(&mg, ";")) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) struct mep *me;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) g = skip_spaces(g);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (*g == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) g = "No_group";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (filter && !strstr(g, filter))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) s = (char *)pe->metric_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (asprintf(&s, "%s\n%*s%s]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) pe->metric_name, 8, "[", pe->desc) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (details) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (asprintf(&s, "%s\n%*s%s]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) s, 8, "[", pe->metric_expr) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (!s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (!metricgroups) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) strlist__add(metriclist, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) me = mep_lookup(&groups, g);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (!me)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) strlist__add(me->metrics, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (!raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) free(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) free(omg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (!filter || !rblist__empty(&groups)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (metricgroups && !raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) printf("\nMetric Groups:\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) else if (metrics && !raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) printf("\nMetrics:\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) for (node = rb_first_cached(&groups.entries); node; node = next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) struct mep *me = container_of(node, struct mep, nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (metricgroups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) printf("%s%s%s", me->name, metrics && !raw ? ":" : "", raw ? " " : "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (metrics)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) metricgroup__print_strlist(me->metrics, raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) next = rb_next(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) rblist__remove_node(&groups, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (!metricgroups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) metricgroup__print_strlist(metriclist, raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) strlist__delete(metriclist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) static void metricgroup__add_metric_weak_group(struct strbuf *events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) struct expr_parse_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) struct hashmap_entry *cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) size_t bkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) bool no_group = true, has_duration = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) hashmap__for_each_entry((&ctx->ids), cur, bkt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) pr_debug("found event %s\n", (const char *)cur->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * Duration time maps to a software event and can make
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * groups not count. Always use it outside a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (!strcmp(cur->key, "duration_time")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) has_duration = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) strbuf_addf(events, "%s%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) no_group ? "{" : ",",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) (const char *)cur->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) no_group = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (!no_group) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) strbuf_addf(events, "}:W");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (has_duration)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) strbuf_addf(events, ",duration_time");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) } else if (has_duration)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) strbuf_addf(events, "duration_time");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) static void metricgroup__add_metric_non_group(struct strbuf *events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct expr_parse_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) struct hashmap_entry *cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) size_t bkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) bool first = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) hashmap__for_each_entry((&ctx->ids), cur, bkt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (!first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) strbuf_addf(events, ",");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) strbuf_addf(events, "%s", (const char *)cur->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) first = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static void metricgroup___watchdog_constraint_hint(const char *name, bool foot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static bool violate_nmi_constraint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (!foot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) pr_warning("Splitting metric group %s into standalone metrics.\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) violate_nmi_constraint = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (!violate_nmi_constraint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) pr_warning("Try disabling the NMI watchdog to comply NO_NMI_WATCHDOG metric constraint:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) " echo 0 > /proc/sys/kernel/nmi_watchdog\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) " perf stat ...\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) " echo 1 > /proc/sys/kernel/nmi_watchdog\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) static bool metricgroup__has_constraint(struct pmu_event *pe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (!pe->metric_constraint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (!strcmp(pe->metric_constraint, "NO_NMI_WATCHDOG") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) sysctl__nmi_watchdog_enabled()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) metricgroup___watchdog_constraint_hint(pe->metric_name, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) int __weak arch_get_runtimeparam(struct pmu_event *pe __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) static int __add_metric(struct list_head *metric_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) struct pmu_event *pe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) bool metric_no_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) int runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) struct metric **mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) struct expr_id *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) struct expr_ids *ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct metric_ref_node *ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) struct metric *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (*mp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * We got in here for the parent group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * allocate it and put it on the list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) m = zalloc(sizeof(*m));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (!m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) expr__ctx_init(&m->pctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) m->metric_name = pe->metric_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) m->metric_expr = pe->metric_expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) m->metric_unit = pe->unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) m->runtime = runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) m->has_constraint = metric_no_group || metricgroup__has_constraint(pe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) INIT_LIST_HEAD(&m->metric_refs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) m->metric_refs_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) parent = expr_ids__alloc(ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (!parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) free(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) parent->id = strdup(pe->metric_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (!parent->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) free(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) *mp = m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) * We got here for the referenced metric, via the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) * recursive metricgroup__add_metric call, add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) * it to the parent group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) m = *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) ref = malloc(sizeof(*ref));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (!ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * Intentionally passing just const char pointers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) * from 'pe' object, so they never go away. We don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) * need to change them, so there's no need to create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) * our own copy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) ref->metric_name = pe->metric_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) ref->metric_expr = pe->metric_expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) list_add(&ref->list, &m->metric_refs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) m->metric_refs_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) /* Force all found IDs in metric to have us as parent ID. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) WARN_ON_ONCE(!parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) m->pctx.parent = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * For both the parent and referenced metrics, we parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) * all the metric's IDs and add it to the parent context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (expr__find_other(pe->metric_expr, NULL, &m->pctx, runtime) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (m->metric_refs_cnt == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) expr__ctx_clear(&m->pctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) free(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) *mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * We add new group only in the 'parent' call,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) * so bail out for referenced metric case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (m->metric_refs_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (list_empty(metric_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) list_add(&m->nd, metric_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) struct list_head *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) /* Place the largest groups at the front. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) list_for_each_prev(pos, metric_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) struct metric *old = list_entry(pos, struct metric, nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (hashmap__size(&m->pctx.ids) <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) hashmap__size(&old->pctx.ids))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) list_add(&m->nd, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) #define map_for_each_event(__pe, __idx, __map) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) for (__idx = 0, __pe = &__map->table[__idx]; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) __pe->name || __pe->metric_group || __pe->metric_name; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) __pe = &__map->table[++__idx])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) #define map_for_each_metric(__pe, __idx, __map, __metric) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) map_for_each_event(__pe, __idx, __map) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (__pe->metric_expr && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) (match_metric(__pe->metric_group, __metric) || \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) match_metric(__pe->metric_name, __metric)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) static struct pmu_event *find_metric(const char *metric, struct pmu_events_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) struct pmu_event *pe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) map_for_each_event(pe, i, map) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (match_metric(pe->metric_name, metric))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) return pe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static int recursion_check(struct metric *m, const char *id, struct expr_id **parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) struct expr_ids *ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) struct expr_id_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) struct expr_id *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) * We get the parent referenced by 'id' argument and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * traverse through all the parent object IDs to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * if we already processed 'id', if we did, it's recursion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * and we fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) ret = expr__get_id(&m->pctx, id, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) p = data->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) while (p->parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (!strcmp(p->id, id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) pr_err("failed: recursion detected for %s\n", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) p = p->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * If we are over the limit of static entris, the metric
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * is too difficult/nested to process, fail as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) p = expr_ids__alloc(ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (!p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) pr_err("failed: too many nested metrics\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) p->id = strdup(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) p->parent = data->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) *parent = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) return p->id ? 0 : -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) static int add_metric(struct list_head *metric_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) struct pmu_event *pe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) bool metric_no_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) struct metric **mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) struct expr_id *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct expr_ids *ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) static int __resolve_metric(struct metric *m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) bool metric_no_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) struct list_head *metric_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) struct pmu_events_map *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct expr_ids *ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) struct hashmap_entry *cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) size_t bkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) bool all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) * Iterate all the parsed IDs and if there's metric,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) * add it to the context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) all = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) hashmap__for_each_entry((&m->pctx.ids), cur, bkt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) struct expr_id *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) struct pmu_event *pe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) pe = find_metric(cur->key, map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (!pe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) ret = recursion_check(m, cur->key, &parent, ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) all = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) /* The metric key itself needs to go out.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) expr__del_id(&m->pctx, cur->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) /* ... and it gets resolved to the parent context. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) ret = add_metric(metric_list, pe, metric_no_group, &m, parent, ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) * We added new metric to hashmap, so we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * to break the iteration and start over.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) } while (!all);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) static int resolve_metric(bool metric_no_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) struct list_head *metric_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) struct pmu_events_map *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) struct expr_ids *ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) struct metric *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) list_for_each_entry(m, metric_list, nd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) err = __resolve_metric(m, metric_no_group, metric_list, map, ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) static int add_metric(struct list_head *metric_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) struct pmu_event *pe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) bool metric_no_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) struct metric **m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct expr_id *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) struct expr_ids *ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct metric *orig = *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if (!strstr(pe->metric_expr, "?")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) ret = __add_metric(metric_list, pe, metric_no_group, 1, m, parent, ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) int j, count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) count = arch_get_runtimeparam(pe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) /* This loop is added to create multiple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) * events depend on count value and add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) * those events to metric_list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) for (j = 0; j < count && !ret; j++, *m = orig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) ret = __add_metric(metric_list, pe, metric_no_group, j, m, parent, ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) static int metricgroup__add_metric(const char *metric, bool metric_no_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) struct strbuf *events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) struct list_head *metric_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) struct pmu_events_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) struct expr_ids ids = { .cnt = 0, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) struct pmu_event *pe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) struct metric *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) LIST_HEAD(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) bool has_match = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) map_for_each_metric(pe, i, map, metric) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) has_match = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) m = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) ret = add_metric(&list, pe, metric_no_group, &m, NULL, &ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) * Process any possible referenced metrics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) * included in the expression.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) ret = resolve_metric(metric_no_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) &list, map, &ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) /* End of pmu events. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) if (!has_match) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) list_for_each_entry(m, &list, nd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (events->len > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) strbuf_addf(events, ",");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (m->has_constraint) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) metricgroup__add_metric_non_group(events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) &m->pctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) metricgroup__add_metric_weak_group(events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) &m->pctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) * add to metric_list so that they can be released
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) * even if it's failed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) list_splice(&list, metric_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) expr_ids__exit(&ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) static int metricgroup__add_metric_list(const char *list, bool metric_no_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) struct strbuf *events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) struct list_head *metric_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) struct pmu_events_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) char *llist, *nlist, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) nlist = strdup(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (!nlist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) llist = nlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) strbuf_init(events, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) strbuf_addf(events, "%s", "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) while ((p = strsep(&llist, ",")) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) ret = metricgroup__add_metric(p, metric_no_group, events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) metric_list, map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (ret == -EINVAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) fprintf(stderr, "Cannot find metric or group `%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) free(nlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) metricgroup___watchdog_constraint_hint(NULL, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) static void metric__free_refs(struct metric *metric)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) struct metric_ref_node *ref, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) list_for_each_entry_safe(ref, tmp, &metric->metric_refs, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) list_del(&ref->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) free(ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) static void metricgroup__free_metrics(struct list_head *metric_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) struct metric *m, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) list_for_each_entry_safe (m, tmp, metric_list, nd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) metric__free_refs(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) expr__ctx_clear(&m->pctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) list_del_init(&m->nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) free(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) static int parse_groups(struct evlist *perf_evlist, const char *str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) bool metric_no_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) bool metric_no_merge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) struct perf_pmu *fake_pmu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct rblist *metric_events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) struct pmu_events_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) struct parse_events_error parse_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) struct strbuf extra_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) LIST_HEAD(metric_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (metric_events->nr_entries == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) metricgroup__rblist_init(metric_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) ret = metricgroup__add_metric_list(str, metric_no_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) &extra_events, &metric_list, map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) pr_debug("adding %s\n", extra_events.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) bzero(&parse_error, sizeof(parse_error));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) ret = __parse_events(perf_evlist, extra_events.buf, &parse_error, fake_pmu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) parse_events_print_error(&parse_error, extra_events.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) ret = metricgroup__setup_events(&metric_list, metric_no_merge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) perf_evlist, metric_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) metricgroup__free_metrics(&metric_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) strbuf_release(&extra_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) int metricgroup__parse_groups(const struct option *opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) const char *str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) bool metric_no_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) bool metric_no_merge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) struct rblist *metric_events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) struct evlist *perf_evlist = *(struct evlist **)opt->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) struct pmu_events_map *map = perf_pmu__find_map(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (!map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) return parse_groups(perf_evlist, str, metric_no_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) metric_no_merge, NULL, metric_events, map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) int metricgroup__parse_groups_test(struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) struct pmu_events_map *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) const char *str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) bool metric_no_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) bool metric_no_merge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) struct rblist *metric_events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) return parse_groups(evlist, str, metric_no_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) metric_no_merge, &perf_pmu__fake, metric_events, map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) bool metricgroup__has_metric(const char *metric)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) struct pmu_events_map *map = perf_pmu__find_map(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) struct pmu_event *pe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (!map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) for (i = 0; ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) pe = &map->table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (!pe->name && !pe->metric_group && !pe->metric_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) if (!pe->metric_expr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) if (match_metric(pe->metric_name, metric))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) struct rblist *new_metric_events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) struct rblist *old_metric_events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) for (i = 0; i < rblist__nr_entries(old_metric_events); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) struct rb_node *nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) struct metric_event *old_me, *new_me;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) struct metric_expr *old_expr, *new_expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) size_t alloc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) int idx, nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) nd = rblist__entry(old_metric_events, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) old_me = container_of(nd, struct metric_event, nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) evsel = evlist__find_evsel(evlist, old_me->evsel->idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (!evsel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) new_me = metricgroup__lookup(new_metric_events, evsel, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) if (!new_me)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) pr_debug("copying metric event for cgroup '%s': %s (idx=%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) cgrp ? cgrp->name : "root", evsel->name, evsel->idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) list_for_each_entry(old_expr, &old_me->head, nd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) new_expr = malloc(sizeof(*new_expr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) if (!new_expr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) new_expr->metric_expr = old_expr->metric_expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) new_expr->metric_name = old_expr->metric_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) new_expr->metric_unit = old_expr->metric_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) new_expr->runtime = old_expr->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (old_expr->metric_refs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) /* calculate number of metric_events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) for (nr = 0; old_expr->metric_refs[nr].metric_name; nr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) alloc_size = sizeof(*new_expr->metric_refs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) new_expr->metric_refs = calloc(nr + 1, alloc_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (!new_expr->metric_refs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) free(new_expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) memcpy(new_expr->metric_refs, old_expr->metric_refs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) nr * alloc_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) new_expr->metric_refs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) /* calculate number of metric_events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) for (nr = 0; old_expr->metric_events[nr]; nr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) alloc_size = sizeof(*new_expr->metric_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) new_expr->metric_events = calloc(nr + 1, alloc_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) if (!new_expr->metric_events) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) free(new_expr->metric_refs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) free(new_expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) /* copy evsel in the same position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) for (idx = 0; idx < nr; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) evsel = old_expr->metric_events[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) evsel = evlist__find_evsel(evlist, evsel->idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if (evsel == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) free(new_expr->metric_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) free(new_expr->metric_refs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) free(new_expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) new_expr->metric_events[idx] = evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) list_add(&new_expr->nd, &new_me->head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) }