Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
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     /* If there is a slots event and a topdown event then the slots event comes first. */
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 }