perf evsel: Add evsel__clone() function
The evsel__clone() is to create an exactly same evsel from same attributes. The function assumes the given evsel is not configured yet so it cares fields set during event parsing. Those fields are now moved together as Jiri suggested. 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@kernel.org> Acked-by: Jiri Olsa <jolsa@redhat.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lore.kernel.org/lkml/20200924124455.336326-2-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:

committed by
Arnaldo Carvalho de Melo

parent
b5ff7f2799
commit
7fedd9b84b
@@ -331,6 +331,110 @@ error_free:
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int evsel__copy_config_terms(struct evsel *dst, struct evsel *src)
|
||||
{
|
||||
struct evsel_config_term *pos, *tmp;
|
||||
|
||||
list_for_each_entry(pos, &src->config_terms, list) {
|
||||
tmp = malloc(sizeof(*tmp));
|
||||
if (tmp == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
*tmp = *pos;
|
||||
if (tmp->free_str) {
|
||||
tmp->val.str = strdup(pos->val.str);
|
||||
if (tmp->val.str == NULL) {
|
||||
free(tmp);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
list_add_tail(&tmp->list, &dst->config_terms);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
BUG_ON(orig->core.fd);
|
||||
BUG_ON(orig->counts);
|
||||
BUG_ON(orig->priv);
|
||||
BUG_ON(orig->per_pkg_mask);
|
||||
|
||||
/* cannot handle BPF objects for now */
|
||||
if (orig->bpf_obj)
|
||||
return NULL;
|
||||
|
||||
evsel = evsel__new(&orig->core.attr);
|
||||
if (evsel == NULL)
|
||||
return NULL;
|
||||
|
||||
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);
|
||||
evsel->core.nr_members = orig->core.nr_members;
|
||||
evsel->core.system_wide = orig->core.system_wide;
|
||||
|
||||
if (orig->name) {
|
||||
evsel->name = strdup(orig->name);
|
||||
if (evsel->name == NULL)
|
||||
goto out_err;
|
||||
}
|
||||
if (orig->group_name) {
|
||||
evsel->group_name = strdup(orig->group_name);
|
||||
if (evsel->group_name == NULL)
|
||||
goto out_err;
|
||||
}
|
||||
if (orig->pmu_name) {
|
||||
evsel->pmu_name = strdup(orig->pmu_name);
|
||||
if (evsel->pmu_name == NULL)
|
||||
goto out_err;
|
||||
}
|
||||
if (orig->filter) {
|
||||
evsel->filter = strdup(orig->filter);
|
||||
if (evsel->filter == NULL)
|
||||
goto out_err;
|
||||
}
|
||||
evsel->cgrp = cgroup__get(orig->cgrp);
|
||||
evsel->tp_format = orig->tp_format;
|
||||
evsel->handler = orig->handler;
|
||||
evsel->leader = orig->leader;
|
||||
|
||||
evsel->max_events = orig->max_events;
|
||||
evsel->tool_event = orig->tool_event;
|
||||
evsel->unit = orig->unit;
|
||||
evsel->scale = orig->scale;
|
||||
evsel->snapshot = orig->snapshot;
|
||||
evsel->per_pkg = orig->per_pkg;
|
||||
evsel->percore = orig->percore;
|
||||
evsel->precise_max = orig->precise_max;
|
||||
evsel->use_uncore_alias = orig->use_uncore_alias;
|
||||
evsel->is_libpfm_event = orig->is_libpfm_event;
|
||||
|
||||
evsel->exclude_GH = orig->exclude_GH;
|
||||
evsel->sample_read = orig->sample_read;
|
||||
evsel->auto_merge_stats = orig->auto_merge_stats;
|
||||
evsel->collect_stat = orig->collect_stat;
|
||||
evsel->weak_group = orig->weak_group;
|
||||
|
||||
if (evsel__copy_config_terms(evsel, orig) < 0)
|
||||
goto out_err;
|
||||
|
||||
return evsel;
|
||||
|
||||
out_err:
|
||||
evsel__delete(evsel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns pointer with encoded error via <linux/err.h> interface.
|
||||
*/
|
||||
|
Reference in New Issue
Block a user