0001
0002 #include <stdio.h>
0003 #include "util/pmu.h"
0004 #include "util/evlist.h"
0005 #include "util/parse-events.h"
0006 #include "util/event.h"
0007 #include "util/pmu-hybrid.h"
0008 #include "topdown.h"
0009
0010 static int ___evlist__add_default_attrs(struct evlist *evlist,
0011 struct perf_event_attr *attrs,
0012 size_t nr_attrs)
0013 {
0014 struct perf_cpu_map *cpus;
0015 struct evsel *evsel, *n;
0016 struct perf_pmu *pmu;
0017 LIST_HEAD(head);
0018 size_t i = 0;
0019
0020 for (i = 0; i < nr_attrs; i++)
0021 event_attr_init(attrs + i);
0022
0023 if (!perf_pmu__has_hybrid())
0024 return evlist__add_attrs(evlist, attrs, nr_attrs);
0025
0026 for (i = 0; i < nr_attrs; i++) {
0027 if (attrs[i].type == PERF_TYPE_SOFTWARE) {
0028 evsel = evsel__new(attrs + i);
0029 if (evsel == NULL)
0030 goto out_delete_partial_list;
0031 list_add_tail(&evsel->core.node, &head);
0032 continue;
0033 }
0034
0035 perf_pmu__for_each_hybrid_pmu(pmu) {
0036 evsel = evsel__new(attrs + i);
0037 if (evsel == NULL)
0038 goto out_delete_partial_list;
0039 evsel->core.attr.config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT;
0040 cpus = perf_cpu_map__get(pmu->cpus);
0041 evsel->core.cpus = cpus;
0042 evsel->core.own_cpus = perf_cpu_map__get(cpus);
0043 evsel->pmu_name = strdup(pmu->name);
0044 list_add_tail(&evsel->core.node, &head);
0045 }
0046 }
0047
0048 evlist__splice_list_tail(evlist, &head);
0049
0050 return 0;
0051
0052 out_delete_partial_list:
0053 __evlist__for_each_entry_safe(&head, n, evsel)
0054 evsel__delete(evsel);
0055 return -1;
0056 }
0057
0058 int arch_evlist__add_default_attrs(struct evlist *evlist,
0059 struct perf_event_attr *attrs,
0060 size_t nr_attrs)
0061 {
0062 if (nr_attrs)
0063 return ___evlist__add_default_attrs(evlist, attrs, nr_attrs);
0064
0065 return topdown_parse_events(evlist);
0066 }
0067
0068 struct evsel *arch_evlist__leader(struct list_head *list)
0069 {
0070 struct evsel *evsel, *first, *slots = NULL;
0071 bool has_topdown = false;
0072
0073 first = list_first_entry(list, struct evsel, core.node);
0074
0075 if (!topdown_sys_has_perf_metrics())
0076 return first;
0077
0078
0079 __evlist__for_each_entry(list, evsel) {
0080 if (evsel->pmu_name && !strncmp(evsel->pmu_name, "cpu", 3) && evsel->name) {
0081 if (strcasestr(evsel->name, "slots")) {
0082 slots = evsel;
0083 if (slots == first)
0084 return first;
0085 }
0086 if (strcasestr(evsel->name, "topdown"))
0087 has_topdown = true;
0088 if (slots && has_topdown)
0089 return slots;
0090 }
0091 }
0092 return first;
0093 }