aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/tests/sw-clock.c18
-rw-r--r--tools/perf/tests/task-exit.c18
-rw-r--r--tools/perf/ui/browsers/hists.c12
-rw-r--r--tools/perf/util/evlist.c138
-rw-r--r--tools/perf/util/evlist.h9
-rw-r--r--tools/perf/util/evsel.c1
-rw-r--r--tools/perf/util/evsel.h1
-rw-r--r--tools/perf/util/header.c4
-rw-r--r--tools/perf/util/parse-events.c7
9 files changed, 126 insertions, 82 deletions
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 1aa21c90731b..5b83f56a3b6f 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -34,6 +34,8 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
34 .disabled = 1, 34 .disabled = 1,
35 .freq = 1, 35 .freq = 1,
36 }; 36 };
37 struct cpu_map *cpus;
38 struct thread_map *threads;
37 39
38 attr.sample_freq = 500; 40 attr.sample_freq = 500;
39 41
@@ -50,14 +52,19 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
50 } 52 }
51 perf_evlist__add(evlist, evsel); 53 perf_evlist__add(evlist, evsel);
52 54
53 evlist->cpus = cpu_map__dummy_new(); 55 cpus = cpu_map__dummy_new();
54 evlist->threads = thread_map__new_by_tid(getpid()); 56 threads = thread_map__new_by_tid(getpid());
55 if (!evlist->cpus || !evlist->threads) { 57 if (!cpus || !threads) {
56 err = -ENOMEM; 58 err = -ENOMEM;
57 pr_debug("Not enough memory to create thread/cpu maps\n"); 59 pr_debug("Not enough memory to create thread/cpu maps\n");
58 goto out_delete_evlist; 60 goto out_free_maps;
59 } 61 }
60 62
63 perf_evlist__set_maps(evlist, cpus, threads);
64
65 cpus = NULL;
66 threads = NULL;
67
61 if (perf_evlist__open(evlist)) { 68 if (perf_evlist__open(evlist)) {
62 const char *knob = "/proc/sys/kernel/perf_event_max_sample_rate"; 69 const char *knob = "/proc/sys/kernel/perf_event_max_sample_rate";
63 70
@@ -107,6 +114,9 @@ next_event:
107 err = -1; 114 err = -1;
108 } 115 }
109 116
117out_free_maps:
118 cpu_map__put(cpus);
119 thread_map__put(threads);
110out_delete_evlist: 120out_delete_evlist:
111 perf_evlist__delete(evlist); 121 perf_evlist__delete(evlist);
112 return err; 122 return err;
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 3a8fedef83bc..add16385f13e 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -43,6 +43,8 @@ int test__task_exit(void)
43 }; 43 };
44 const char *argv[] = { "true", NULL }; 44 const char *argv[] = { "true", NULL };
45 char sbuf[STRERR_BUFSIZE]; 45 char sbuf[STRERR_BUFSIZE];
46 struct cpu_map *cpus;
47 struct thread_map *threads;
46 48
47 signal(SIGCHLD, sig_handler); 49 signal(SIGCHLD, sig_handler);
48 50
@@ -58,14 +60,19 @@ int test__task_exit(void)
58 * perf_evlist__prepare_workload we'll fill in the only thread 60 * perf_evlist__prepare_workload we'll fill in the only thread
59 * we're monitoring, the one forked there. 61 * we're monitoring, the one forked there.
60 */ 62 */
61 evlist->cpus = cpu_map__dummy_new(); 63 cpus = cpu_map__dummy_new();
62 evlist->threads = thread_map__new_by_tid(-1); 64 threads = thread_map__new_by_tid(-1);
63 if (!evlist->cpus || !evlist->threads) { 65 if (!cpus || !threads) {
64 err = -ENOMEM; 66 err = -ENOMEM;
65 pr_debug("Not enough memory to create thread/cpu maps\n"); 67 pr_debug("Not enough memory to create thread/cpu maps\n");
66 goto out_delete_evlist; 68 goto out_free_maps;
67 } 69 }
68 70
71 perf_evlist__set_maps(evlist, cpus, threads);
72
73 cpus = NULL;
74 threads = NULL;
75
69 err = perf_evlist__prepare_workload(evlist, &target, argv, false, 76 err = perf_evlist__prepare_workload(evlist, &target, argv, false,
70 workload_exec_failed_signal); 77 workload_exec_failed_signal);
71 if (err < 0) { 78 if (err < 0) {
@@ -114,6 +121,9 @@ retry:
114 err = -1; 121 err = -1;
115 } 122 }
116 123
124out_free_maps:
125 cpu_map__put(cpus);
126 thread_map__put(threads);
117out_delete_evlist: 127out_delete_evlist:
118 perf_evlist__delete(evlist); 128 perf_evlist__delete(evlist);
119 return err; 129 return err;
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 380e9080991e..e1f28f4cdc8e 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -2017,7 +2017,8 @@ skip_annotation:
2017 &options[nr_options], dso); 2017 &options[nr_options], dso);
2018 nr_options += add_map_opt(browser, &actions[nr_options], 2018 nr_options += add_map_opt(browser, &actions[nr_options],
2019 &options[nr_options], 2019 &options[nr_options],
2020 browser->selection->map); 2020 browser->selection ?
2021 browser->selection->map : NULL);
2021 nr_options += add_socket_opt(browser, &actions[nr_options], 2022 nr_options += add_socket_opt(browser, &actions[nr_options],
2022 &options[nr_options], 2023 &options[nr_options],
2023 socked_id); 2024 socked_id);
@@ -2027,6 +2028,15 @@ skip_annotation:
2027 &actions[nr_options], 2028 &actions[nr_options],
2028 &options[nr_options], 2029 &options[nr_options],
2029 thread, NULL); 2030 thread, NULL);
2031 /*
2032 * Note that browser->selection != NULL
2033 * when browser->he_selection is not NULL,
2034 * so we don't need to check browser->selection
2035 * before fetching browser->selection->sym like what
2036 * we do before fetching browser->selection->map.
2037 *
2038 * See hist_browser__show_entry.
2039 */
2030 nr_options += add_script_opt(browser, 2040 nr_options += add_script_opt(browser,
2031 &actions[nr_options], 2041 &actions[nr_options],
2032 &options[nr_options], 2042 &options[nr_options],
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 3cb2bf9bd4bd..a8643735dcea 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -125,6 +125,33 @@ void perf_evlist__delete(struct perf_evlist *evlist)
125 free(evlist); 125 free(evlist);
126} 126}
127 127
128static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
129 struct perf_evsel *evsel)
130{
131 /*
132 * We already have cpus for evsel (via PMU sysfs) so
133 * keep it, if there's no target cpu list defined.
134 */
135 if (!evsel->own_cpus || evlist->has_user_cpus) {
136 cpu_map__put(evsel->cpus);
137 evsel->cpus = cpu_map__get(evlist->cpus);
138 } else if (evsel->cpus != evsel->own_cpus) {
139 cpu_map__put(evsel->cpus);
140 evsel->cpus = cpu_map__get(evsel->own_cpus);
141 }
142
143 thread_map__put(evsel->threads);
144 evsel->threads = thread_map__get(evlist->threads);
145}
146
147static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
148{
149 struct perf_evsel *evsel;
150
151 evlist__for_each(evlist, evsel)
152 __perf_evlist__propagate_maps(evlist, evsel);
153}
154
128void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) 155void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
129{ 156{
130 entry->evlist = evlist; 157 entry->evlist = evlist;
@@ -134,18 +161,19 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
134 161
135 if (!evlist->nr_entries++) 162 if (!evlist->nr_entries++)
136 perf_evlist__set_id_pos(evlist); 163 perf_evlist__set_id_pos(evlist);
164
165 __perf_evlist__propagate_maps(evlist, entry);
137} 166}
138 167
139void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 168void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
140 struct list_head *list, 169 struct list_head *list)
141 int nr_entries)
142{ 170{
143 bool set_id_pos = !evlist->nr_entries; 171 struct perf_evsel *evsel, *temp;
144 172
145 list_splice_tail(list, &evlist->entries); 173 __evlist__for_each_safe(list, temp, evsel) {
146 evlist->nr_entries += nr_entries; 174 list_del_init(&evsel->node);
147 if (set_id_pos) 175 perf_evlist__add(evlist, evsel);
148 perf_evlist__set_id_pos(evlist); 176 }
149} 177}
150 178
151void __perf_evlist__set_leader(struct list_head *list) 179void __perf_evlist__set_leader(struct list_head *list)
@@ -211,7 +239,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist,
211 list_add_tail(&evsel->node, &head); 239 list_add_tail(&evsel->node, &head);
212 } 240 }
213 241
214 perf_evlist__splice_list_tail(evlist, &head, nr_attrs); 242 perf_evlist__splice_list_tail(evlist, &head);
215 243
216 return 0; 244 return 0;
217 245
@@ -1104,71 +1132,56 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
1104 return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false); 1132 return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false);
1105} 1133}
1106 1134
1107static int perf_evlist__propagate_maps(struct perf_evlist *evlist,
1108 bool has_user_cpus)
1109{
1110 struct perf_evsel *evsel;
1111
1112 evlist__for_each(evlist, evsel) {
1113 /*
1114 * We already have cpus for evsel (via PMU sysfs) so
1115 * keep it, if there's no target cpu list defined.
1116 */
1117 if (evsel->cpus && has_user_cpus)
1118 cpu_map__put(evsel->cpus);
1119
1120 if (!evsel->cpus || has_user_cpus)
1121 evsel->cpus = cpu_map__get(evlist->cpus);
1122
1123 evsel->threads = thread_map__get(evlist->threads);
1124
1125 if ((evlist->cpus && !evsel->cpus) ||
1126 (evlist->threads && !evsel->threads))
1127 return -ENOMEM;
1128 }
1129
1130 return 0;
1131}
1132
1133int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) 1135int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
1134{ 1136{
1135 evlist->threads = thread_map__new_str(target->pid, target->tid, 1137 struct cpu_map *cpus;
1136 target->uid); 1138 struct thread_map *threads;
1139
1140 threads = thread_map__new_str(target->pid, target->tid, target->uid);
1137 1141
1138 if (evlist->threads == NULL) 1142 if (!threads)
1139 return -1; 1143 return -1;
1140 1144
1141 if (target__uses_dummy_map(target)) 1145 if (target__uses_dummy_map(target))
1142 evlist->cpus = cpu_map__dummy_new(); 1146 cpus = cpu_map__dummy_new();
1143 else 1147 else
1144 evlist->cpus = cpu_map__new(target->cpu_list); 1148 cpus = cpu_map__new(target->cpu_list);
1145 1149
1146 if (evlist->cpus == NULL) 1150 if (!cpus)
1147 goto out_delete_threads; 1151 goto out_delete_threads;
1148 1152
1149 return perf_evlist__propagate_maps(evlist, !!target->cpu_list); 1153 evlist->has_user_cpus = !!target->cpu_list;
1154
1155 perf_evlist__set_maps(evlist, cpus, threads);
1156
1157 return 0;
1150 1158
1151out_delete_threads: 1159out_delete_threads:
1152 thread_map__put(evlist->threads); 1160 thread_map__put(threads);
1153 evlist->threads = NULL;
1154 return -1; 1161 return -1;
1155} 1162}
1156 1163
1157int perf_evlist__set_maps(struct perf_evlist *evlist, 1164void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus,
1158 struct cpu_map *cpus, 1165 struct thread_map *threads)
1159 struct thread_map *threads)
1160{ 1166{
1161 if (evlist->cpus) 1167 /*
1168 * Allow for the possibility that one or another of the maps isn't being
1169 * changed i.e. don't put it. Note we are assuming the maps that are
1170 * being applied are brand new and evlist is taking ownership of the
1171 * original reference count of 1. If that is not the case it is up to
1172 * the caller to increase the reference count.
1173 */
1174 if (cpus != evlist->cpus) {
1162 cpu_map__put(evlist->cpus); 1175 cpu_map__put(evlist->cpus);
1176 evlist->cpus = cpus;
1177 }
1163 1178
1164 evlist->cpus = cpus; 1179 if (threads != evlist->threads) {
1165
1166 if (evlist->threads)
1167 thread_map__put(evlist->threads); 1180 thread_map__put(evlist->threads);
1181 evlist->threads = threads;
1182 }
1168 1183
1169 evlist->threads = threads; 1184 perf_evlist__propagate_maps(evlist);
1170
1171 return perf_evlist__propagate_maps(evlist, false);
1172} 1185}
1173 1186
1174int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel) 1187int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
@@ -1388,6 +1401,8 @@ void perf_evlist__close(struct perf_evlist *evlist)
1388 1401
1389static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) 1402static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist)
1390{ 1403{
1404 struct cpu_map *cpus;
1405 struct thread_map *threads;
1391 int err = -ENOMEM; 1406 int err = -ENOMEM;
1392 1407
1393 /* 1408 /*
@@ -1399,20 +1414,19 @@ static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist)
1399 * error, and we may not want to do that fallback to a 1414 * error, and we may not want to do that fallback to a
1400 * default cpu identity map :-\ 1415 * default cpu identity map :-\
1401 */ 1416 */
1402 evlist->cpus = cpu_map__new(NULL); 1417 cpus = cpu_map__new(NULL);
1403 if (evlist->cpus == NULL) 1418 if (!cpus)
1404 goto out; 1419 goto out;
1405 1420
1406 evlist->threads = thread_map__new_dummy(); 1421 threads = thread_map__new_dummy();
1407 if (evlist->threads == NULL) 1422 if (!threads)
1408 goto out_free_cpus; 1423 goto out_put;
1409 1424
1410 err = 0; 1425 perf_evlist__set_maps(evlist, cpus, threads);
1411out: 1426out:
1412 return err; 1427 return err;
1413out_free_cpus: 1428out_put:
1414 cpu_map__put(evlist->cpus); 1429 cpu_map__put(cpus);
1415 evlist->cpus = NULL;
1416 goto out; 1430 goto out;
1417} 1431}
1418 1432
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index b39a6198f4ac..115d8b53c601 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -42,6 +42,7 @@ struct perf_evlist {
42 int nr_mmaps; 42 int nr_mmaps;
43 bool overwrite; 43 bool overwrite;
44 bool enabled; 44 bool enabled;
45 bool has_user_cpus;
45 size_t mmap_len; 46 size_t mmap_len;
46 int id_pos; 47 int id_pos;
47 int is_pos; 48 int is_pos;
@@ -155,9 +156,8 @@ int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
155void perf_evlist__set_selected(struct perf_evlist *evlist, 156void perf_evlist__set_selected(struct perf_evlist *evlist,
156 struct perf_evsel *evsel); 157 struct perf_evsel *evsel);
157 158
158int perf_evlist__set_maps(struct perf_evlist *evlist, 159void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus,
159 struct cpu_map *cpus, 160 struct thread_map *threads);
160 struct thread_map *threads);
161int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); 161int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target);
162int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel); 162int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel);
163 163
@@ -179,8 +179,7 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist);
179bool perf_evlist__valid_read_format(struct perf_evlist *evlist); 179bool perf_evlist__valid_read_format(struct perf_evlist *evlist);
180 180
181void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 181void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
182 struct list_head *list, 182 struct list_head *list);
183 int nr_entries);
184 183
185static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist) 184static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist)
186{ 185{
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 6b5d1b509148..58890044d835 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1043,6 +1043,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)
1043 perf_evsel__free_config_terms(evsel); 1043 perf_evsel__free_config_terms(evsel);
1044 close_cgroup(evsel->cgrp); 1044 close_cgroup(evsel->cgrp);
1045 cpu_map__put(evsel->cpus); 1045 cpu_map__put(evsel->cpus);
1046 cpu_map__put(evsel->own_cpus);
1046 thread_map__put(evsel->threads); 1047 thread_map__put(evsel->threads);
1047 zfree(&evsel->group_name); 1048 zfree(&evsel->group_name);
1048 zfree(&evsel->name); 1049 zfree(&evsel->name);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 62ab307b7306..7906666580da 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -98,6 +98,7 @@ struct perf_evsel {
98 struct cgroup_sel *cgrp; 98 struct cgroup_sel *cgrp;
99 void *handler; 99 void *handler;
100 struct cpu_map *cpus; 100 struct cpu_map *cpus;
101 struct cpu_map *own_cpus;
101 struct thread_map *threads; 102 struct thread_map *threads;
102 unsigned int sample_size; 103 unsigned int sample_size;
103 int id_pos; 104 int id_pos;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 6d8fa543dcff..43838003c1a1 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1431,7 +1431,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,
1431 if (ph->needs_swap) 1431 if (ph->needs_swap)
1432 nr = bswap_32(nr); 1432 nr = bswap_32(nr);
1433 1433
1434 ph->env.nr_cpus_online = nr; 1434 ph->env.nr_cpus_avail = nr;
1435 1435
1436 ret = readn(fd, &nr, sizeof(nr)); 1436 ret = readn(fd, &nr, sizeof(nr));
1437 if (ret != sizeof(nr)) 1437 if (ret != sizeof(nr))
@@ -1440,7 +1440,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,
1440 if (ph->needs_swap) 1440 if (ph->needs_swap)
1441 nr = bswap_32(nr); 1441 nr = bswap_32(nr);
1442 1442
1443 ph->env.nr_cpus_avail = nr; 1443 ph->env.nr_cpus_online = nr;
1444 return 0; 1444 return 0;
1445} 1445}
1446 1446
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index d3fb90be6216..0fde5293a38e 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -288,8 +288,8 @@ __add_event(struct list_head *list, int *idx,
288 if (!evsel) 288 if (!evsel)
289 return NULL; 289 return NULL;
290 290
291 if (cpus) 291 evsel->cpus = cpu_map__get(cpus);
292 evsel->cpus = cpu_map__get(cpus); 292 evsel->own_cpus = cpu_map__get(cpus);
293 293
294 if (name) 294 if (name)
295 evsel->name = strdup(name); 295 evsel->name = strdup(name);
@@ -1174,10 +1174,9 @@ int parse_events(struct perf_evlist *evlist, const char *str,
1174 ret = parse_events__scanner(str, &data, PE_START_EVENTS); 1174 ret = parse_events__scanner(str, &data, PE_START_EVENTS);
1175 perf_pmu__parse_cleanup(); 1175 perf_pmu__parse_cleanup();
1176 if (!ret) { 1176 if (!ret) {
1177 int entries = data.idx - evlist->nr_entries;
1178 struct perf_evsel *last; 1177 struct perf_evsel *last;
1179 1178
1180 perf_evlist__splice_list_tail(evlist, &data.list, entries); 1179 perf_evlist__splice_list_tail(evlist, &data.list);
1181 evlist->nr_groups += data.nr_groups; 1180 evlist->nr_groups += data.nr_groups;
1182 last = perf_evlist__last(evlist); 1181 last = perf_evlist__last(evlist);
1183 last->cmdline_group_boundary = true; 1182 last->cmdline_group_boundary = true;