[PATCH 1/4] perf evsel: Add evsel__clone() function

From: Namhyung Kim
Date: Tue Sep 08 2020 - 00:42:56 EST


The evsel__clone() is to create an exactly same evsel from same
attributes. Note that metric events will be handled by later patch.

It will be used by perf stat to generate separate events for each
cgroup.

Signed-off-by: Namhyung Kim <namhyung@xxxxxxxxxx>
---
tools/perf/util/evsel.c | 57 +++++++++++++++++++++++++++++++++++++++++
tools/perf/util/evsel.h | 1 +
2 files changed, 58 insertions(+)

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index fd865002cbbd..4f50f9499973 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -331,6 +331,63 @@ struct evsel *evsel__new_cycles(bool precise)
goto out;
}

+/**
+ * evsel__clone - create a new evsel copied from @orig
+ * @orig: original evsel
+ *
+ * The assumption is that @orig is not configured nor opened yet.
+ * So we only care about the attributes that can be set while it's parsed.
+ */
+struct evsel *evsel__clone(struct evsel *orig)
+{
+ struct evsel *evsel;
+ struct evsel_config_term *pos, *tmp;
+
+ BUG_ON(orig->core.fd);
+
+ evsel = evsel__new(&orig->core.attr);
+ if (evsel == NULL)
+ return NULL;
+
+ *evsel = *orig;
+ evsel->evlist = NULL;
+ INIT_LIST_HEAD(&evsel->core.node);
+
+ evsel->core.cpus = perf_cpu_map__get(orig->core.cpus);
+ evsel->core.own_cpus = perf_cpu_map__get(orig->core.own_cpus);
+ evsel->core.threads = perf_thread_map__get(orig->core.threads);
+ if (orig->name)
+ evsel->name = strdup(orig->name);
+ if (orig->group_name)
+ evsel->group_name = strdup(orig->group_name);
+ if (orig->pmu_name)
+ evsel->pmu_name = strdup(orig->pmu_name);
+
+ INIT_LIST_HEAD(&evsel->config_terms);
+ list_for_each_entry(pos, &orig->config_terms, list) {
+ tmp = malloc(sizeof(*tmp));
+ if (tmp == NULL) {
+ evsel__delete(evsel);
+ evsel = NULL;
+ break;
+ }
+
+ *tmp = *pos;
+ if (tmp->free_str) {
+ tmp->val.str = strdup(pos->val.str);
+ if (tmp->val.str == NULL) {
+ evsel__delete(evsel);
+ evsel = NULL;
+ free(tmp);
+ break;
+ }
+ }
+ list_add_tail(&tmp->list, &evsel->config_terms);
+ }
+
+ return evsel;
+}
+
/*
* Returns pointer with encoded error via <linux/err.h> interface.
*/
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 35e3f6d66085..507c31d6a389 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -169,6 +169,7 @@ static inline struct evsel *evsel__new(struct perf_event_attr *attr)
return evsel__new_idx(attr, 0);
}

+struct evsel *evsel__clone(struct evsel *orig);
struct evsel *evsel__newtp_idx(const char *sys, const char *name, int idx);

/*
--
2.28.0.526.ge36021eeef-goog